|
fn strip_serde_derives(item: syn::MacroInput) -> (bool, bool, syn::MacroInput) { |
|
let mut ser = false; |
|
let mut de = false; |
|
let item = syn::MacroInput { |
|
attrs: item.attrs.into_iter().flat_map(|attr| { |
|
if attr.is_sugared_doc { |
|
return Some(attr); |
|
} |
|
let (name, nested) = match attr.value { |
|
syn::MetaItem::List(name, nested) => (name, nested), |
|
_ => return Some(attr) |
|
}; |
|
if name != "derive" { |
|
return Some(syn::Attribute { |
|
value: syn::MetaItem::List(name, nested), |
|
is_sugared_doc: false, |
|
}); |
|
} |
|
let rest: Vec<_> = nested.into_iter().filter(|nested| { |
|
match *nested { |
|
syn::MetaItem::Word(ref word) if word == "Serialize" => { |
|
ser = true; |
|
false |
|
} |
|
syn::MetaItem::Word(ref word) if word == "Deserialize" => { |
|
de = true; |
|
false |
|
} |
|
_ => true, |
|
} |
|
}).collect(); |
|
if rest.is_empty() { |
|
None |
|
} else { |
|
Some(syn::Attribute { |
|
value: syn::MetaItem::List(name, rest), |
|
is_sugared_doc: false, |
|
}) |
|
} |
|
}).collect(), |
|
..item |
|
}; |
|
(ser, de, item) |
|
} |
|
|
|
fn strip_serde_attrs(item: syn::MacroInput) -> syn::MacroInput { |
|
syn::MacroInput { |
|
attrs: strip_serde_from_attrs(item.attrs), |
|
body: match item.body { |
|
syn::Body::Enum(variants) => syn::Body::Enum( |
|
variants.into_iter().map(|variant| { |
|
syn::Variant { |
|
ident: variant.ident, |
|
attrs: strip_serde_from_attrs(variant.attrs), |
|
data: strip_serde_from_variant_data(variant.data), |
|
discriminant: variant.discriminant, |
|
} |
|
}).collect() |
|
), |
|
syn::Body::Struct(variant_data) => syn::Body::Struct( |
|
strip_serde_from_variant_data(variant_data) |
|
), |
|
}, |
|
..item |
|
} |
|
} |
|
|
|
fn strip_serde_from_variant_data(data: syn::VariantData) -> syn::VariantData { |
|
match data { |
|
syn::VariantData::Struct(fields) => syn::VariantData::Struct( |
|
fields.into_iter().map(strip_serde_from_field).collect() |
|
), |
|
syn::VariantData::Tuple(fields) => syn::VariantData::Tuple( |
|
fields.into_iter().map(strip_serde_from_field).collect() |
|
), |
|
syn::VariantData::Unit => syn::VariantData::Unit, |
|
} |
|
} |
|
|
|
fn strip_serde_from_field(field: syn::Field) -> syn::Field { |
|
syn::Field { |
|
attrs: strip_serde_from_attrs(field.attrs), |
|
..field |
|
} |
|
} |
|
|
|
fn strip_serde_from_attrs(attrs: Vec<syn::Attribute>) -> Vec<syn::Attribute> { |
|
attrs.into_iter().filter(|attr| { |
|
match attr.value { |
|
syn::MetaItem::List(ref ident, _) => ident != "serde", |
|
_ => true, |
|
} |
|
}).collect() |
|
} |
This stuff:
serde/serde_codegen/src/lib.rs
Lines 199 to 292 in 3a3777a
Here is how libsyntax does it: https://github.com/rust-lang/rust/blob/master/src/libsyntax/fold.rs