Skip to content

Commit d7e1fc0

Browse files
committed
Implement #[serde(bound = "...")]
1 parent 8148f2e commit d7e1fc0

File tree

4 files changed

+60
-33
lines changed

4 files changed

+60
-33
lines changed

src/trait_/deserialize.rs

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
use std::{borrow::Cow, ops::Deref};
44

55
use proc_macro2::{Span, TokenStream};
6-
use quote::quote;
6+
use quote::{format_ident, quote};
77
use syn::{
88
punctuated::Punctuated, Attribute, DeriveInput, Ident, ImplGenerics, Meta, Path, Result,
99
TypeGenerics, WhereClause,
1010
};
1111

1212
use super::serde;
13-
use crate::{util, DeriveTrait, Trait, TraitImpl, DERIVE_WHERE};
13+
use crate::{util, DeriveTrait, Trait, TraitImpl};
1414

1515
/// [`TraitImpl`] for [`Deserialize`](https://docs.rs/serde/latest/serde/derive.Deserialize.html).
1616
#[derive(Eq, PartialEq)]
@@ -48,7 +48,8 @@ impl TraitImpl for Deserialize {
4848
}
4949

5050
fn path(&self) -> Path {
51-
util::path_from_root_and_strs(self.crate_(), &["Deserialize"])
51+
let crate_ = self.crate_();
52+
syn::parse2::<Path>(quote! { #crate_::Deserialize<'de> }).unwrap()
5253
}
5354

5455
fn impl_item(
@@ -58,19 +59,16 @@ impl TraitImpl for Deserialize {
5859
_: &ImplGenerics<'_>,
5960
_: &Ident,
6061
_: &TypeGenerics<'_>,
61-
_: &Option<Cow<'_, WhereClause>>,
62+
where_clause: &Option<Cow<'_, WhereClause>>,
6263
_: TokenStream,
6364
) -> TokenStream {
64-
let derive_where = crate_
65-
.map(Cow::Borrowed)
66-
.unwrap_or_else(|| Cow::Owned(util::path_from_strs(&[DERIVE_WHERE])));
67-
let serde = self.crate_();
68-
69-
quote! {
70-
#[derive(#serde::Deserialize)]
71-
#[#derive_where::derive_where_serde]
72-
#full_item
73-
}
65+
serde::impl_item(
66+
crate_,
67+
&self.crate_(),
68+
format_ident!("Deserialize"),
69+
full_item,
70+
where_clause,
71+
)
7472
}
7573
}
7674

src/trait_/serde.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22
//! [`Deserialize`](https://docs.rs/serde/latest/serde/derive.Deserialize.html) and
33
//! [`Serialize`](https://docs.rs/serde/latest/serde/derive.Serialize.html).
44
5-
use proc_macro2::Span;
5+
use std::borrow::Cow;
6+
7+
use proc_macro2::{Span, TokenStream};
8+
use quote::{quote, ToTokens};
69
use syn::{
7-
punctuated::Punctuated, spanned::Spanned, Attribute, Expr, ExprLit, Lit, Meta, Path, Token,
10+
punctuated::Punctuated, spanned::Spanned, Attribute, DeriveInput, Expr, ExprLit, Ident, Lit,
11+
Meta, Path, Token, WhereClause,
812
};
913

10-
use crate::{Error, Result, Trait};
14+
use crate::{util, Error, Result, Trait, DERIVE_WHERE};
1115

12-
/// Parses
16+
/// Parse `#[serde(crate = "...")]`.
1317
pub fn parse_derive_trait(
1418
trait_: Trait,
1519
attrs: &[Attribute],
@@ -71,3 +75,29 @@ pub fn parse_derive_trait(
7175

7276
Ok(crate_)
7377
}
78+
79+
/// Implement Serde trait.
80+
pub fn impl_item(
81+
derive_where: Option<&Path>,
82+
serde: &Path,
83+
trait_: Ident,
84+
full_item: &DeriveInput,
85+
where_clause: &Option<Cow<'_, WhereClause>>,
86+
) -> TokenStream {
87+
let derive_where = derive_where
88+
.map(Cow::Borrowed)
89+
.unwrap_or_else(|| Cow::Owned(util::path_from_strs(&[DERIVE_WHERE])));
90+
91+
let bound = if let Some(where_clause) = where_clause {
92+
where_clause.predicates.to_token_stream().to_string()
93+
} else {
94+
String::new()
95+
};
96+
97+
quote! {
98+
#[::core::prelude::v1::derive(#serde::#trait_)]
99+
#[serde(bound = #bound)]
100+
#[#derive_where::derive_where_serde]
101+
#full_item
102+
}
103+
}

src/trait_/serialize.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
use std::{borrow::Cow, ops::Deref};
44

55
use proc_macro2::{Span, TokenStream};
6-
use quote::quote;
6+
use quote::format_ident;
77
use syn::{
88
punctuated::Punctuated, Attribute, DeriveInput, Ident, ImplGenerics, Meta, Path, Result,
99
TypeGenerics, WhereClause,
1010
};
1111

1212
use super::serde;
13-
use crate::{util, DeriveTrait, Trait, TraitImpl, DERIVE_WHERE};
13+
use crate::{util, DeriveTrait, Trait, TraitImpl};
1414

1515
/// [`TraitImpl`] for [`Serialize`](https://docs.rs/serde/latest/serde/derive.Serialize.html).
1616
#[derive(Eq, PartialEq)]
@@ -58,19 +58,16 @@ impl TraitImpl for Serialize {
5858
_: &ImplGenerics<'_>,
5959
_: &Ident,
6060
_: &TypeGenerics<'_>,
61-
_: &Option<Cow<'_, WhereClause>>,
61+
where_clause: &Option<Cow<'_, WhereClause>>,
6262
_: TokenStream,
6363
) -> TokenStream {
64-
let derive_where = crate_
65-
.map(Cow::Borrowed)
66-
.unwrap_or_else(|| Cow::Owned(util::path_from_strs(&[DERIVE_WHERE])));
67-
let serde = self.crate_();
68-
69-
quote! {
70-
#[::core::prelude::v1::derive(#serde::Serialize)]
71-
#[#derive_where::derive_where_serde]
72-
#full_item
73-
}
64+
serde::impl_item(
65+
crate_,
66+
&self.crate_(),
67+
format_ident!("Serialize"),
68+
full_item,
69+
where_clause,
70+
)
7471
}
7572
}
7673

tests/serde.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
#![cfg(feature = "serde")]
22

3+
use std::marker::PhantomData;
4+
35
use derive_where::derive_where;
46

57
#[test]
68
fn test() {
7-
#[derive_where(Deserialize, Serialize)]
9+
#[derive_where(Deserialize, Serialize; T)]
810
#[serde(crate = "serde_")]
9-
struct Test<T>(T);
11+
struct Test<T, U>(T, PhantomData<U>);
1012
}

0 commit comments

Comments
 (0)