17e2e9c0cSopenharmony_ciuse crate::internals::symbol::*; 27e2e9c0cSopenharmony_ciuse crate::internals::{ungroup, Ctxt}; 37e2e9c0cSopenharmony_ciuse proc_macro2::{Spacing, Span, TokenStream, TokenTree}; 47e2e9c0cSopenharmony_ciuse quote::ToTokens; 57e2e9c0cSopenharmony_ciuse std::borrow::Cow; 67e2e9c0cSopenharmony_ciuse std::collections::BTreeSet; 77e2e9c0cSopenharmony_ciuse std::iter::FromIterator; 87e2e9c0cSopenharmony_ciuse syn::meta::ParseNestedMeta; 97e2e9c0cSopenharmony_ciuse syn::parse::ParseStream; 107e2e9c0cSopenharmony_ciuse syn::punctuated::Punctuated; 117e2e9c0cSopenharmony_ciuse syn::{parse_quote, token, Ident, Lifetime, Token}; 127e2e9c0cSopenharmony_ci 137e2e9c0cSopenharmony_ci// This module handles parsing of `#[serde(...)]` attributes. The entrypoints 147e2e9c0cSopenharmony_ci// are `attr::Container::from_ast`, `attr::Variant::from_ast`, and 157e2e9c0cSopenharmony_ci// `attr::Field::from_ast`. Each returns an instance of the corresponding 167e2e9c0cSopenharmony_ci// struct. Note that none of them return a Result. Unrecognized, malformed, or 177e2e9c0cSopenharmony_ci// duplicated attributes result in a span_err but otherwise are ignored. The 187e2e9c0cSopenharmony_ci// user will see errors simultaneously for all bad attributes in the crate 197e2e9c0cSopenharmony_ci// rather than just the first. 207e2e9c0cSopenharmony_ci 217e2e9c0cSopenharmony_cipub use crate::internals::case::RenameRule; 227e2e9c0cSopenharmony_ci 237e2e9c0cSopenharmony_cistruct Attr<'c, T> { 247e2e9c0cSopenharmony_ci cx: &'c Ctxt, 257e2e9c0cSopenharmony_ci name: Symbol, 267e2e9c0cSopenharmony_ci tokens: TokenStream, 277e2e9c0cSopenharmony_ci value: Option<T>, 287e2e9c0cSopenharmony_ci} 297e2e9c0cSopenharmony_ci 307e2e9c0cSopenharmony_ciimpl<'c, T> Attr<'c, T> { 317e2e9c0cSopenharmony_ci fn none(cx: &'c Ctxt, name: Symbol) -> Self { 327e2e9c0cSopenharmony_ci Attr { 337e2e9c0cSopenharmony_ci cx, 347e2e9c0cSopenharmony_ci name, 357e2e9c0cSopenharmony_ci tokens: TokenStream::new(), 367e2e9c0cSopenharmony_ci value: None, 377e2e9c0cSopenharmony_ci } 387e2e9c0cSopenharmony_ci } 397e2e9c0cSopenharmony_ci 407e2e9c0cSopenharmony_ci fn set<A: ToTokens>(&mut self, obj: A, value: T) { 417e2e9c0cSopenharmony_ci let tokens = obj.into_token_stream(); 427e2e9c0cSopenharmony_ci 437e2e9c0cSopenharmony_ci if self.value.is_some() { 447e2e9c0cSopenharmony_ci let msg = format!("duplicate serde attribute `{}`", self.name); 457e2e9c0cSopenharmony_ci self.cx.error_spanned_by(tokens, msg); 467e2e9c0cSopenharmony_ci } else { 477e2e9c0cSopenharmony_ci self.tokens = tokens; 487e2e9c0cSopenharmony_ci self.value = Some(value); 497e2e9c0cSopenharmony_ci } 507e2e9c0cSopenharmony_ci } 517e2e9c0cSopenharmony_ci 527e2e9c0cSopenharmony_ci fn set_opt<A: ToTokens>(&mut self, obj: A, value: Option<T>) { 537e2e9c0cSopenharmony_ci if let Some(value) = value { 547e2e9c0cSopenharmony_ci self.set(obj, value); 557e2e9c0cSopenharmony_ci } 567e2e9c0cSopenharmony_ci } 577e2e9c0cSopenharmony_ci 587e2e9c0cSopenharmony_ci fn set_if_none(&mut self, value: T) { 597e2e9c0cSopenharmony_ci if self.value.is_none() { 607e2e9c0cSopenharmony_ci self.value = Some(value); 617e2e9c0cSopenharmony_ci } 627e2e9c0cSopenharmony_ci } 637e2e9c0cSopenharmony_ci 647e2e9c0cSopenharmony_ci fn get(self) -> Option<T> { 657e2e9c0cSopenharmony_ci self.value 667e2e9c0cSopenharmony_ci } 677e2e9c0cSopenharmony_ci 687e2e9c0cSopenharmony_ci fn get_with_tokens(self) -> Option<(TokenStream, T)> { 697e2e9c0cSopenharmony_ci match self.value { 707e2e9c0cSopenharmony_ci Some(v) => Some((self.tokens, v)), 717e2e9c0cSopenharmony_ci None => None, 727e2e9c0cSopenharmony_ci } 737e2e9c0cSopenharmony_ci } 747e2e9c0cSopenharmony_ci} 757e2e9c0cSopenharmony_ci 767e2e9c0cSopenharmony_cistruct BoolAttr<'c>(Attr<'c, ()>); 777e2e9c0cSopenharmony_ci 787e2e9c0cSopenharmony_ciimpl<'c> BoolAttr<'c> { 797e2e9c0cSopenharmony_ci fn none(cx: &'c Ctxt, name: Symbol) -> Self { 807e2e9c0cSopenharmony_ci BoolAttr(Attr::none(cx, name)) 817e2e9c0cSopenharmony_ci } 827e2e9c0cSopenharmony_ci 837e2e9c0cSopenharmony_ci fn set_true<A: ToTokens>(&mut self, obj: A) { 847e2e9c0cSopenharmony_ci self.0.set(obj, ()); 857e2e9c0cSopenharmony_ci } 867e2e9c0cSopenharmony_ci 877e2e9c0cSopenharmony_ci fn get(&self) -> bool { 887e2e9c0cSopenharmony_ci self.0.value.is_some() 897e2e9c0cSopenharmony_ci } 907e2e9c0cSopenharmony_ci} 917e2e9c0cSopenharmony_ci 927e2e9c0cSopenharmony_cistruct VecAttr<'c, T> { 937e2e9c0cSopenharmony_ci cx: &'c Ctxt, 947e2e9c0cSopenharmony_ci name: Symbol, 957e2e9c0cSopenharmony_ci first_dup_tokens: TokenStream, 967e2e9c0cSopenharmony_ci values: Vec<T>, 977e2e9c0cSopenharmony_ci} 987e2e9c0cSopenharmony_ci 997e2e9c0cSopenharmony_ciimpl<'c, T> VecAttr<'c, T> { 1007e2e9c0cSopenharmony_ci fn none(cx: &'c Ctxt, name: Symbol) -> Self { 1017e2e9c0cSopenharmony_ci VecAttr { 1027e2e9c0cSopenharmony_ci cx, 1037e2e9c0cSopenharmony_ci name, 1047e2e9c0cSopenharmony_ci first_dup_tokens: TokenStream::new(), 1057e2e9c0cSopenharmony_ci values: Vec::new(), 1067e2e9c0cSopenharmony_ci } 1077e2e9c0cSopenharmony_ci } 1087e2e9c0cSopenharmony_ci 1097e2e9c0cSopenharmony_ci fn insert<A: ToTokens>(&mut self, obj: A, value: T) { 1107e2e9c0cSopenharmony_ci if self.values.len() == 1 { 1117e2e9c0cSopenharmony_ci self.first_dup_tokens = obj.into_token_stream(); 1127e2e9c0cSopenharmony_ci } 1137e2e9c0cSopenharmony_ci self.values.push(value); 1147e2e9c0cSopenharmony_ci } 1157e2e9c0cSopenharmony_ci 1167e2e9c0cSopenharmony_ci fn at_most_one(mut self) -> Option<T> { 1177e2e9c0cSopenharmony_ci if self.values.len() > 1 { 1187e2e9c0cSopenharmony_ci let dup_token = self.first_dup_tokens; 1197e2e9c0cSopenharmony_ci let msg = format!("duplicate serde attribute `{}`", self.name); 1207e2e9c0cSopenharmony_ci self.cx.error_spanned_by(dup_token, msg); 1217e2e9c0cSopenharmony_ci None 1227e2e9c0cSopenharmony_ci } else { 1237e2e9c0cSopenharmony_ci self.values.pop() 1247e2e9c0cSopenharmony_ci } 1257e2e9c0cSopenharmony_ci } 1267e2e9c0cSopenharmony_ci 1277e2e9c0cSopenharmony_ci fn get(self) -> Vec<T> { 1287e2e9c0cSopenharmony_ci self.values 1297e2e9c0cSopenharmony_ci } 1307e2e9c0cSopenharmony_ci} 1317e2e9c0cSopenharmony_ci 1327e2e9c0cSopenharmony_cipub struct Name { 1337e2e9c0cSopenharmony_ci serialize: String, 1347e2e9c0cSopenharmony_ci serialize_renamed: bool, 1357e2e9c0cSopenharmony_ci deserialize: String, 1367e2e9c0cSopenharmony_ci deserialize_renamed: bool, 1377e2e9c0cSopenharmony_ci deserialize_aliases: BTreeSet<String>, 1387e2e9c0cSopenharmony_ci} 1397e2e9c0cSopenharmony_ci 1407e2e9c0cSopenharmony_cifn unraw(ident: &Ident) -> String { 1417e2e9c0cSopenharmony_ci ident.to_string().trim_start_matches("r#").to_owned() 1427e2e9c0cSopenharmony_ci} 1437e2e9c0cSopenharmony_ci 1447e2e9c0cSopenharmony_ciimpl Name { 1457e2e9c0cSopenharmony_ci fn from_attrs( 1467e2e9c0cSopenharmony_ci source_name: String, 1477e2e9c0cSopenharmony_ci ser_name: Attr<String>, 1487e2e9c0cSopenharmony_ci de_name: Attr<String>, 1497e2e9c0cSopenharmony_ci de_aliases: Option<VecAttr<String>>, 1507e2e9c0cSopenharmony_ci ) -> Name { 1517e2e9c0cSopenharmony_ci let mut alias_set = BTreeSet::new(); 1527e2e9c0cSopenharmony_ci if let Some(de_aliases) = de_aliases { 1537e2e9c0cSopenharmony_ci for alias_name in de_aliases.get() { 1547e2e9c0cSopenharmony_ci alias_set.insert(alias_name); 1557e2e9c0cSopenharmony_ci } 1567e2e9c0cSopenharmony_ci } 1577e2e9c0cSopenharmony_ci 1587e2e9c0cSopenharmony_ci let ser_name = ser_name.get(); 1597e2e9c0cSopenharmony_ci let ser_renamed = ser_name.is_some(); 1607e2e9c0cSopenharmony_ci let de_name = de_name.get(); 1617e2e9c0cSopenharmony_ci let de_renamed = de_name.is_some(); 1627e2e9c0cSopenharmony_ci Name { 1637e2e9c0cSopenharmony_ci serialize: ser_name.unwrap_or_else(|| source_name.clone()), 1647e2e9c0cSopenharmony_ci serialize_renamed: ser_renamed, 1657e2e9c0cSopenharmony_ci deserialize: de_name.unwrap_or(source_name), 1667e2e9c0cSopenharmony_ci deserialize_renamed: de_renamed, 1677e2e9c0cSopenharmony_ci deserialize_aliases: alias_set, 1687e2e9c0cSopenharmony_ci } 1697e2e9c0cSopenharmony_ci } 1707e2e9c0cSopenharmony_ci 1717e2e9c0cSopenharmony_ci /// Return the container name for the container when serializing. 1727e2e9c0cSopenharmony_ci pub fn serialize_name(&self) -> &str { 1737e2e9c0cSopenharmony_ci &self.serialize 1747e2e9c0cSopenharmony_ci } 1757e2e9c0cSopenharmony_ci 1767e2e9c0cSopenharmony_ci /// Return the container name for the container when deserializing. 1777e2e9c0cSopenharmony_ci pub fn deserialize_name(&self) -> &str { 1787e2e9c0cSopenharmony_ci &self.deserialize 1797e2e9c0cSopenharmony_ci } 1807e2e9c0cSopenharmony_ci 1817e2e9c0cSopenharmony_ci fn deserialize_aliases(&self) -> &BTreeSet<String> { 1827e2e9c0cSopenharmony_ci &self.deserialize_aliases 1837e2e9c0cSopenharmony_ci } 1847e2e9c0cSopenharmony_ci} 1857e2e9c0cSopenharmony_ci 1867e2e9c0cSopenharmony_ci#[derive(Copy, Clone)] 1877e2e9c0cSopenharmony_cipub struct RenameAllRules { 1887e2e9c0cSopenharmony_ci serialize: RenameRule, 1897e2e9c0cSopenharmony_ci deserialize: RenameRule, 1907e2e9c0cSopenharmony_ci} 1917e2e9c0cSopenharmony_ci 1927e2e9c0cSopenharmony_ciimpl RenameAllRules { 1937e2e9c0cSopenharmony_ci /// Returns a new `RenameAllRules` with the individual rules of `self` and 1947e2e9c0cSopenharmony_ci /// `other_rules` joined by `RenameRules::or`. 1957e2e9c0cSopenharmony_ci pub fn or(self, other_rules: Self) -> Self { 1967e2e9c0cSopenharmony_ci Self { 1977e2e9c0cSopenharmony_ci serialize: self.serialize.or(other_rules.serialize), 1987e2e9c0cSopenharmony_ci deserialize: self.deserialize.or(other_rules.deserialize), 1997e2e9c0cSopenharmony_ci } 2007e2e9c0cSopenharmony_ci } 2017e2e9c0cSopenharmony_ci} 2027e2e9c0cSopenharmony_ci 2037e2e9c0cSopenharmony_ci/// Represents struct or enum attribute information. 2047e2e9c0cSopenharmony_cipub struct Container { 2057e2e9c0cSopenharmony_ci name: Name, 2067e2e9c0cSopenharmony_ci transparent: bool, 2077e2e9c0cSopenharmony_ci deny_unknown_fields: bool, 2087e2e9c0cSopenharmony_ci default: Default, 2097e2e9c0cSopenharmony_ci rename_all_rules: RenameAllRules, 2107e2e9c0cSopenharmony_ci rename_all_fields_rules: RenameAllRules, 2117e2e9c0cSopenharmony_ci ser_bound: Option<Vec<syn::WherePredicate>>, 2127e2e9c0cSopenharmony_ci de_bound: Option<Vec<syn::WherePredicate>>, 2137e2e9c0cSopenharmony_ci tag: TagType, 2147e2e9c0cSopenharmony_ci type_from: Option<syn::Type>, 2157e2e9c0cSopenharmony_ci type_try_from: Option<syn::Type>, 2167e2e9c0cSopenharmony_ci type_into: Option<syn::Type>, 2177e2e9c0cSopenharmony_ci remote: Option<syn::Path>, 2187e2e9c0cSopenharmony_ci identifier: Identifier, 2197e2e9c0cSopenharmony_ci has_flatten: bool, 2207e2e9c0cSopenharmony_ci serde_path: Option<syn::Path>, 2217e2e9c0cSopenharmony_ci is_packed: bool, 2227e2e9c0cSopenharmony_ci /// Error message generated when type can't be deserialized 2237e2e9c0cSopenharmony_ci expecting: Option<String>, 2247e2e9c0cSopenharmony_ci non_exhaustive: bool, 2257e2e9c0cSopenharmony_ci} 2267e2e9c0cSopenharmony_ci 2277e2e9c0cSopenharmony_ci/// Styles of representing an enum. 2287e2e9c0cSopenharmony_cipub enum TagType { 2297e2e9c0cSopenharmony_ci /// The default. 2307e2e9c0cSopenharmony_ci /// 2317e2e9c0cSopenharmony_ci /// ```json 2327e2e9c0cSopenharmony_ci /// {"variant1": {"key1": "value1", "key2": "value2"}} 2337e2e9c0cSopenharmony_ci /// ``` 2347e2e9c0cSopenharmony_ci External, 2357e2e9c0cSopenharmony_ci 2367e2e9c0cSopenharmony_ci /// `#[serde(tag = "type")]` 2377e2e9c0cSopenharmony_ci /// 2387e2e9c0cSopenharmony_ci /// ```json 2397e2e9c0cSopenharmony_ci /// {"type": "variant1", "key1": "value1", "key2": "value2"} 2407e2e9c0cSopenharmony_ci /// ``` 2417e2e9c0cSopenharmony_ci Internal { tag: String }, 2427e2e9c0cSopenharmony_ci 2437e2e9c0cSopenharmony_ci /// `#[serde(tag = "t", content = "c")]` 2447e2e9c0cSopenharmony_ci /// 2457e2e9c0cSopenharmony_ci /// ```json 2467e2e9c0cSopenharmony_ci /// {"t": "variant1", "c": {"key1": "value1", "key2": "value2"}} 2477e2e9c0cSopenharmony_ci /// ``` 2487e2e9c0cSopenharmony_ci Adjacent { tag: String, content: String }, 2497e2e9c0cSopenharmony_ci 2507e2e9c0cSopenharmony_ci /// `#[serde(untagged)]` 2517e2e9c0cSopenharmony_ci /// 2527e2e9c0cSopenharmony_ci /// ```json 2537e2e9c0cSopenharmony_ci /// {"key1": "value1", "key2": "value2"} 2547e2e9c0cSopenharmony_ci /// ``` 2557e2e9c0cSopenharmony_ci None, 2567e2e9c0cSopenharmony_ci} 2577e2e9c0cSopenharmony_ci 2587e2e9c0cSopenharmony_ci/// Whether this enum represents the fields of a struct or the variants of an 2597e2e9c0cSopenharmony_ci/// enum. 2607e2e9c0cSopenharmony_ci#[derive(Copy, Clone)] 2617e2e9c0cSopenharmony_cipub enum Identifier { 2627e2e9c0cSopenharmony_ci /// It does not. 2637e2e9c0cSopenharmony_ci No, 2647e2e9c0cSopenharmony_ci 2657e2e9c0cSopenharmony_ci /// This enum represents the fields of a struct. All of the variants must be 2667e2e9c0cSopenharmony_ci /// unit variants, except possibly one which is annotated with 2677e2e9c0cSopenharmony_ci /// `#[serde(other)]` and is a newtype variant. 2687e2e9c0cSopenharmony_ci Field, 2697e2e9c0cSopenharmony_ci 2707e2e9c0cSopenharmony_ci /// This enum represents the variants of an enum. All of the variants must 2717e2e9c0cSopenharmony_ci /// be unit variants. 2727e2e9c0cSopenharmony_ci Variant, 2737e2e9c0cSopenharmony_ci} 2747e2e9c0cSopenharmony_ci 2757e2e9c0cSopenharmony_ciimpl Identifier { 2767e2e9c0cSopenharmony_ci #[cfg(feature = "deserialize_in_place")] 2777e2e9c0cSopenharmony_ci pub fn is_some(self) -> bool { 2787e2e9c0cSopenharmony_ci match self { 2797e2e9c0cSopenharmony_ci Identifier::No => false, 2807e2e9c0cSopenharmony_ci Identifier::Field | Identifier::Variant => true, 2817e2e9c0cSopenharmony_ci } 2827e2e9c0cSopenharmony_ci } 2837e2e9c0cSopenharmony_ci} 2847e2e9c0cSopenharmony_ci 2857e2e9c0cSopenharmony_ciimpl Container { 2867e2e9c0cSopenharmony_ci /// Extract out the `#[serde(...)]` attributes from an item. 2877e2e9c0cSopenharmony_ci pub fn from_ast(cx: &Ctxt, item: &syn::DeriveInput) -> Self { 2887e2e9c0cSopenharmony_ci let mut ser_name = Attr::none(cx, RENAME); 2897e2e9c0cSopenharmony_ci let mut de_name = Attr::none(cx, RENAME); 2907e2e9c0cSopenharmony_ci let mut transparent = BoolAttr::none(cx, TRANSPARENT); 2917e2e9c0cSopenharmony_ci let mut deny_unknown_fields = BoolAttr::none(cx, DENY_UNKNOWN_FIELDS); 2927e2e9c0cSopenharmony_ci let mut default = Attr::none(cx, DEFAULT); 2937e2e9c0cSopenharmony_ci let mut rename_all_ser_rule = Attr::none(cx, RENAME_ALL); 2947e2e9c0cSopenharmony_ci let mut rename_all_de_rule = Attr::none(cx, RENAME_ALL); 2957e2e9c0cSopenharmony_ci let mut rename_all_fields_ser_rule = Attr::none(cx, RENAME_ALL_FIELDS); 2967e2e9c0cSopenharmony_ci let mut rename_all_fields_de_rule = Attr::none(cx, RENAME_ALL_FIELDS); 2977e2e9c0cSopenharmony_ci let mut ser_bound = Attr::none(cx, BOUND); 2987e2e9c0cSopenharmony_ci let mut de_bound = Attr::none(cx, BOUND); 2997e2e9c0cSopenharmony_ci let mut untagged = BoolAttr::none(cx, UNTAGGED); 3007e2e9c0cSopenharmony_ci let mut internal_tag = Attr::none(cx, TAG); 3017e2e9c0cSopenharmony_ci let mut content = Attr::none(cx, CONTENT); 3027e2e9c0cSopenharmony_ci let mut type_from = Attr::none(cx, FROM); 3037e2e9c0cSopenharmony_ci let mut type_try_from = Attr::none(cx, TRY_FROM); 3047e2e9c0cSopenharmony_ci let mut type_into = Attr::none(cx, INTO); 3057e2e9c0cSopenharmony_ci let mut remote = Attr::none(cx, REMOTE); 3067e2e9c0cSopenharmony_ci let mut field_identifier = BoolAttr::none(cx, FIELD_IDENTIFIER); 3077e2e9c0cSopenharmony_ci let mut variant_identifier = BoolAttr::none(cx, VARIANT_IDENTIFIER); 3087e2e9c0cSopenharmony_ci let mut serde_path = Attr::none(cx, CRATE); 3097e2e9c0cSopenharmony_ci let mut expecting = Attr::none(cx, EXPECTING); 3107e2e9c0cSopenharmony_ci let mut non_exhaustive = false; 3117e2e9c0cSopenharmony_ci 3127e2e9c0cSopenharmony_ci for attr in &item.attrs { 3137e2e9c0cSopenharmony_ci if attr.path() != SERDE { 3147e2e9c0cSopenharmony_ci non_exhaustive |= 3157e2e9c0cSopenharmony_ci matches!(&attr.meta, syn::Meta::Path(path) if path == NON_EXHAUSTIVE); 3167e2e9c0cSopenharmony_ci continue; 3177e2e9c0cSopenharmony_ci } 3187e2e9c0cSopenharmony_ci 3197e2e9c0cSopenharmony_ci if let syn::Meta::List(meta) = &attr.meta { 3207e2e9c0cSopenharmony_ci if meta.tokens.is_empty() { 3217e2e9c0cSopenharmony_ci continue; 3227e2e9c0cSopenharmony_ci } 3237e2e9c0cSopenharmony_ci } 3247e2e9c0cSopenharmony_ci 3257e2e9c0cSopenharmony_ci if let Err(err) = attr.parse_nested_meta(|meta| { 3267e2e9c0cSopenharmony_ci if meta.path == RENAME { 3277e2e9c0cSopenharmony_ci // #[serde(rename = "foo")] 3287e2e9c0cSopenharmony_ci // #[serde(rename(serialize = "foo", deserialize = "bar"))] 3297e2e9c0cSopenharmony_ci let (ser, de) = get_renames(cx, RENAME, &meta)?; 3307e2e9c0cSopenharmony_ci ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value)); 3317e2e9c0cSopenharmony_ci de_name.set_opt(&meta.path, de.as_ref().map(syn::LitStr::value)); 3327e2e9c0cSopenharmony_ci } else if meta.path == RENAME_ALL { 3337e2e9c0cSopenharmony_ci // #[serde(rename_all = "foo")] 3347e2e9c0cSopenharmony_ci // #[serde(rename_all(serialize = "foo", deserialize = "bar"))] 3357e2e9c0cSopenharmony_ci let one_name = meta.input.peek(Token![=]); 3367e2e9c0cSopenharmony_ci let (ser, de) = get_renames(cx, RENAME_ALL, &meta)?; 3377e2e9c0cSopenharmony_ci if let Some(ser) = ser { 3387e2e9c0cSopenharmony_ci match RenameRule::from_str(&ser.value()) { 3397e2e9c0cSopenharmony_ci Ok(rename_rule) => rename_all_ser_rule.set(&meta.path, rename_rule), 3407e2e9c0cSopenharmony_ci Err(err) => cx.error_spanned_by(ser, err), 3417e2e9c0cSopenharmony_ci } 3427e2e9c0cSopenharmony_ci } 3437e2e9c0cSopenharmony_ci if let Some(de) = de { 3447e2e9c0cSopenharmony_ci match RenameRule::from_str(&de.value()) { 3457e2e9c0cSopenharmony_ci Ok(rename_rule) => rename_all_de_rule.set(&meta.path, rename_rule), 3467e2e9c0cSopenharmony_ci Err(err) => { 3477e2e9c0cSopenharmony_ci if !one_name { 3487e2e9c0cSopenharmony_ci cx.error_spanned_by(de, err); 3497e2e9c0cSopenharmony_ci } 3507e2e9c0cSopenharmony_ci } 3517e2e9c0cSopenharmony_ci } 3527e2e9c0cSopenharmony_ci } 3537e2e9c0cSopenharmony_ci } else if meta.path == RENAME_ALL_FIELDS { 3547e2e9c0cSopenharmony_ci // #[serde(rename_all_fields = "foo")] 3557e2e9c0cSopenharmony_ci // #[serde(rename_all_fields(serialize = "foo", deserialize = "bar"))] 3567e2e9c0cSopenharmony_ci let one_name = meta.input.peek(Token![=]); 3577e2e9c0cSopenharmony_ci let (ser, de) = get_renames(cx, RENAME_ALL_FIELDS, &meta)?; 3587e2e9c0cSopenharmony_ci 3597e2e9c0cSopenharmony_ci match item.data { 3607e2e9c0cSopenharmony_ci syn::Data::Enum(_) => { 3617e2e9c0cSopenharmony_ci if let Some(ser) = ser { 3627e2e9c0cSopenharmony_ci match RenameRule::from_str(&ser.value()) { 3637e2e9c0cSopenharmony_ci Ok(rename_rule) => { 3647e2e9c0cSopenharmony_ci rename_all_fields_ser_rule.set(&meta.path, rename_rule); 3657e2e9c0cSopenharmony_ci } 3667e2e9c0cSopenharmony_ci Err(err) => cx.error_spanned_by(ser, err), 3677e2e9c0cSopenharmony_ci } 3687e2e9c0cSopenharmony_ci } 3697e2e9c0cSopenharmony_ci if let Some(de) = de { 3707e2e9c0cSopenharmony_ci match RenameRule::from_str(&de.value()) { 3717e2e9c0cSopenharmony_ci Ok(rename_rule) => { 3727e2e9c0cSopenharmony_ci rename_all_fields_de_rule.set(&meta.path, rename_rule); 3737e2e9c0cSopenharmony_ci } 3747e2e9c0cSopenharmony_ci Err(err) => { 3757e2e9c0cSopenharmony_ci if !one_name { 3767e2e9c0cSopenharmony_ci cx.error_spanned_by(de, err); 3777e2e9c0cSopenharmony_ci } 3787e2e9c0cSopenharmony_ci } 3797e2e9c0cSopenharmony_ci } 3807e2e9c0cSopenharmony_ci } 3817e2e9c0cSopenharmony_ci } 3827e2e9c0cSopenharmony_ci syn::Data::Struct(_) => { 3837e2e9c0cSopenharmony_ci let msg = "#[serde(rename_all_fields)] can only be used on enums"; 3847e2e9c0cSopenharmony_ci cx.syn_error(meta.error(msg)); 3857e2e9c0cSopenharmony_ci } 3867e2e9c0cSopenharmony_ci syn::Data::Union(_) => { 3877e2e9c0cSopenharmony_ci let msg = "#[serde(rename_all_fields)] can only be used on enums"; 3887e2e9c0cSopenharmony_ci cx.syn_error(meta.error(msg)); 3897e2e9c0cSopenharmony_ci } 3907e2e9c0cSopenharmony_ci } 3917e2e9c0cSopenharmony_ci } else if meta.path == TRANSPARENT { 3927e2e9c0cSopenharmony_ci // #[serde(transparent)] 3937e2e9c0cSopenharmony_ci transparent.set_true(meta.path); 3947e2e9c0cSopenharmony_ci } else if meta.path == DENY_UNKNOWN_FIELDS { 3957e2e9c0cSopenharmony_ci // #[serde(deny_unknown_fields)] 3967e2e9c0cSopenharmony_ci deny_unknown_fields.set_true(meta.path); 3977e2e9c0cSopenharmony_ci } else if meta.path == DEFAULT { 3987e2e9c0cSopenharmony_ci if meta.input.peek(Token![=]) { 3997e2e9c0cSopenharmony_ci // #[serde(default = "...")] 4007e2e9c0cSopenharmony_ci if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? { 4017e2e9c0cSopenharmony_ci match &item.data { 4027e2e9c0cSopenharmony_ci syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { 4037e2e9c0cSopenharmony_ci syn::Fields::Named(_) | syn::Fields::Unnamed(_) => { 4047e2e9c0cSopenharmony_ci default.set(&meta.path, Default::Path(path)); 4057e2e9c0cSopenharmony_ci } 4067e2e9c0cSopenharmony_ci syn::Fields::Unit => { 4077e2e9c0cSopenharmony_ci let msg = "#[serde(default = \"...\")] can only be used on structs that have fields"; 4087e2e9c0cSopenharmony_ci cx.syn_error(meta.error(msg)); 4097e2e9c0cSopenharmony_ci } 4107e2e9c0cSopenharmony_ci }, 4117e2e9c0cSopenharmony_ci syn::Data::Enum(_) => { 4127e2e9c0cSopenharmony_ci let msg = "#[serde(default = \"...\")] can only be used on structs"; 4137e2e9c0cSopenharmony_ci cx.syn_error(meta.error(msg)); 4147e2e9c0cSopenharmony_ci } 4157e2e9c0cSopenharmony_ci syn::Data::Union(_) => { 4167e2e9c0cSopenharmony_ci let msg = "#[serde(default = \"...\")] can only be used on structs"; 4177e2e9c0cSopenharmony_ci cx.syn_error(meta.error(msg)); 4187e2e9c0cSopenharmony_ci } 4197e2e9c0cSopenharmony_ci } 4207e2e9c0cSopenharmony_ci } 4217e2e9c0cSopenharmony_ci } else { 4227e2e9c0cSopenharmony_ci // #[serde(default)] 4237e2e9c0cSopenharmony_ci match &item.data { 4247e2e9c0cSopenharmony_ci syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { 4257e2e9c0cSopenharmony_ci syn::Fields::Named(_) | syn::Fields::Unnamed(_) => { 4267e2e9c0cSopenharmony_ci default.set(meta.path, Default::Default); 4277e2e9c0cSopenharmony_ci } 4287e2e9c0cSopenharmony_ci syn::Fields::Unit => { 4297e2e9c0cSopenharmony_ci let msg = "#[serde(default)] can only be used on structs that have fields"; 4307e2e9c0cSopenharmony_ci cx.error_spanned_by(fields, msg); 4317e2e9c0cSopenharmony_ci } 4327e2e9c0cSopenharmony_ci }, 4337e2e9c0cSopenharmony_ci syn::Data::Enum(_) => { 4347e2e9c0cSopenharmony_ci let msg = "#[serde(default)] can only be used on structs"; 4357e2e9c0cSopenharmony_ci cx.syn_error(meta.error(msg)); 4367e2e9c0cSopenharmony_ci } 4377e2e9c0cSopenharmony_ci syn::Data::Union(_) => { 4387e2e9c0cSopenharmony_ci let msg = "#[serde(default)] can only be used on structs"; 4397e2e9c0cSopenharmony_ci cx.syn_error(meta.error(msg)); 4407e2e9c0cSopenharmony_ci } 4417e2e9c0cSopenharmony_ci } 4427e2e9c0cSopenharmony_ci } 4437e2e9c0cSopenharmony_ci } else if meta.path == BOUND { 4447e2e9c0cSopenharmony_ci // #[serde(bound = "T: SomeBound")] 4457e2e9c0cSopenharmony_ci // #[serde(bound(serialize = "...", deserialize = "..."))] 4467e2e9c0cSopenharmony_ci let (ser, de) = get_where_predicates(cx, &meta)?; 4477e2e9c0cSopenharmony_ci ser_bound.set_opt(&meta.path, ser); 4487e2e9c0cSopenharmony_ci de_bound.set_opt(&meta.path, de); 4497e2e9c0cSopenharmony_ci } else if meta.path == UNTAGGED { 4507e2e9c0cSopenharmony_ci // #[serde(untagged)] 4517e2e9c0cSopenharmony_ci match item.data { 4527e2e9c0cSopenharmony_ci syn::Data::Enum(_) => { 4537e2e9c0cSopenharmony_ci untagged.set_true(&meta.path); 4547e2e9c0cSopenharmony_ci } 4557e2e9c0cSopenharmony_ci syn::Data::Struct(_) => { 4567e2e9c0cSopenharmony_ci let msg = "#[serde(untagged)] can only be used on enums"; 4577e2e9c0cSopenharmony_ci cx.syn_error(meta.error(msg)); 4587e2e9c0cSopenharmony_ci } 4597e2e9c0cSopenharmony_ci syn::Data::Union(_) => { 4607e2e9c0cSopenharmony_ci let msg = "#[serde(untagged)] can only be used on enums"; 4617e2e9c0cSopenharmony_ci cx.syn_error(meta.error(msg)); 4627e2e9c0cSopenharmony_ci } 4637e2e9c0cSopenharmony_ci } 4647e2e9c0cSopenharmony_ci } else if meta.path == TAG { 4657e2e9c0cSopenharmony_ci // #[serde(tag = "type")] 4667e2e9c0cSopenharmony_ci if let Some(s) = get_lit_str(cx, TAG, &meta)? { 4677e2e9c0cSopenharmony_ci match &item.data { 4687e2e9c0cSopenharmony_ci syn::Data::Enum(_) => { 4697e2e9c0cSopenharmony_ci internal_tag.set(&meta.path, s.value()); 4707e2e9c0cSopenharmony_ci } 4717e2e9c0cSopenharmony_ci syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { 4727e2e9c0cSopenharmony_ci syn::Fields::Named(_) => { 4737e2e9c0cSopenharmony_ci internal_tag.set(&meta.path, s.value()); 4747e2e9c0cSopenharmony_ci } 4757e2e9c0cSopenharmony_ci syn::Fields::Unnamed(_) | syn::Fields::Unit => { 4767e2e9c0cSopenharmony_ci let msg = "#[serde(tag = \"...\")] can only be used on enums and structs with named fields"; 4777e2e9c0cSopenharmony_ci cx.syn_error(meta.error(msg)); 4787e2e9c0cSopenharmony_ci } 4797e2e9c0cSopenharmony_ci }, 4807e2e9c0cSopenharmony_ci syn::Data::Union(_) => { 4817e2e9c0cSopenharmony_ci let msg = "#[serde(tag = \"...\")] can only be used on enums and structs with named fields"; 4827e2e9c0cSopenharmony_ci cx.syn_error(meta.error(msg)); 4837e2e9c0cSopenharmony_ci } 4847e2e9c0cSopenharmony_ci } 4857e2e9c0cSopenharmony_ci } 4867e2e9c0cSopenharmony_ci } else if meta.path == CONTENT { 4877e2e9c0cSopenharmony_ci // #[serde(content = "c")] 4887e2e9c0cSopenharmony_ci if let Some(s) = get_lit_str(cx, CONTENT, &meta)? { 4897e2e9c0cSopenharmony_ci match &item.data { 4907e2e9c0cSopenharmony_ci syn::Data::Enum(_) => { 4917e2e9c0cSopenharmony_ci content.set(&meta.path, s.value()); 4927e2e9c0cSopenharmony_ci } 4937e2e9c0cSopenharmony_ci syn::Data::Struct(_) => { 4947e2e9c0cSopenharmony_ci let msg = "#[serde(content = \"...\")] can only be used on enums"; 4957e2e9c0cSopenharmony_ci cx.syn_error(meta.error(msg)); 4967e2e9c0cSopenharmony_ci } 4977e2e9c0cSopenharmony_ci syn::Data::Union(_) => { 4987e2e9c0cSopenharmony_ci let msg = "#[serde(content = \"...\")] can only be used on enums"; 4997e2e9c0cSopenharmony_ci cx.syn_error(meta.error(msg)); 5007e2e9c0cSopenharmony_ci } 5017e2e9c0cSopenharmony_ci } 5027e2e9c0cSopenharmony_ci } 5037e2e9c0cSopenharmony_ci } else if meta.path == FROM { 5047e2e9c0cSopenharmony_ci // #[serde(from = "Type")] 5057e2e9c0cSopenharmony_ci if let Some(from_ty) = parse_lit_into_ty(cx, FROM, &meta)? { 5067e2e9c0cSopenharmony_ci type_from.set_opt(&meta.path, Some(from_ty)); 5077e2e9c0cSopenharmony_ci } 5087e2e9c0cSopenharmony_ci } else if meta.path == TRY_FROM { 5097e2e9c0cSopenharmony_ci // #[serde(try_from = "Type")] 5107e2e9c0cSopenharmony_ci if let Some(try_from_ty) = parse_lit_into_ty(cx, TRY_FROM, &meta)? { 5117e2e9c0cSopenharmony_ci type_try_from.set_opt(&meta.path, Some(try_from_ty)); 5127e2e9c0cSopenharmony_ci } 5137e2e9c0cSopenharmony_ci } else if meta.path == INTO { 5147e2e9c0cSopenharmony_ci // #[serde(into = "Type")] 5157e2e9c0cSopenharmony_ci if let Some(into_ty) = parse_lit_into_ty(cx, INTO, &meta)? { 5167e2e9c0cSopenharmony_ci type_into.set_opt(&meta.path, Some(into_ty)); 5177e2e9c0cSopenharmony_ci } 5187e2e9c0cSopenharmony_ci } else if meta.path == REMOTE { 5197e2e9c0cSopenharmony_ci // #[serde(remote = "...")] 5207e2e9c0cSopenharmony_ci if let Some(path) = parse_lit_into_path(cx, REMOTE, &meta)? { 5217e2e9c0cSopenharmony_ci if is_primitive_path(&path, "Self") { 5227e2e9c0cSopenharmony_ci remote.set(&meta.path, item.ident.clone().into()); 5237e2e9c0cSopenharmony_ci } else { 5247e2e9c0cSopenharmony_ci remote.set(&meta.path, path); 5257e2e9c0cSopenharmony_ci } 5267e2e9c0cSopenharmony_ci } 5277e2e9c0cSopenharmony_ci } else if meta.path == FIELD_IDENTIFIER { 5287e2e9c0cSopenharmony_ci // #[serde(field_identifier)] 5297e2e9c0cSopenharmony_ci field_identifier.set_true(&meta.path); 5307e2e9c0cSopenharmony_ci } else if meta.path == VARIANT_IDENTIFIER { 5317e2e9c0cSopenharmony_ci // #[serde(variant_identifier)] 5327e2e9c0cSopenharmony_ci variant_identifier.set_true(&meta.path); 5337e2e9c0cSopenharmony_ci } else if meta.path == CRATE { 5347e2e9c0cSopenharmony_ci // #[serde(crate = "foo")] 5357e2e9c0cSopenharmony_ci if let Some(path) = parse_lit_into_path(cx, CRATE, &meta)? { 5367e2e9c0cSopenharmony_ci serde_path.set(&meta.path, path); 5377e2e9c0cSopenharmony_ci } 5387e2e9c0cSopenharmony_ci } else if meta.path == EXPECTING { 5397e2e9c0cSopenharmony_ci // #[serde(expecting = "a message")] 5407e2e9c0cSopenharmony_ci if let Some(s) = get_lit_str(cx, EXPECTING, &meta)? { 5417e2e9c0cSopenharmony_ci expecting.set(&meta.path, s.value()); 5427e2e9c0cSopenharmony_ci } 5437e2e9c0cSopenharmony_ci } else { 5447e2e9c0cSopenharmony_ci let path = meta.path.to_token_stream().to_string().replace(' ', ""); 5457e2e9c0cSopenharmony_ci return Err( 5467e2e9c0cSopenharmony_ci meta.error(format_args!("unknown serde container attribute `{}`", path)) 5477e2e9c0cSopenharmony_ci ); 5487e2e9c0cSopenharmony_ci } 5497e2e9c0cSopenharmony_ci Ok(()) 5507e2e9c0cSopenharmony_ci }) { 5517e2e9c0cSopenharmony_ci cx.syn_error(err); 5527e2e9c0cSopenharmony_ci } 5537e2e9c0cSopenharmony_ci } 5547e2e9c0cSopenharmony_ci 5557e2e9c0cSopenharmony_ci let mut is_packed = false; 5567e2e9c0cSopenharmony_ci for attr in &item.attrs { 5577e2e9c0cSopenharmony_ci if attr.path() == REPR { 5587e2e9c0cSopenharmony_ci let _ = attr.parse_args_with(|input: ParseStream| { 5597e2e9c0cSopenharmony_ci while let Some(token) = input.parse()? { 5607e2e9c0cSopenharmony_ci if let TokenTree::Ident(ident) = token { 5617e2e9c0cSopenharmony_ci is_packed |= ident == "packed"; 5627e2e9c0cSopenharmony_ci } 5637e2e9c0cSopenharmony_ci } 5647e2e9c0cSopenharmony_ci Ok(()) 5657e2e9c0cSopenharmony_ci }); 5667e2e9c0cSopenharmony_ci } 5677e2e9c0cSopenharmony_ci } 5687e2e9c0cSopenharmony_ci 5697e2e9c0cSopenharmony_ci Container { 5707e2e9c0cSopenharmony_ci name: Name::from_attrs(unraw(&item.ident), ser_name, de_name, None), 5717e2e9c0cSopenharmony_ci transparent: transparent.get(), 5727e2e9c0cSopenharmony_ci deny_unknown_fields: deny_unknown_fields.get(), 5737e2e9c0cSopenharmony_ci default: default.get().unwrap_or(Default::None), 5747e2e9c0cSopenharmony_ci rename_all_rules: RenameAllRules { 5757e2e9c0cSopenharmony_ci serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None), 5767e2e9c0cSopenharmony_ci deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None), 5777e2e9c0cSopenharmony_ci }, 5787e2e9c0cSopenharmony_ci rename_all_fields_rules: RenameAllRules { 5797e2e9c0cSopenharmony_ci serialize: rename_all_fields_ser_rule.get().unwrap_or(RenameRule::None), 5807e2e9c0cSopenharmony_ci deserialize: rename_all_fields_de_rule.get().unwrap_or(RenameRule::None), 5817e2e9c0cSopenharmony_ci }, 5827e2e9c0cSopenharmony_ci ser_bound: ser_bound.get(), 5837e2e9c0cSopenharmony_ci de_bound: de_bound.get(), 5847e2e9c0cSopenharmony_ci tag: decide_tag(cx, item, untagged, internal_tag, content), 5857e2e9c0cSopenharmony_ci type_from: type_from.get(), 5867e2e9c0cSopenharmony_ci type_try_from: type_try_from.get(), 5877e2e9c0cSopenharmony_ci type_into: type_into.get(), 5887e2e9c0cSopenharmony_ci remote: remote.get(), 5897e2e9c0cSopenharmony_ci identifier: decide_identifier(cx, item, field_identifier, variant_identifier), 5907e2e9c0cSopenharmony_ci has_flatten: false, 5917e2e9c0cSopenharmony_ci serde_path: serde_path.get(), 5927e2e9c0cSopenharmony_ci is_packed, 5937e2e9c0cSopenharmony_ci expecting: expecting.get(), 5947e2e9c0cSopenharmony_ci non_exhaustive, 5957e2e9c0cSopenharmony_ci } 5967e2e9c0cSopenharmony_ci } 5977e2e9c0cSopenharmony_ci 5987e2e9c0cSopenharmony_ci pub fn name(&self) -> &Name { 5997e2e9c0cSopenharmony_ci &self.name 6007e2e9c0cSopenharmony_ci } 6017e2e9c0cSopenharmony_ci 6027e2e9c0cSopenharmony_ci pub fn rename_all_rules(&self) -> RenameAllRules { 6037e2e9c0cSopenharmony_ci self.rename_all_rules 6047e2e9c0cSopenharmony_ci } 6057e2e9c0cSopenharmony_ci 6067e2e9c0cSopenharmony_ci pub fn rename_all_fields_rules(&self) -> RenameAllRules { 6077e2e9c0cSopenharmony_ci self.rename_all_fields_rules 6087e2e9c0cSopenharmony_ci } 6097e2e9c0cSopenharmony_ci 6107e2e9c0cSopenharmony_ci pub fn transparent(&self) -> bool { 6117e2e9c0cSopenharmony_ci self.transparent 6127e2e9c0cSopenharmony_ci } 6137e2e9c0cSopenharmony_ci 6147e2e9c0cSopenharmony_ci pub fn deny_unknown_fields(&self) -> bool { 6157e2e9c0cSopenharmony_ci self.deny_unknown_fields 6167e2e9c0cSopenharmony_ci } 6177e2e9c0cSopenharmony_ci 6187e2e9c0cSopenharmony_ci pub fn default(&self) -> &Default { 6197e2e9c0cSopenharmony_ci &self.default 6207e2e9c0cSopenharmony_ci } 6217e2e9c0cSopenharmony_ci 6227e2e9c0cSopenharmony_ci pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> { 6237e2e9c0cSopenharmony_ci self.ser_bound.as_ref().map(|vec| &vec[..]) 6247e2e9c0cSopenharmony_ci } 6257e2e9c0cSopenharmony_ci 6267e2e9c0cSopenharmony_ci pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { 6277e2e9c0cSopenharmony_ci self.de_bound.as_ref().map(|vec| &vec[..]) 6287e2e9c0cSopenharmony_ci } 6297e2e9c0cSopenharmony_ci 6307e2e9c0cSopenharmony_ci pub fn tag(&self) -> &TagType { 6317e2e9c0cSopenharmony_ci &self.tag 6327e2e9c0cSopenharmony_ci } 6337e2e9c0cSopenharmony_ci 6347e2e9c0cSopenharmony_ci pub fn type_from(&self) -> Option<&syn::Type> { 6357e2e9c0cSopenharmony_ci self.type_from.as_ref() 6367e2e9c0cSopenharmony_ci } 6377e2e9c0cSopenharmony_ci 6387e2e9c0cSopenharmony_ci pub fn type_try_from(&self) -> Option<&syn::Type> { 6397e2e9c0cSopenharmony_ci self.type_try_from.as_ref() 6407e2e9c0cSopenharmony_ci } 6417e2e9c0cSopenharmony_ci 6427e2e9c0cSopenharmony_ci pub fn type_into(&self) -> Option<&syn::Type> { 6437e2e9c0cSopenharmony_ci self.type_into.as_ref() 6447e2e9c0cSopenharmony_ci } 6457e2e9c0cSopenharmony_ci 6467e2e9c0cSopenharmony_ci pub fn remote(&self) -> Option<&syn::Path> { 6477e2e9c0cSopenharmony_ci self.remote.as_ref() 6487e2e9c0cSopenharmony_ci } 6497e2e9c0cSopenharmony_ci 6507e2e9c0cSopenharmony_ci pub fn is_packed(&self) -> bool { 6517e2e9c0cSopenharmony_ci self.is_packed 6527e2e9c0cSopenharmony_ci } 6537e2e9c0cSopenharmony_ci 6547e2e9c0cSopenharmony_ci pub fn identifier(&self) -> Identifier { 6557e2e9c0cSopenharmony_ci self.identifier 6567e2e9c0cSopenharmony_ci } 6577e2e9c0cSopenharmony_ci 6587e2e9c0cSopenharmony_ci pub fn has_flatten(&self) -> bool { 6597e2e9c0cSopenharmony_ci self.has_flatten 6607e2e9c0cSopenharmony_ci } 6617e2e9c0cSopenharmony_ci 6627e2e9c0cSopenharmony_ci pub fn mark_has_flatten(&mut self) { 6637e2e9c0cSopenharmony_ci self.has_flatten = true; 6647e2e9c0cSopenharmony_ci } 6657e2e9c0cSopenharmony_ci 6667e2e9c0cSopenharmony_ci pub fn custom_serde_path(&self) -> Option<&syn::Path> { 6677e2e9c0cSopenharmony_ci self.serde_path.as_ref() 6687e2e9c0cSopenharmony_ci } 6697e2e9c0cSopenharmony_ci 6707e2e9c0cSopenharmony_ci pub fn serde_path(&self) -> Cow<syn::Path> { 6717e2e9c0cSopenharmony_ci self.custom_serde_path() 6727e2e9c0cSopenharmony_ci .map_or_else(|| Cow::Owned(parse_quote!(_serde)), Cow::Borrowed) 6737e2e9c0cSopenharmony_ci } 6747e2e9c0cSopenharmony_ci 6757e2e9c0cSopenharmony_ci /// Error message generated when type can't be deserialized. 6767e2e9c0cSopenharmony_ci /// If `None`, default message will be used 6777e2e9c0cSopenharmony_ci pub fn expecting(&self) -> Option<&str> { 6787e2e9c0cSopenharmony_ci self.expecting.as_ref().map(String::as_ref) 6797e2e9c0cSopenharmony_ci } 6807e2e9c0cSopenharmony_ci 6817e2e9c0cSopenharmony_ci pub fn non_exhaustive(&self) -> bool { 6827e2e9c0cSopenharmony_ci self.non_exhaustive 6837e2e9c0cSopenharmony_ci } 6847e2e9c0cSopenharmony_ci} 6857e2e9c0cSopenharmony_ci 6867e2e9c0cSopenharmony_cifn decide_tag( 6877e2e9c0cSopenharmony_ci cx: &Ctxt, 6887e2e9c0cSopenharmony_ci item: &syn::DeriveInput, 6897e2e9c0cSopenharmony_ci untagged: BoolAttr, 6907e2e9c0cSopenharmony_ci internal_tag: Attr<String>, 6917e2e9c0cSopenharmony_ci content: Attr<String>, 6927e2e9c0cSopenharmony_ci) -> TagType { 6937e2e9c0cSopenharmony_ci match ( 6947e2e9c0cSopenharmony_ci untagged.0.get_with_tokens(), 6957e2e9c0cSopenharmony_ci internal_tag.get_with_tokens(), 6967e2e9c0cSopenharmony_ci content.get_with_tokens(), 6977e2e9c0cSopenharmony_ci ) { 6987e2e9c0cSopenharmony_ci (None, None, None) => TagType::External, 6997e2e9c0cSopenharmony_ci (Some(_), None, None) => TagType::None, 7007e2e9c0cSopenharmony_ci (None, Some((_, tag)), None) => { 7017e2e9c0cSopenharmony_ci // Check that there are no tuple variants. 7027e2e9c0cSopenharmony_ci if let syn::Data::Enum(data) = &item.data { 7037e2e9c0cSopenharmony_ci for variant in &data.variants { 7047e2e9c0cSopenharmony_ci match &variant.fields { 7057e2e9c0cSopenharmony_ci syn::Fields::Named(_) | syn::Fields::Unit => {} 7067e2e9c0cSopenharmony_ci syn::Fields::Unnamed(fields) => { 7077e2e9c0cSopenharmony_ci if fields.unnamed.len() != 1 { 7087e2e9c0cSopenharmony_ci let msg = 7097e2e9c0cSopenharmony_ci "#[serde(tag = \"...\")] cannot be used with tuple variants"; 7107e2e9c0cSopenharmony_ci cx.error_spanned_by(variant, msg); 7117e2e9c0cSopenharmony_ci break; 7127e2e9c0cSopenharmony_ci } 7137e2e9c0cSopenharmony_ci } 7147e2e9c0cSopenharmony_ci } 7157e2e9c0cSopenharmony_ci } 7167e2e9c0cSopenharmony_ci } 7177e2e9c0cSopenharmony_ci TagType::Internal { tag } 7187e2e9c0cSopenharmony_ci } 7197e2e9c0cSopenharmony_ci (Some((untagged_tokens, ())), Some((tag_tokens, _)), None) => { 7207e2e9c0cSopenharmony_ci let msg = "enum cannot be both untagged and internally tagged"; 7217e2e9c0cSopenharmony_ci cx.error_spanned_by(untagged_tokens, msg); 7227e2e9c0cSopenharmony_ci cx.error_spanned_by(tag_tokens, msg); 7237e2e9c0cSopenharmony_ci TagType::External // doesn't matter, will error 7247e2e9c0cSopenharmony_ci } 7257e2e9c0cSopenharmony_ci (None, None, Some((content_tokens, _))) => { 7267e2e9c0cSopenharmony_ci let msg = "#[serde(tag = \"...\", content = \"...\")] must be used together"; 7277e2e9c0cSopenharmony_ci cx.error_spanned_by(content_tokens, msg); 7287e2e9c0cSopenharmony_ci TagType::External 7297e2e9c0cSopenharmony_ci } 7307e2e9c0cSopenharmony_ci (Some((untagged_tokens, ())), None, Some((content_tokens, _))) => { 7317e2e9c0cSopenharmony_ci let msg = "untagged enum cannot have #[serde(content = \"...\")]"; 7327e2e9c0cSopenharmony_ci cx.error_spanned_by(untagged_tokens, msg); 7337e2e9c0cSopenharmony_ci cx.error_spanned_by(content_tokens, msg); 7347e2e9c0cSopenharmony_ci TagType::External 7357e2e9c0cSopenharmony_ci } 7367e2e9c0cSopenharmony_ci (None, Some((_, tag)), Some((_, content))) => TagType::Adjacent { tag, content }, 7377e2e9c0cSopenharmony_ci (Some((untagged_tokens, ())), Some((tag_tokens, _)), Some((content_tokens, _))) => { 7387e2e9c0cSopenharmony_ci let msg = "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]"; 7397e2e9c0cSopenharmony_ci cx.error_spanned_by(untagged_tokens, msg); 7407e2e9c0cSopenharmony_ci cx.error_spanned_by(tag_tokens, msg); 7417e2e9c0cSopenharmony_ci cx.error_spanned_by(content_tokens, msg); 7427e2e9c0cSopenharmony_ci TagType::External 7437e2e9c0cSopenharmony_ci } 7447e2e9c0cSopenharmony_ci } 7457e2e9c0cSopenharmony_ci} 7467e2e9c0cSopenharmony_ci 7477e2e9c0cSopenharmony_cifn decide_identifier( 7487e2e9c0cSopenharmony_ci cx: &Ctxt, 7497e2e9c0cSopenharmony_ci item: &syn::DeriveInput, 7507e2e9c0cSopenharmony_ci field_identifier: BoolAttr, 7517e2e9c0cSopenharmony_ci variant_identifier: BoolAttr, 7527e2e9c0cSopenharmony_ci) -> Identifier { 7537e2e9c0cSopenharmony_ci match ( 7547e2e9c0cSopenharmony_ci &item.data, 7557e2e9c0cSopenharmony_ci field_identifier.0.get_with_tokens(), 7567e2e9c0cSopenharmony_ci variant_identifier.0.get_with_tokens(), 7577e2e9c0cSopenharmony_ci ) { 7587e2e9c0cSopenharmony_ci (_, None, None) => Identifier::No, 7597e2e9c0cSopenharmony_ci (_, Some((field_identifier_tokens, ())), Some((variant_identifier_tokens, ()))) => { 7607e2e9c0cSopenharmony_ci let msg = 7617e2e9c0cSopenharmony_ci "#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set"; 7627e2e9c0cSopenharmony_ci cx.error_spanned_by(field_identifier_tokens, msg); 7637e2e9c0cSopenharmony_ci cx.error_spanned_by(variant_identifier_tokens, msg); 7647e2e9c0cSopenharmony_ci Identifier::No 7657e2e9c0cSopenharmony_ci } 7667e2e9c0cSopenharmony_ci (syn::Data::Enum(_), Some(_), None) => Identifier::Field, 7677e2e9c0cSopenharmony_ci (syn::Data::Enum(_), None, Some(_)) => Identifier::Variant, 7687e2e9c0cSopenharmony_ci (syn::Data::Struct(syn::DataStruct { struct_token, .. }), Some(_), None) => { 7697e2e9c0cSopenharmony_ci let msg = "#[serde(field_identifier)] can only be used on an enum"; 7707e2e9c0cSopenharmony_ci cx.error_spanned_by(struct_token, msg); 7717e2e9c0cSopenharmony_ci Identifier::No 7727e2e9c0cSopenharmony_ci } 7737e2e9c0cSopenharmony_ci (syn::Data::Union(syn::DataUnion { union_token, .. }), Some(_), None) => { 7747e2e9c0cSopenharmony_ci let msg = "#[serde(field_identifier)] can only be used on an enum"; 7757e2e9c0cSopenharmony_ci cx.error_spanned_by(union_token, msg); 7767e2e9c0cSopenharmony_ci Identifier::No 7777e2e9c0cSopenharmony_ci } 7787e2e9c0cSopenharmony_ci (syn::Data::Struct(syn::DataStruct { struct_token, .. }), None, Some(_)) => { 7797e2e9c0cSopenharmony_ci let msg = "#[serde(variant_identifier)] can only be used on an enum"; 7807e2e9c0cSopenharmony_ci cx.error_spanned_by(struct_token, msg); 7817e2e9c0cSopenharmony_ci Identifier::No 7827e2e9c0cSopenharmony_ci } 7837e2e9c0cSopenharmony_ci (syn::Data::Union(syn::DataUnion { union_token, .. }), None, Some(_)) => { 7847e2e9c0cSopenharmony_ci let msg = "#[serde(variant_identifier)] can only be used on an enum"; 7857e2e9c0cSopenharmony_ci cx.error_spanned_by(union_token, msg); 7867e2e9c0cSopenharmony_ci Identifier::No 7877e2e9c0cSopenharmony_ci } 7887e2e9c0cSopenharmony_ci } 7897e2e9c0cSopenharmony_ci} 7907e2e9c0cSopenharmony_ci 7917e2e9c0cSopenharmony_ci/// Represents variant attribute information 7927e2e9c0cSopenharmony_cipub struct Variant { 7937e2e9c0cSopenharmony_ci name: Name, 7947e2e9c0cSopenharmony_ci rename_all_rules: RenameAllRules, 7957e2e9c0cSopenharmony_ci ser_bound: Option<Vec<syn::WherePredicate>>, 7967e2e9c0cSopenharmony_ci de_bound: Option<Vec<syn::WherePredicate>>, 7977e2e9c0cSopenharmony_ci skip_deserializing: bool, 7987e2e9c0cSopenharmony_ci skip_serializing: bool, 7997e2e9c0cSopenharmony_ci other: bool, 8007e2e9c0cSopenharmony_ci serialize_with: Option<syn::ExprPath>, 8017e2e9c0cSopenharmony_ci deserialize_with: Option<syn::ExprPath>, 8027e2e9c0cSopenharmony_ci borrow: Option<BorrowAttribute>, 8037e2e9c0cSopenharmony_ci untagged: bool, 8047e2e9c0cSopenharmony_ci} 8057e2e9c0cSopenharmony_ci 8067e2e9c0cSopenharmony_cistruct BorrowAttribute { 8077e2e9c0cSopenharmony_ci path: syn::Path, 8087e2e9c0cSopenharmony_ci lifetimes: Option<BTreeSet<syn::Lifetime>>, 8097e2e9c0cSopenharmony_ci} 8107e2e9c0cSopenharmony_ci 8117e2e9c0cSopenharmony_ciimpl Variant { 8127e2e9c0cSopenharmony_ci pub fn from_ast(cx: &Ctxt, variant: &syn::Variant) -> Self { 8137e2e9c0cSopenharmony_ci let mut ser_name = Attr::none(cx, RENAME); 8147e2e9c0cSopenharmony_ci let mut de_name = Attr::none(cx, RENAME); 8157e2e9c0cSopenharmony_ci let mut de_aliases = VecAttr::none(cx, RENAME); 8167e2e9c0cSopenharmony_ci let mut skip_deserializing = BoolAttr::none(cx, SKIP_DESERIALIZING); 8177e2e9c0cSopenharmony_ci let mut skip_serializing = BoolAttr::none(cx, SKIP_SERIALIZING); 8187e2e9c0cSopenharmony_ci let mut rename_all_ser_rule = Attr::none(cx, RENAME_ALL); 8197e2e9c0cSopenharmony_ci let mut rename_all_de_rule = Attr::none(cx, RENAME_ALL); 8207e2e9c0cSopenharmony_ci let mut ser_bound = Attr::none(cx, BOUND); 8217e2e9c0cSopenharmony_ci let mut de_bound = Attr::none(cx, BOUND); 8227e2e9c0cSopenharmony_ci let mut other = BoolAttr::none(cx, OTHER); 8237e2e9c0cSopenharmony_ci let mut serialize_with = Attr::none(cx, SERIALIZE_WITH); 8247e2e9c0cSopenharmony_ci let mut deserialize_with = Attr::none(cx, DESERIALIZE_WITH); 8257e2e9c0cSopenharmony_ci let mut borrow = Attr::none(cx, BORROW); 8267e2e9c0cSopenharmony_ci let mut untagged = BoolAttr::none(cx, UNTAGGED); 8277e2e9c0cSopenharmony_ci 8287e2e9c0cSopenharmony_ci for attr in &variant.attrs { 8297e2e9c0cSopenharmony_ci if attr.path() != SERDE { 8307e2e9c0cSopenharmony_ci continue; 8317e2e9c0cSopenharmony_ci } 8327e2e9c0cSopenharmony_ci 8337e2e9c0cSopenharmony_ci if let syn::Meta::List(meta) = &attr.meta { 8347e2e9c0cSopenharmony_ci if meta.tokens.is_empty() { 8357e2e9c0cSopenharmony_ci continue; 8367e2e9c0cSopenharmony_ci } 8377e2e9c0cSopenharmony_ci } 8387e2e9c0cSopenharmony_ci 8397e2e9c0cSopenharmony_ci if let Err(err) = attr.parse_nested_meta(|meta| { 8407e2e9c0cSopenharmony_ci if meta.path == RENAME { 8417e2e9c0cSopenharmony_ci // #[serde(rename = "foo")] 8427e2e9c0cSopenharmony_ci // #[serde(rename(serialize = "foo", deserialize = "bar"))] 8437e2e9c0cSopenharmony_ci let (ser, de) = get_multiple_renames(cx, &meta)?; 8447e2e9c0cSopenharmony_ci ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value)); 8457e2e9c0cSopenharmony_ci for de_value in de { 8467e2e9c0cSopenharmony_ci de_name.set_if_none(de_value.value()); 8477e2e9c0cSopenharmony_ci de_aliases.insert(&meta.path, de_value.value()); 8487e2e9c0cSopenharmony_ci } 8497e2e9c0cSopenharmony_ci } else if meta.path == ALIAS { 8507e2e9c0cSopenharmony_ci // #[serde(alias = "foo")] 8517e2e9c0cSopenharmony_ci if let Some(s) = get_lit_str(cx, ALIAS, &meta)? { 8527e2e9c0cSopenharmony_ci de_aliases.insert(&meta.path, s.value()); 8537e2e9c0cSopenharmony_ci } 8547e2e9c0cSopenharmony_ci } else if meta.path == RENAME_ALL { 8557e2e9c0cSopenharmony_ci // #[serde(rename_all = "foo")] 8567e2e9c0cSopenharmony_ci // #[serde(rename_all(serialize = "foo", deserialize = "bar"))] 8577e2e9c0cSopenharmony_ci let one_name = meta.input.peek(Token![=]); 8587e2e9c0cSopenharmony_ci let (ser, de) = get_renames(cx, RENAME_ALL, &meta)?; 8597e2e9c0cSopenharmony_ci if let Some(ser) = ser { 8607e2e9c0cSopenharmony_ci match RenameRule::from_str(&ser.value()) { 8617e2e9c0cSopenharmony_ci Ok(rename_rule) => rename_all_ser_rule.set(&meta.path, rename_rule), 8627e2e9c0cSopenharmony_ci Err(err) => cx.error_spanned_by(ser, err), 8637e2e9c0cSopenharmony_ci } 8647e2e9c0cSopenharmony_ci } 8657e2e9c0cSopenharmony_ci if let Some(de) = de { 8667e2e9c0cSopenharmony_ci match RenameRule::from_str(&de.value()) { 8677e2e9c0cSopenharmony_ci Ok(rename_rule) => rename_all_de_rule.set(&meta.path, rename_rule), 8687e2e9c0cSopenharmony_ci Err(err) => { 8697e2e9c0cSopenharmony_ci if !one_name { 8707e2e9c0cSopenharmony_ci cx.error_spanned_by(de, err); 8717e2e9c0cSopenharmony_ci } 8727e2e9c0cSopenharmony_ci } 8737e2e9c0cSopenharmony_ci } 8747e2e9c0cSopenharmony_ci } 8757e2e9c0cSopenharmony_ci } else if meta.path == SKIP { 8767e2e9c0cSopenharmony_ci // #[serde(skip)] 8777e2e9c0cSopenharmony_ci skip_serializing.set_true(&meta.path); 8787e2e9c0cSopenharmony_ci skip_deserializing.set_true(&meta.path); 8797e2e9c0cSopenharmony_ci } else if meta.path == SKIP_DESERIALIZING { 8807e2e9c0cSopenharmony_ci // #[serde(skip_deserializing)] 8817e2e9c0cSopenharmony_ci skip_deserializing.set_true(&meta.path); 8827e2e9c0cSopenharmony_ci } else if meta.path == SKIP_SERIALIZING { 8837e2e9c0cSopenharmony_ci // #[serde(skip_serializing)] 8847e2e9c0cSopenharmony_ci skip_serializing.set_true(&meta.path); 8857e2e9c0cSopenharmony_ci } else if meta.path == OTHER { 8867e2e9c0cSopenharmony_ci // #[serde(other)] 8877e2e9c0cSopenharmony_ci other.set_true(&meta.path); 8887e2e9c0cSopenharmony_ci } else if meta.path == BOUND { 8897e2e9c0cSopenharmony_ci // #[serde(bound = "T: SomeBound")] 8907e2e9c0cSopenharmony_ci // #[serde(bound(serialize = "...", deserialize = "..."))] 8917e2e9c0cSopenharmony_ci let (ser, de) = get_where_predicates(cx, &meta)?; 8927e2e9c0cSopenharmony_ci ser_bound.set_opt(&meta.path, ser); 8937e2e9c0cSopenharmony_ci de_bound.set_opt(&meta.path, de); 8947e2e9c0cSopenharmony_ci } else if meta.path == WITH { 8957e2e9c0cSopenharmony_ci // #[serde(with = "...")] 8967e2e9c0cSopenharmony_ci if let Some(path) = parse_lit_into_expr_path(cx, WITH, &meta)? { 8977e2e9c0cSopenharmony_ci let mut ser_path = path.clone(); 8987e2e9c0cSopenharmony_ci ser_path 8997e2e9c0cSopenharmony_ci .path 9007e2e9c0cSopenharmony_ci .segments 9017e2e9c0cSopenharmony_ci .push(Ident::new("serialize", Span::call_site()).into()); 9027e2e9c0cSopenharmony_ci serialize_with.set(&meta.path, ser_path); 9037e2e9c0cSopenharmony_ci let mut de_path = path; 9047e2e9c0cSopenharmony_ci de_path 9057e2e9c0cSopenharmony_ci .path 9067e2e9c0cSopenharmony_ci .segments 9077e2e9c0cSopenharmony_ci .push(Ident::new("deserialize", Span::call_site()).into()); 9087e2e9c0cSopenharmony_ci deserialize_with.set(&meta.path, de_path); 9097e2e9c0cSopenharmony_ci } 9107e2e9c0cSopenharmony_ci } else if meta.path == SERIALIZE_WITH { 9117e2e9c0cSopenharmony_ci // #[serde(serialize_with = "...")] 9127e2e9c0cSopenharmony_ci if let Some(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &meta)? { 9137e2e9c0cSopenharmony_ci serialize_with.set(&meta.path, path); 9147e2e9c0cSopenharmony_ci } 9157e2e9c0cSopenharmony_ci } else if meta.path == DESERIALIZE_WITH { 9167e2e9c0cSopenharmony_ci // #[serde(deserialize_with = "...")] 9177e2e9c0cSopenharmony_ci if let Some(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &meta)? { 9187e2e9c0cSopenharmony_ci deserialize_with.set(&meta.path, path); 9197e2e9c0cSopenharmony_ci } 9207e2e9c0cSopenharmony_ci } else if meta.path == BORROW { 9217e2e9c0cSopenharmony_ci let borrow_attribute = if meta.input.peek(Token![=]) { 9227e2e9c0cSopenharmony_ci // #[serde(borrow = "'a + 'b")] 9237e2e9c0cSopenharmony_ci let lifetimes = parse_lit_into_lifetimes(cx, &meta)?; 9247e2e9c0cSopenharmony_ci BorrowAttribute { 9257e2e9c0cSopenharmony_ci path: meta.path.clone(), 9267e2e9c0cSopenharmony_ci lifetimes: Some(lifetimes), 9277e2e9c0cSopenharmony_ci } 9287e2e9c0cSopenharmony_ci } else { 9297e2e9c0cSopenharmony_ci // #[serde(borrow)] 9307e2e9c0cSopenharmony_ci BorrowAttribute { 9317e2e9c0cSopenharmony_ci path: meta.path.clone(), 9327e2e9c0cSopenharmony_ci lifetimes: None, 9337e2e9c0cSopenharmony_ci } 9347e2e9c0cSopenharmony_ci }; 9357e2e9c0cSopenharmony_ci match &variant.fields { 9367e2e9c0cSopenharmony_ci syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => { 9377e2e9c0cSopenharmony_ci borrow.set(&meta.path, borrow_attribute); 9387e2e9c0cSopenharmony_ci } 9397e2e9c0cSopenharmony_ci _ => { 9407e2e9c0cSopenharmony_ci let msg = "#[serde(borrow)] may only be used on newtype variants"; 9417e2e9c0cSopenharmony_ci cx.error_spanned_by(variant, msg); 9427e2e9c0cSopenharmony_ci } 9437e2e9c0cSopenharmony_ci } 9447e2e9c0cSopenharmony_ci } else if meta.path == UNTAGGED { 9457e2e9c0cSopenharmony_ci untagged.set_true(&meta.path); 9467e2e9c0cSopenharmony_ci } else { 9477e2e9c0cSopenharmony_ci let path = meta.path.to_token_stream().to_string().replace(' ', ""); 9487e2e9c0cSopenharmony_ci return Err( 9497e2e9c0cSopenharmony_ci meta.error(format_args!("unknown serde variant attribute `{}`", path)) 9507e2e9c0cSopenharmony_ci ); 9517e2e9c0cSopenharmony_ci } 9527e2e9c0cSopenharmony_ci Ok(()) 9537e2e9c0cSopenharmony_ci }) { 9547e2e9c0cSopenharmony_ci cx.syn_error(err); 9557e2e9c0cSopenharmony_ci } 9567e2e9c0cSopenharmony_ci } 9577e2e9c0cSopenharmony_ci 9587e2e9c0cSopenharmony_ci Variant { 9597e2e9c0cSopenharmony_ci name: Name::from_attrs(unraw(&variant.ident), ser_name, de_name, Some(de_aliases)), 9607e2e9c0cSopenharmony_ci rename_all_rules: RenameAllRules { 9617e2e9c0cSopenharmony_ci serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None), 9627e2e9c0cSopenharmony_ci deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None), 9637e2e9c0cSopenharmony_ci }, 9647e2e9c0cSopenharmony_ci ser_bound: ser_bound.get(), 9657e2e9c0cSopenharmony_ci de_bound: de_bound.get(), 9667e2e9c0cSopenharmony_ci skip_deserializing: skip_deserializing.get(), 9677e2e9c0cSopenharmony_ci skip_serializing: skip_serializing.get(), 9687e2e9c0cSopenharmony_ci other: other.get(), 9697e2e9c0cSopenharmony_ci serialize_with: serialize_with.get(), 9707e2e9c0cSopenharmony_ci deserialize_with: deserialize_with.get(), 9717e2e9c0cSopenharmony_ci borrow: borrow.get(), 9727e2e9c0cSopenharmony_ci untagged: untagged.get(), 9737e2e9c0cSopenharmony_ci } 9747e2e9c0cSopenharmony_ci } 9757e2e9c0cSopenharmony_ci 9767e2e9c0cSopenharmony_ci pub fn name(&self) -> &Name { 9777e2e9c0cSopenharmony_ci &self.name 9787e2e9c0cSopenharmony_ci } 9797e2e9c0cSopenharmony_ci 9807e2e9c0cSopenharmony_ci pub fn aliases(&self) -> &BTreeSet<String> { 9817e2e9c0cSopenharmony_ci self.name.deserialize_aliases() 9827e2e9c0cSopenharmony_ci } 9837e2e9c0cSopenharmony_ci 9847e2e9c0cSopenharmony_ci pub fn rename_by_rules(&mut self, rules: RenameAllRules) { 9857e2e9c0cSopenharmony_ci if !self.name.serialize_renamed { 9867e2e9c0cSopenharmony_ci self.name.serialize = rules.serialize.apply_to_variant(&self.name.serialize); 9877e2e9c0cSopenharmony_ci } 9887e2e9c0cSopenharmony_ci if !self.name.deserialize_renamed { 9897e2e9c0cSopenharmony_ci self.name.deserialize = rules.deserialize.apply_to_variant(&self.name.deserialize); 9907e2e9c0cSopenharmony_ci } 9917e2e9c0cSopenharmony_ci self.name 9927e2e9c0cSopenharmony_ci .deserialize_aliases 9937e2e9c0cSopenharmony_ci .insert(self.name.deserialize.clone()); 9947e2e9c0cSopenharmony_ci } 9957e2e9c0cSopenharmony_ci 9967e2e9c0cSopenharmony_ci pub fn rename_all_rules(&self) -> RenameAllRules { 9977e2e9c0cSopenharmony_ci self.rename_all_rules 9987e2e9c0cSopenharmony_ci } 9997e2e9c0cSopenharmony_ci 10007e2e9c0cSopenharmony_ci pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> { 10017e2e9c0cSopenharmony_ci self.ser_bound.as_ref().map(|vec| &vec[..]) 10027e2e9c0cSopenharmony_ci } 10037e2e9c0cSopenharmony_ci 10047e2e9c0cSopenharmony_ci pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { 10057e2e9c0cSopenharmony_ci self.de_bound.as_ref().map(|vec| &vec[..]) 10067e2e9c0cSopenharmony_ci } 10077e2e9c0cSopenharmony_ci 10087e2e9c0cSopenharmony_ci pub fn skip_deserializing(&self) -> bool { 10097e2e9c0cSopenharmony_ci self.skip_deserializing 10107e2e9c0cSopenharmony_ci } 10117e2e9c0cSopenharmony_ci 10127e2e9c0cSopenharmony_ci pub fn skip_serializing(&self) -> bool { 10137e2e9c0cSopenharmony_ci self.skip_serializing 10147e2e9c0cSopenharmony_ci } 10157e2e9c0cSopenharmony_ci 10167e2e9c0cSopenharmony_ci pub fn other(&self) -> bool { 10177e2e9c0cSopenharmony_ci self.other 10187e2e9c0cSopenharmony_ci } 10197e2e9c0cSopenharmony_ci 10207e2e9c0cSopenharmony_ci pub fn serialize_with(&self) -> Option<&syn::ExprPath> { 10217e2e9c0cSopenharmony_ci self.serialize_with.as_ref() 10227e2e9c0cSopenharmony_ci } 10237e2e9c0cSopenharmony_ci 10247e2e9c0cSopenharmony_ci pub fn deserialize_with(&self) -> Option<&syn::ExprPath> { 10257e2e9c0cSopenharmony_ci self.deserialize_with.as_ref() 10267e2e9c0cSopenharmony_ci } 10277e2e9c0cSopenharmony_ci 10287e2e9c0cSopenharmony_ci pub fn untagged(&self) -> bool { 10297e2e9c0cSopenharmony_ci self.untagged 10307e2e9c0cSopenharmony_ci } 10317e2e9c0cSopenharmony_ci} 10327e2e9c0cSopenharmony_ci 10337e2e9c0cSopenharmony_ci/// Represents field attribute information 10347e2e9c0cSopenharmony_cipub struct Field { 10357e2e9c0cSopenharmony_ci name: Name, 10367e2e9c0cSopenharmony_ci skip_serializing: bool, 10377e2e9c0cSopenharmony_ci skip_deserializing: bool, 10387e2e9c0cSopenharmony_ci skip_serializing_if: Option<syn::ExprPath>, 10397e2e9c0cSopenharmony_ci default: Default, 10407e2e9c0cSopenharmony_ci serialize_with: Option<syn::ExprPath>, 10417e2e9c0cSopenharmony_ci deserialize_with: Option<syn::ExprPath>, 10427e2e9c0cSopenharmony_ci ser_bound: Option<Vec<syn::WherePredicate>>, 10437e2e9c0cSopenharmony_ci de_bound: Option<Vec<syn::WherePredicate>>, 10447e2e9c0cSopenharmony_ci borrowed_lifetimes: BTreeSet<syn::Lifetime>, 10457e2e9c0cSopenharmony_ci getter: Option<syn::ExprPath>, 10467e2e9c0cSopenharmony_ci flatten: bool, 10477e2e9c0cSopenharmony_ci transparent: bool, 10487e2e9c0cSopenharmony_ci} 10497e2e9c0cSopenharmony_ci 10507e2e9c0cSopenharmony_ci/// Represents the default to use for a field when deserializing. 10517e2e9c0cSopenharmony_cipub enum Default { 10527e2e9c0cSopenharmony_ci /// Field must always be specified because it does not have a default. 10537e2e9c0cSopenharmony_ci None, 10547e2e9c0cSopenharmony_ci /// The default is given by `std::default::Default::default()`. 10557e2e9c0cSopenharmony_ci Default, 10567e2e9c0cSopenharmony_ci /// The default is given by this function. 10577e2e9c0cSopenharmony_ci Path(syn::ExprPath), 10587e2e9c0cSopenharmony_ci} 10597e2e9c0cSopenharmony_ci 10607e2e9c0cSopenharmony_ciimpl Default { 10617e2e9c0cSopenharmony_ci pub fn is_none(&self) -> bool { 10627e2e9c0cSopenharmony_ci match self { 10637e2e9c0cSopenharmony_ci Default::None => true, 10647e2e9c0cSopenharmony_ci Default::Default | Default::Path(_) => false, 10657e2e9c0cSopenharmony_ci } 10667e2e9c0cSopenharmony_ci } 10677e2e9c0cSopenharmony_ci} 10687e2e9c0cSopenharmony_ci 10697e2e9c0cSopenharmony_ciimpl Field { 10707e2e9c0cSopenharmony_ci /// Extract out the `#[serde(...)]` attributes from a struct field. 10717e2e9c0cSopenharmony_ci pub fn from_ast( 10727e2e9c0cSopenharmony_ci cx: &Ctxt, 10737e2e9c0cSopenharmony_ci index: usize, 10747e2e9c0cSopenharmony_ci field: &syn::Field, 10757e2e9c0cSopenharmony_ci attrs: Option<&Variant>, 10767e2e9c0cSopenharmony_ci container_default: &Default, 10777e2e9c0cSopenharmony_ci ) -> Self { 10787e2e9c0cSopenharmony_ci let mut ser_name = Attr::none(cx, RENAME); 10797e2e9c0cSopenharmony_ci let mut de_name = Attr::none(cx, RENAME); 10807e2e9c0cSopenharmony_ci let mut de_aliases = VecAttr::none(cx, RENAME); 10817e2e9c0cSopenharmony_ci let mut skip_serializing = BoolAttr::none(cx, SKIP_SERIALIZING); 10827e2e9c0cSopenharmony_ci let mut skip_deserializing = BoolAttr::none(cx, SKIP_DESERIALIZING); 10837e2e9c0cSopenharmony_ci let mut skip_serializing_if = Attr::none(cx, SKIP_SERIALIZING_IF); 10847e2e9c0cSopenharmony_ci let mut default = Attr::none(cx, DEFAULT); 10857e2e9c0cSopenharmony_ci let mut serialize_with = Attr::none(cx, SERIALIZE_WITH); 10867e2e9c0cSopenharmony_ci let mut deserialize_with = Attr::none(cx, DESERIALIZE_WITH); 10877e2e9c0cSopenharmony_ci let mut ser_bound = Attr::none(cx, BOUND); 10887e2e9c0cSopenharmony_ci let mut de_bound = Attr::none(cx, BOUND); 10897e2e9c0cSopenharmony_ci let mut borrowed_lifetimes = Attr::none(cx, BORROW); 10907e2e9c0cSopenharmony_ci let mut getter = Attr::none(cx, GETTER); 10917e2e9c0cSopenharmony_ci let mut flatten = BoolAttr::none(cx, FLATTEN); 10927e2e9c0cSopenharmony_ci 10937e2e9c0cSopenharmony_ci let ident = match &field.ident { 10947e2e9c0cSopenharmony_ci Some(ident) => unraw(ident), 10957e2e9c0cSopenharmony_ci None => index.to_string(), 10967e2e9c0cSopenharmony_ci }; 10977e2e9c0cSopenharmony_ci 10987e2e9c0cSopenharmony_ci if let Some(borrow_attribute) = attrs.and_then(|variant| variant.borrow.as_ref()) { 10997e2e9c0cSopenharmony_ci if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { 11007e2e9c0cSopenharmony_ci if let Some(lifetimes) = &borrow_attribute.lifetimes { 11017e2e9c0cSopenharmony_ci for lifetime in lifetimes { 11027e2e9c0cSopenharmony_ci if !borrowable.contains(lifetime) { 11037e2e9c0cSopenharmony_ci let msg = 11047e2e9c0cSopenharmony_ci format!("field `{}` does not have lifetime {}", ident, lifetime); 11057e2e9c0cSopenharmony_ci cx.error_spanned_by(field, msg); 11067e2e9c0cSopenharmony_ci } 11077e2e9c0cSopenharmony_ci } 11087e2e9c0cSopenharmony_ci borrowed_lifetimes.set(&borrow_attribute.path, lifetimes.clone()); 11097e2e9c0cSopenharmony_ci } else { 11107e2e9c0cSopenharmony_ci borrowed_lifetimes.set(&borrow_attribute.path, borrowable); 11117e2e9c0cSopenharmony_ci } 11127e2e9c0cSopenharmony_ci } 11137e2e9c0cSopenharmony_ci } 11147e2e9c0cSopenharmony_ci 11157e2e9c0cSopenharmony_ci for attr in &field.attrs { 11167e2e9c0cSopenharmony_ci if attr.path() != SERDE { 11177e2e9c0cSopenharmony_ci continue; 11187e2e9c0cSopenharmony_ci } 11197e2e9c0cSopenharmony_ci 11207e2e9c0cSopenharmony_ci if let syn::Meta::List(meta) = &attr.meta { 11217e2e9c0cSopenharmony_ci if meta.tokens.is_empty() { 11227e2e9c0cSopenharmony_ci continue; 11237e2e9c0cSopenharmony_ci } 11247e2e9c0cSopenharmony_ci } 11257e2e9c0cSopenharmony_ci 11267e2e9c0cSopenharmony_ci if let Err(err) = attr.parse_nested_meta(|meta| { 11277e2e9c0cSopenharmony_ci if meta.path == RENAME { 11287e2e9c0cSopenharmony_ci // #[serde(rename = "foo")] 11297e2e9c0cSopenharmony_ci // #[serde(rename(serialize = "foo", deserialize = "bar"))] 11307e2e9c0cSopenharmony_ci let (ser, de) = get_multiple_renames(cx, &meta)?; 11317e2e9c0cSopenharmony_ci ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value)); 11327e2e9c0cSopenharmony_ci for de_value in de { 11337e2e9c0cSopenharmony_ci de_name.set_if_none(de_value.value()); 11347e2e9c0cSopenharmony_ci de_aliases.insert(&meta.path, de_value.value()); 11357e2e9c0cSopenharmony_ci } 11367e2e9c0cSopenharmony_ci } else if meta.path == ALIAS { 11377e2e9c0cSopenharmony_ci // #[serde(alias = "foo")] 11387e2e9c0cSopenharmony_ci if let Some(s) = get_lit_str(cx, ALIAS, &meta)? { 11397e2e9c0cSopenharmony_ci de_aliases.insert(&meta.path, s.value()); 11407e2e9c0cSopenharmony_ci } 11417e2e9c0cSopenharmony_ci } else if meta.path == DEFAULT { 11427e2e9c0cSopenharmony_ci if meta.input.peek(Token![=]) { 11437e2e9c0cSopenharmony_ci // #[serde(default = "...")] 11447e2e9c0cSopenharmony_ci if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? { 11457e2e9c0cSopenharmony_ci default.set(&meta.path, Default::Path(path)); 11467e2e9c0cSopenharmony_ci } 11477e2e9c0cSopenharmony_ci } else { 11487e2e9c0cSopenharmony_ci // #[serde(default)] 11497e2e9c0cSopenharmony_ci default.set(&meta.path, Default::Default); 11507e2e9c0cSopenharmony_ci } 11517e2e9c0cSopenharmony_ci } else if meta.path == SKIP_SERIALIZING { 11527e2e9c0cSopenharmony_ci // #[serde(skip_serializing)] 11537e2e9c0cSopenharmony_ci skip_serializing.set_true(&meta.path); 11547e2e9c0cSopenharmony_ci } else if meta.path == SKIP_DESERIALIZING { 11557e2e9c0cSopenharmony_ci // #[serde(skip_deserializing)] 11567e2e9c0cSopenharmony_ci skip_deserializing.set_true(&meta.path); 11577e2e9c0cSopenharmony_ci } else if meta.path == SKIP { 11587e2e9c0cSopenharmony_ci // #[serde(skip)] 11597e2e9c0cSopenharmony_ci skip_serializing.set_true(&meta.path); 11607e2e9c0cSopenharmony_ci skip_deserializing.set_true(&meta.path); 11617e2e9c0cSopenharmony_ci } else if meta.path == SKIP_SERIALIZING_IF { 11627e2e9c0cSopenharmony_ci // #[serde(skip_serializing_if = "...")] 11637e2e9c0cSopenharmony_ci if let Some(path) = parse_lit_into_expr_path(cx, SKIP_SERIALIZING_IF, &meta)? { 11647e2e9c0cSopenharmony_ci skip_serializing_if.set(&meta.path, path); 11657e2e9c0cSopenharmony_ci } 11667e2e9c0cSopenharmony_ci } else if meta.path == SERIALIZE_WITH { 11677e2e9c0cSopenharmony_ci // #[serde(serialize_with = "...")] 11687e2e9c0cSopenharmony_ci if let Some(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &meta)? { 11697e2e9c0cSopenharmony_ci serialize_with.set(&meta.path, path); 11707e2e9c0cSopenharmony_ci } 11717e2e9c0cSopenharmony_ci } else if meta.path == DESERIALIZE_WITH { 11727e2e9c0cSopenharmony_ci // #[serde(deserialize_with = "...")] 11737e2e9c0cSopenharmony_ci if let Some(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &meta)? { 11747e2e9c0cSopenharmony_ci deserialize_with.set(&meta.path, path); 11757e2e9c0cSopenharmony_ci } 11767e2e9c0cSopenharmony_ci } else if meta.path == WITH { 11777e2e9c0cSopenharmony_ci // #[serde(with = "...")] 11787e2e9c0cSopenharmony_ci if let Some(path) = parse_lit_into_expr_path(cx, WITH, &meta)? { 11797e2e9c0cSopenharmony_ci let mut ser_path = path.clone(); 11807e2e9c0cSopenharmony_ci ser_path 11817e2e9c0cSopenharmony_ci .path 11827e2e9c0cSopenharmony_ci .segments 11837e2e9c0cSopenharmony_ci .push(Ident::new("serialize", Span::call_site()).into()); 11847e2e9c0cSopenharmony_ci serialize_with.set(&meta.path, ser_path); 11857e2e9c0cSopenharmony_ci let mut de_path = path; 11867e2e9c0cSopenharmony_ci de_path 11877e2e9c0cSopenharmony_ci .path 11887e2e9c0cSopenharmony_ci .segments 11897e2e9c0cSopenharmony_ci .push(Ident::new("deserialize", Span::call_site()).into()); 11907e2e9c0cSopenharmony_ci deserialize_with.set(&meta.path, de_path); 11917e2e9c0cSopenharmony_ci } 11927e2e9c0cSopenharmony_ci } else if meta.path == BOUND { 11937e2e9c0cSopenharmony_ci // #[serde(bound = "T: SomeBound")] 11947e2e9c0cSopenharmony_ci // #[serde(bound(serialize = "...", deserialize = "..."))] 11957e2e9c0cSopenharmony_ci let (ser, de) = get_where_predicates(cx, &meta)?; 11967e2e9c0cSopenharmony_ci ser_bound.set_opt(&meta.path, ser); 11977e2e9c0cSopenharmony_ci de_bound.set_opt(&meta.path, de); 11987e2e9c0cSopenharmony_ci } else if meta.path == BORROW { 11997e2e9c0cSopenharmony_ci if meta.input.peek(Token![=]) { 12007e2e9c0cSopenharmony_ci // #[serde(borrow = "'a + 'b")] 12017e2e9c0cSopenharmony_ci let lifetimes = parse_lit_into_lifetimes(cx, &meta)?; 12027e2e9c0cSopenharmony_ci if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { 12037e2e9c0cSopenharmony_ci for lifetime in &lifetimes { 12047e2e9c0cSopenharmony_ci if !borrowable.contains(lifetime) { 12057e2e9c0cSopenharmony_ci let msg = format!( 12067e2e9c0cSopenharmony_ci "field `{}` does not have lifetime {}", 12077e2e9c0cSopenharmony_ci ident, lifetime, 12087e2e9c0cSopenharmony_ci ); 12097e2e9c0cSopenharmony_ci cx.error_spanned_by(field, msg); 12107e2e9c0cSopenharmony_ci } 12117e2e9c0cSopenharmony_ci } 12127e2e9c0cSopenharmony_ci borrowed_lifetimes.set(&meta.path, lifetimes); 12137e2e9c0cSopenharmony_ci } 12147e2e9c0cSopenharmony_ci } else { 12157e2e9c0cSopenharmony_ci // #[serde(borrow)] 12167e2e9c0cSopenharmony_ci if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { 12177e2e9c0cSopenharmony_ci borrowed_lifetimes.set(&meta.path, borrowable); 12187e2e9c0cSopenharmony_ci } 12197e2e9c0cSopenharmony_ci } 12207e2e9c0cSopenharmony_ci } else if meta.path == GETTER { 12217e2e9c0cSopenharmony_ci // #[serde(getter = "...")] 12227e2e9c0cSopenharmony_ci if let Some(path) = parse_lit_into_expr_path(cx, GETTER, &meta)? { 12237e2e9c0cSopenharmony_ci getter.set(&meta.path, path); 12247e2e9c0cSopenharmony_ci } 12257e2e9c0cSopenharmony_ci } else if meta.path == FLATTEN { 12267e2e9c0cSopenharmony_ci // #[serde(flatten)] 12277e2e9c0cSopenharmony_ci flatten.set_true(&meta.path); 12287e2e9c0cSopenharmony_ci } else { 12297e2e9c0cSopenharmony_ci let path = meta.path.to_token_stream().to_string().replace(' ', ""); 12307e2e9c0cSopenharmony_ci return Err( 12317e2e9c0cSopenharmony_ci meta.error(format_args!("unknown serde field attribute `{}`", path)) 12327e2e9c0cSopenharmony_ci ); 12337e2e9c0cSopenharmony_ci } 12347e2e9c0cSopenharmony_ci Ok(()) 12357e2e9c0cSopenharmony_ci }) { 12367e2e9c0cSopenharmony_ci cx.syn_error(err); 12377e2e9c0cSopenharmony_ci } 12387e2e9c0cSopenharmony_ci } 12397e2e9c0cSopenharmony_ci 12407e2e9c0cSopenharmony_ci // Is skip_deserializing, initialize the field to Default::default() unless a 12417e2e9c0cSopenharmony_ci // different default is specified by `#[serde(default = "...")]` on 12427e2e9c0cSopenharmony_ci // ourselves or our container (e.g. the struct we are in). 12437e2e9c0cSopenharmony_ci if let Default::None = *container_default { 12447e2e9c0cSopenharmony_ci if skip_deserializing.0.value.is_some() { 12457e2e9c0cSopenharmony_ci default.set_if_none(Default::Default); 12467e2e9c0cSopenharmony_ci } 12477e2e9c0cSopenharmony_ci } 12487e2e9c0cSopenharmony_ci 12497e2e9c0cSopenharmony_ci let mut borrowed_lifetimes = borrowed_lifetimes.get().unwrap_or_default(); 12507e2e9c0cSopenharmony_ci if !borrowed_lifetimes.is_empty() { 12517e2e9c0cSopenharmony_ci // Cow<str> and Cow<[u8]> never borrow by default: 12527e2e9c0cSopenharmony_ci // 12537e2e9c0cSopenharmony_ci // impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T> 12547e2e9c0cSopenharmony_ci // 12557e2e9c0cSopenharmony_ci // A #[serde(borrow)] attribute enables borrowing that corresponds 12567e2e9c0cSopenharmony_ci // roughly to these impls: 12577e2e9c0cSopenharmony_ci // 12587e2e9c0cSopenharmony_ci // impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, str> 12597e2e9c0cSopenharmony_ci // impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, [u8]> 12607e2e9c0cSopenharmony_ci if is_cow(&field.ty, is_str) { 12617e2e9c0cSopenharmony_ci let mut path = syn::Path { 12627e2e9c0cSopenharmony_ci leading_colon: None, 12637e2e9c0cSopenharmony_ci segments: Punctuated::new(), 12647e2e9c0cSopenharmony_ci }; 12657e2e9c0cSopenharmony_ci let span = Span::call_site(); 12667e2e9c0cSopenharmony_ci path.segments.push(Ident::new("_serde", span).into()); 12677e2e9c0cSopenharmony_ci path.segments.push(Ident::new("__private", span).into()); 12687e2e9c0cSopenharmony_ci path.segments.push(Ident::new("de", span).into()); 12697e2e9c0cSopenharmony_ci path.segments 12707e2e9c0cSopenharmony_ci .push(Ident::new("borrow_cow_str", span).into()); 12717e2e9c0cSopenharmony_ci let expr = syn::ExprPath { 12727e2e9c0cSopenharmony_ci attrs: Vec::new(), 12737e2e9c0cSopenharmony_ci qself: None, 12747e2e9c0cSopenharmony_ci path, 12757e2e9c0cSopenharmony_ci }; 12767e2e9c0cSopenharmony_ci deserialize_with.set_if_none(expr); 12777e2e9c0cSopenharmony_ci } else if is_cow(&field.ty, is_slice_u8) { 12787e2e9c0cSopenharmony_ci let mut path = syn::Path { 12797e2e9c0cSopenharmony_ci leading_colon: None, 12807e2e9c0cSopenharmony_ci segments: Punctuated::new(), 12817e2e9c0cSopenharmony_ci }; 12827e2e9c0cSopenharmony_ci let span = Span::call_site(); 12837e2e9c0cSopenharmony_ci path.segments.push(Ident::new("_serde", span).into()); 12847e2e9c0cSopenharmony_ci path.segments.push(Ident::new("__private", span).into()); 12857e2e9c0cSopenharmony_ci path.segments.push(Ident::new("de", span).into()); 12867e2e9c0cSopenharmony_ci path.segments 12877e2e9c0cSopenharmony_ci .push(Ident::new("borrow_cow_bytes", span).into()); 12887e2e9c0cSopenharmony_ci let expr = syn::ExprPath { 12897e2e9c0cSopenharmony_ci attrs: Vec::new(), 12907e2e9c0cSopenharmony_ci qself: None, 12917e2e9c0cSopenharmony_ci path, 12927e2e9c0cSopenharmony_ci }; 12937e2e9c0cSopenharmony_ci deserialize_with.set_if_none(expr); 12947e2e9c0cSopenharmony_ci } 12957e2e9c0cSopenharmony_ci } else if is_implicitly_borrowed(&field.ty) { 12967e2e9c0cSopenharmony_ci // Types &str and &[u8] are always implicitly borrowed. No need for 12977e2e9c0cSopenharmony_ci // a #[serde(borrow)]. 12987e2e9c0cSopenharmony_ci collect_lifetimes(&field.ty, &mut borrowed_lifetimes); 12997e2e9c0cSopenharmony_ci } 13007e2e9c0cSopenharmony_ci 13017e2e9c0cSopenharmony_ci Field { 13027e2e9c0cSopenharmony_ci name: Name::from_attrs(ident, ser_name, de_name, Some(de_aliases)), 13037e2e9c0cSopenharmony_ci skip_serializing: skip_serializing.get(), 13047e2e9c0cSopenharmony_ci skip_deserializing: skip_deserializing.get(), 13057e2e9c0cSopenharmony_ci skip_serializing_if: skip_serializing_if.get(), 13067e2e9c0cSopenharmony_ci default: default.get().unwrap_or(Default::None), 13077e2e9c0cSopenharmony_ci serialize_with: serialize_with.get(), 13087e2e9c0cSopenharmony_ci deserialize_with: deserialize_with.get(), 13097e2e9c0cSopenharmony_ci ser_bound: ser_bound.get(), 13107e2e9c0cSopenharmony_ci de_bound: de_bound.get(), 13117e2e9c0cSopenharmony_ci borrowed_lifetimes, 13127e2e9c0cSopenharmony_ci getter: getter.get(), 13137e2e9c0cSopenharmony_ci flatten: flatten.get(), 13147e2e9c0cSopenharmony_ci transparent: false, 13157e2e9c0cSopenharmony_ci } 13167e2e9c0cSopenharmony_ci } 13177e2e9c0cSopenharmony_ci 13187e2e9c0cSopenharmony_ci pub fn name(&self) -> &Name { 13197e2e9c0cSopenharmony_ci &self.name 13207e2e9c0cSopenharmony_ci } 13217e2e9c0cSopenharmony_ci 13227e2e9c0cSopenharmony_ci pub fn aliases(&self) -> &BTreeSet<String> { 13237e2e9c0cSopenharmony_ci self.name.deserialize_aliases() 13247e2e9c0cSopenharmony_ci } 13257e2e9c0cSopenharmony_ci 13267e2e9c0cSopenharmony_ci pub fn rename_by_rules(&mut self, rules: RenameAllRules) { 13277e2e9c0cSopenharmony_ci if !self.name.serialize_renamed { 13287e2e9c0cSopenharmony_ci self.name.serialize = rules.serialize.apply_to_field(&self.name.serialize); 13297e2e9c0cSopenharmony_ci } 13307e2e9c0cSopenharmony_ci if !self.name.deserialize_renamed { 13317e2e9c0cSopenharmony_ci self.name.deserialize = rules.deserialize.apply_to_field(&self.name.deserialize); 13327e2e9c0cSopenharmony_ci } 13337e2e9c0cSopenharmony_ci self.name 13347e2e9c0cSopenharmony_ci .deserialize_aliases 13357e2e9c0cSopenharmony_ci .insert(self.name.deserialize.clone()); 13367e2e9c0cSopenharmony_ci } 13377e2e9c0cSopenharmony_ci 13387e2e9c0cSopenharmony_ci pub fn skip_serializing(&self) -> bool { 13397e2e9c0cSopenharmony_ci self.skip_serializing 13407e2e9c0cSopenharmony_ci } 13417e2e9c0cSopenharmony_ci 13427e2e9c0cSopenharmony_ci pub fn skip_deserializing(&self) -> bool { 13437e2e9c0cSopenharmony_ci self.skip_deserializing 13447e2e9c0cSopenharmony_ci } 13457e2e9c0cSopenharmony_ci 13467e2e9c0cSopenharmony_ci pub fn skip_serializing_if(&self) -> Option<&syn::ExprPath> { 13477e2e9c0cSopenharmony_ci self.skip_serializing_if.as_ref() 13487e2e9c0cSopenharmony_ci } 13497e2e9c0cSopenharmony_ci 13507e2e9c0cSopenharmony_ci pub fn default(&self) -> &Default { 13517e2e9c0cSopenharmony_ci &self.default 13527e2e9c0cSopenharmony_ci } 13537e2e9c0cSopenharmony_ci 13547e2e9c0cSopenharmony_ci pub fn serialize_with(&self) -> Option<&syn::ExprPath> { 13557e2e9c0cSopenharmony_ci self.serialize_with.as_ref() 13567e2e9c0cSopenharmony_ci } 13577e2e9c0cSopenharmony_ci 13587e2e9c0cSopenharmony_ci pub fn deserialize_with(&self) -> Option<&syn::ExprPath> { 13597e2e9c0cSopenharmony_ci self.deserialize_with.as_ref() 13607e2e9c0cSopenharmony_ci } 13617e2e9c0cSopenharmony_ci 13627e2e9c0cSopenharmony_ci pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> { 13637e2e9c0cSopenharmony_ci self.ser_bound.as_ref().map(|vec| &vec[..]) 13647e2e9c0cSopenharmony_ci } 13657e2e9c0cSopenharmony_ci 13667e2e9c0cSopenharmony_ci pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { 13677e2e9c0cSopenharmony_ci self.de_bound.as_ref().map(|vec| &vec[..]) 13687e2e9c0cSopenharmony_ci } 13697e2e9c0cSopenharmony_ci 13707e2e9c0cSopenharmony_ci pub fn borrowed_lifetimes(&self) -> &BTreeSet<syn::Lifetime> { 13717e2e9c0cSopenharmony_ci &self.borrowed_lifetimes 13727e2e9c0cSopenharmony_ci } 13737e2e9c0cSopenharmony_ci 13747e2e9c0cSopenharmony_ci pub fn getter(&self) -> Option<&syn::ExprPath> { 13757e2e9c0cSopenharmony_ci self.getter.as_ref() 13767e2e9c0cSopenharmony_ci } 13777e2e9c0cSopenharmony_ci 13787e2e9c0cSopenharmony_ci pub fn flatten(&self) -> bool { 13797e2e9c0cSopenharmony_ci self.flatten 13807e2e9c0cSopenharmony_ci } 13817e2e9c0cSopenharmony_ci 13827e2e9c0cSopenharmony_ci pub fn transparent(&self) -> bool { 13837e2e9c0cSopenharmony_ci self.transparent 13847e2e9c0cSopenharmony_ci } 13857e2e9c0cSopenharmony_ci 13867e2e9c0cSopenharmony_ci pub fn mark_transparent(&mut self) { 13877e2e9c0cSopenharmony_ci self.transparent = true; 13887e2e9c0cSopenharmony_ci } 13897e2e9c0cSopenharmony_ci} 13907e2e9c0cSopenharmony_ci 13917e2e9c0cSopenharmony_citype SerAndDe<T> = (Option<T>, Option<T>); 13927e2e9c0cSopenharmony_ci 13937e2e9c0cSopenharmony_cifn get_ser_and_de<'c, T, F, R>( 13947e2e9c0cSopenharmony_ci cx: &'c Ctxt, 13957e2e9c0cSopenharmony_ci attr_name: Symbol, 13967e2e9c0cSopenharmony_ci meta: &ParseNestedMeta, 13977e2e9c0cSopenharmony_ci f: F, 13987e2e9c0cSopenharmony_ci) -> syn::Result<(VecAttr<'c, T>, VecAttr<'c, T>)> 13997e2e9c0cSopenharmony_ciwhere 14007e2e9c0cSopenharmony_ci T: Clone, 14017e2e9c0cSopenharmony_ci F: Fn(&Ctxt, Symbol, Symbol, &ParseNestedMeta) -> syn::Result<R>, 14027e2e9c0cSopenharmony_ci R: Into<Option<T>>, 14037e2e9c0cSopenharmony_ci{ 14047e2e9c0cSopenharmony_ci let mut ser_meta = VecAttr::none(cx, attr_name); 14057e2e9c0cSopenharmony_ci let mut de_meta = VecAttr::none(cx, attr_name); 14067e2e9c0cSopenharmony_ci 14077e2e9c0cSopenharmony_ci let lookahead = meta.input.lookahead1(); 14087e2e9c0cSopenharmony_ci if lookahead.peek(Token![=]) { 14097e2e9c0cSopenharmony_ci if let Some(both) = f(cx, attr_name, attr_name, meta)?.into() { 14107e2e9c0cSopenharmony_ci ser_meta.insert(&meta.path, both.clone()); 14117e2e9c0cSopenharmony_ci de_meta.insert(&meta.path, both); 14127e2e9c0cSopenharmony_ci } 14137e2e9c0cSopenharmony_ci } else if lookahead.peek(token::Paren) { 14147e2e9c0cSopenharmony_ci meta.parse_nested_meta(|meta| { 14157e2e9c0cSopenharmony_ci if meta.path == SERIALIZE { 14167e2e9c0cSopenharmony_ci if let Some(v) = f(cx, attr_name, SERIALIZE, &meta)?.into() { 14177e2e9c0cSopenharmony_ci ser_meta.insert(&meta.path, v); 14187e2e9c0cSopenharmony_ci } 14197e2e9c0cSopenharmony_ci } else if meta.path == DESERIALIZE { 14207e2e9c0cSopenharmony_ci if let Some(v) = f(cx, attr_name, DESERIALIZE, &meta)?.into() { 14217e2e9c0cSopenharmony_ci de_meta.insert(&meta.path, v); 14227e2e9c0cSopenharmony_ci } 14237e2e9c0cSopenharmony_ci } else { 14247e2e9c0cSopenharmony_ci return Err(meta.error(format_args!( 14257e2e9c0cSopenharmony_ci "malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`", 14267e2e9c0cSopenharmony_ci attr_name, 14277e2e9c0cSopenharmony_ci ))); 14287e2e9c0cSopenharmony_ci } 14297e2e9c0cSopenharmony_ci Ok(()) 14307e2e9c0cSopenharmony_ci })?; 14317e2e9c0cSopenharmony_ci } else { 14327e2e9c0cSopenharmony_ci return Err(lookahead.error()); 14337e2e9c0cSopenharmony_ci } 14347e2e9c0cSopenharmony_ci 14357e2e9c0cSopenharmony_ci Ok((ser_meta, de_meta)) 14367e2e9c0cSopenharmony_ci} 14377e2e9c0cSopenharmony_ci 14387e2e9c0cSopenharmony_cifn get_renames( 14397e2e9c0cSopenharmony_ci cx: &Ctxt, 14407e2e9c0cSopenharmony_ci attr_name: Symbol, 14417e2e9c0cSopenharmony_ci meta: &ParseNestedMeta, 14427e2e9c0cSopenharmony_ci) -> syn::Result<SerAndDe<syn::LitStr>> { 14437e2e9c0cSopenharmony_ci let (ser, de) = get_ser_and_de(cx, attr_name, meta, get_lit_str2)?; 14447e2e9c0cSopenharmony_ci Ok((ser.at_most_one(), de.at_most_one())) 14457e2e9c0cSopenharmony_ci} 14467e2e9c0cSopenharmony_ci 14477e2e9c0cSopenharmony_cifn get_multiple_renames( 14487e2e9c0cSopenharmony_ci cx: &Ctxt, 14497e2e9c0cSopenharmony_ci meta: &ParseNestedMeta, 14507e2e9c0cSopenharmony_ci) -> syn::Result<(Option<syn::LitStr>, Vec<syn::LitStr>)> { 14517e2e9c0cSopenharmony_ci let (ser, de) = get_ser_and_de(cx, RENAME, meta, get_lit_str2)?; 14527e2e9c0cSopenharmony_ci Ok((ser.at_most_one(), de.get())) 14537e2e9c0cSopenharmony_ci} 14547e2e9c0cSopenharmony_ci 14557e2e9c0cSopenharmony_cifn get_where_predicates( 14567e2e9c0cSopenharmony_ci cx: &Ctxt, 14577e2e9c0cSopenharmony_ci meta: &ParseNestedMeta, 14587e2e9c0cSopenharmony_ci) -> syn::Result<SerAndDe<Vec<syn::WherePredicate>>> { 14597e2e9c0cSopenharmony_ci let (ser, de) = get_ser_and_de(cx, BOUND, meta, parse_lit_into_where)?; 14607e2e9c0cSopenharmony_ci Ok((ser.at_most_one(), de.at_most_one())) 14617e2e9c0cSopenharmony_ci} 14627e2e9c0cSopenharmony_ci 14637e2e9c0cSopenharmony_cifn get_lit_str( 14647e2e9c0cSopenharmony_ci cx: &Ctxt, 14657e2e9c0cSopenharmony_ci attr_name: Symbol, 14667e2e9c0cSopenharmony_ci meta: &ParseNestedMeta, 14677e2e9c0cSopenharmony_ci) -> syn::Result<Option<syn::LitStr>> { 14687e2e9c0cSopenharmony_ci get_lit_str2(cx, attr_name, attr_name, meta) 14697e2e9c0cSopenharmony_ci} 14707e2e9c0cSopenharmony_ci 14717e2e9c0cSopenharmony_cifn get_lit_str2( 14727e2e9c0cSopenharmony_ci cx: &Ctxt, 14737e2e9c0cSopenharmony_ci attr_name: Symbol, 14747e2e9c0cSopenharmony_ci meta_item_name: Symbol, 14757e2e9c0cSopenharmony_ci meta: &ParseNestedMeta, 14767e2e9c0cSopenharmony_ci) -> syn::Result<Option<syn::LitStr>> { 14777e2e9c0cSopenharmony_ci let expr: syn::Expr = meta.value()?.parse()?; 14787e2e9c0cSopenharmony_ci let mut value = &expr; 14797e2e9c0cSopenharmony_ci while let syn::Expr::Group(e) = value { 14807e2e9c0cSopenharmony_ci value = &e.expr; 14817e2e9c0cSopenharmony_ci } 14827e2e9c0cSopenharmony_ci if let syn::Expr::Lit(syn::ExprLit { 14837e2e9c0cSopenharmony_ci lit: syn::Lit::Str(lit), 14847e2e9c0cSopenharmony_ci .. 14857e2e9c0cSopenharmony_ci }) = value 14867e2e9c0cSopenharmony_ci { 14877e2e9c0cSopenharmony_ci let suffix = lit.suffix(); 14887e2e9c0cSopenharmony_ci if !suffix.is_empty() { 14897e2e9c0cSopenharmony_ci cx.error_spanned_by( 14907e2e9c0cSopenharmony_ci lit, 14917e2e9c0cSopenharmony_ci format!("unexpected suffix `{}` on string literal", suffix), 14927e2e9c0cSopenharmony_ci ); 14937e2e9c0cSopenharmony_ci } 14947e2e9c0cSopenharmony_ci Ok(Some(lit.clone())) 14957e2e9c0cSopenharmony_ci } else { 14967e2e9c0cSopenharmony_ci cx.error_spanned_by( 14977e2e9c0cSopenharmony_ci expr, 14987e2e9c0cSopenharmony_ci format!( 14997e2e9c0cSopenharmony_ci "expected serde {} attribute to be a string: `{} = \"...\"`", 15007e2e9c0cSopenharmony_ci attr_name, meta_item_name 15017e2e9c0cSopenharmony_ci ), 15027e2e9c0cSopenharmony_ci ); 15037e2e9c0cSopenharmony_ci Ok(None) 15047e2e9c0cSopenharmony_ci } 15057e2e9c0cSopenharmony_ci} 15067e2e9c0cSopenharmony_ci 15077e2e9c0cSopenharmony_cifn parse_lit_into_path( 15087e2e9c0cSopenharmony_ci cx: &Ctxt, 15097e2e9c0cSopenharmony_ci attr_name: Symbol, 15107e2e9c0cSopenharmony_ci meta: &ParseNestedMeta, 15117e2e9c0cSopenharmony_ci) -> syn::Result<Option<syn::Path>> { 15127e2e9c0cSopenharmony_ci let string = match get_lit_str(cx, attr_name, meta)? { 15137e2e9c0cSopenharmony_ci Some(string) => string, 15147e2e9c0cSopenharmony_ci None => return Ok(None), 15157e2e9c0cSopenharmony_ci }; 15167e2e9c0cSopenharmony_ci 15177e2e9c0cSopenharmony_ci Ok(match string.parse() { 15187e2e9c0cSopenharmony_ci Ok(path) => Some(path), 15197e2e9c0cSopenharmony_ci Err(_) => { 15207e2e9c0cSopenharmony_ci cx.error_spanned_by( 15217e2e9c0cSopenharmony_ci &string, 15227e2e9c0cSopenharmony_ci format!("failed to parse path: {:?}", string.value()), 15237e2e9c0cSopenharmony_ci ); 15247e2e9c0cSopenharmony_ci None 15257e2e9c0cSopenharmony_ci } 15267e2e9c0cSopenharmony_ci }) 15277e2e9c0cSopenharmony_ci} 15287e2e9c0cSopenharmony_ci 15297e2e9c0cSopenharmony_cifn parse_lit_into_expr_path( 15307e2e9c0cSopenharmony_ci cx: &Ctxt, 15317e2e9c0cSopenharmony_ci attr_name: Symbol, 15327e2e9c0cSopenharmony_ci meta: &ParseNestedMeta, 15337e2e9c0cSopenharmony_ci) -> syn::Result<Option<syn::ExprPath>> { 15347e2e9c0cSopenharmony_ci let string = match get_lit_str(cx, attr_name, meta)? { 15357e2e9c0cSopenharmony_ci Some(string) => string, 15367e2e9c0cSopenharmony_ci None => return Ok(None), 15377e2e9c0cSopenharmony_ci }; 15387e2e9c0cSopenharmony_ci 15397e2e9c0cSopenharmony_ci Ok(match string.parse() { 15407e2e9c0cSopenharmony_ci Ok(expr) => Some(expr), 15417e2e9c0cSopenharmony_ci Err(_) => { 15427e2e9c0cSopenharmony_ci cx.error_spanned_by( 15437e2e9c0cSopenharmony_ci &string, 15447e2e9c0cSopenharmony_ci format!("failed to parse path: {:?}", string.value()), 15457e2e9c0cSopenharmony_ci ); 15467e2e9c0cSopenharmony_ci None 15477e2e9c0cSopenharmony_ci } 15487e2e9c0cSopenharmony_ci }) 15497e2e9c0cSopenharmony_ci} 15507e2e9c0cSopenharmony_ci 15517e2e9c0cSopenharmony_cifn parse_lit_into_where( 15527e2e9c0cSopenharmony_ci cx: &Ctxt, 15537e2e9c0cSopenharmony_ci attr_name: Symbol, 15547e2e9c0cSopenharmony_ci meta_item_name: Symbol, 15557e2e9c0cSopenharmony_ci meta: &ParseNestedMeta, 15567e2e9c0cSopenharmony_ci) -> syn::Result<Vec<syn::WherePredicate>> { 15577e2e9c0cSopenharmony_ci let string = match get_lit_str2(cx, attr_name, meta_item_name, meta)? { 15587e2e9c0cSopenharmony_ci Some(string) => string, 15597e2e9c0cSopenharmony_ci None => return Ok(Vec::new()), 15607e2e9c0cSopenharmony_ci }; 15617e2e9c0cSopenharmony_ci 15627e2e9c0cSopenharmony_ci Ok( 15637e2e9c0cSopenharmony_ci match string.parse_with(Punctuated::<syn::WherePredicate, Token![,]>::parse_terminated) { 15647e2e9c0cSopenharmony_ci Ok(predicates) => Vec::from_iter(predicates), 15657e2e9c0cSopenharmony_ci Err(err) => { 15667e2e9c0cSopenharmony_ci cx.error_spanned_by(string, err); 15677e2e9c0cSopenharmony_ci Vec::new() 15687e2e9c0cSopenharmony_ci } 15697e2e9c0cSopenharmony_ci }, 15707e2e9c0cSopenharmony_ci ) 15717e2e9c0cSopenharmony_ci} 15727e2e9c0cSopenharmony_ci 15737e2e9c0cSopenharmony_cifn parse_lit_into_ty( 15747e2e9c0cSopenharmony_ci cx: &Ctxt, 15757e2e9c0cSopenharmony_ci attr_name: Symbol, 15767e2e9c0cSopenharmony_ci meta: &ParseNestedMeta, 15777e2e9c0cSopenharmony_ci) -> syn::Result<Option<syn::Type>> { 15787e2e9c0cSopenharmony_ci let string = match get_lit_str(cx, attr_name, meta)? { 15797e2e9c0cSopenharmony_ci Some(string) => string, 15807e2e9c0cSopenharmony_ci None => return Ok(None), 15817e2e9c0cSopenharmony_ci }; 15827e2e9c0cSopenharmony_ci 15837e2e9c0cSopenharmony_ci Ok(match string.parse() { 15847e2e9c0cSopenharmony_ci Ok(ty) => Some(ty), 15857e2e9c0cSopenharmony_ci Err(_) => { 15867e2e9c0cSopenharmony_ci cx.error_spanned_by( 15877e2e9c0cSopenharmony_ci &string, 15887e2e9c0cSopenharmony_ci format!("failed to parse type: {} = {:?}", attr_name, string.value()), 15897e2e9c0cSopenharmony_ci ); 15907e2e9c0cSopenharmony_ci None 15917e2e9c0cSopenharmony_ci } 15927e2e9c0cSopenharmony_ci }) 15937e2e9c0cSopenharmony_ci} 15947e2e9c0cSopenharmony_ci 15957e2e9c0cSopenharmony_ci// Parses a string literal like "'a + 'b + 'c" containing a nonempty list of 15967e2e9c0cSopenharmony_ci// lifetimes separated by `+`. 15977e2e9c0cSopenharmony_cifn parse_lit_into_lifetimes( 15987e2e9c0cSopenharmony_ci cx: &Ctxt, 15997e2e9c0cSopenharmony_ci meta: &ParseNestedMeta, 16007e2e9c0cSopenharmony_ci) -> syn::Result<BTreeSet<syn::Lifetime>> { 16017e2e9c0cSopenharmony_ci let string = match get_lit_str(cx, BORROW, meta)? { 16027e2e9c0cSopenharmony_ci Some(string) => string, 16037e2e9c0cSopenharmony_ci None => return Ok(BTreeSet::new()), 16047e2e9c0cSopenharmony_ci }; 16057e2e9c0cSopenharmony_ci 16067e2e9c0cSopenharmony_ci if let Ok(lifetimes) = string.parse_with(|input: ParseStream| { 16077e2e9c0cSopenharmony_ci let mut set = BTreeSet::new(); 16087e2e9c0cSopenharmony_ci while !input.is_empty() { 16097e2e9c0cSopenharmony_ci let lifetime: Lifetime = input.parse()?; 16107e2e9c0cSopenharmony_ci if !set.insert(lifetime.clone()) { 16117e2e9c0cSopenharmony_ci cx.error_spanned_by( 16127e2e9c0cSopenharmony_ci &string, 16137e2e9c0cSopenharmony_ci format!("duplicate borrowed lifetime `{}`", lifetime), 16147e2e9c0cSopenharmony_ci ); 16157e2e9c0cSopenharmony_ci } 16167e2e9c0cSopenharmony_ci if input.is_empty() { 16177e2e9c0cSopenharmony_ci break; 16187e2e9c0cSopenharmony_ci } 16197e2e9c0cSopenharmony_ci input.parse::<Token![+]>()?; 16207e2e9c0cSopenharmony_ci } 16217e2e9c0cSopenharmony_ci Ok(set) 16227e2e9c0cSopenharmony_ci }) { 16237e2e9c0cSopenharmony_ci if lifetimes.is_empty() { 16247e2e9c0cSopenharmony_ci cx.error_spanned_by(string, "at least one lifetime must be borrowed"); 16257e2e9c0cSopenharmony_ci } 16267e2e9c0cSopenharmony_ci return Ok(lifetimes); 16277e2e9c0cSopenharmony_ci } 16287e2e9c0cSopenharmony_ci 16297e2e9c0cSopenharmony_ci cx.error_spanned_by( 16307e2e9c0cSopenharmony_ci &string, 16317e2e9c0cSopenharmony_ci format!("failed to parse borrowed lifetimes: {:?}", string.value()), 16327e2e9c0cSopenharmony_ci ); 16337e2e9c0cSopenharmony_ci Ok(BTreeSet::new()) 16347e2e9c0cSopenharmony_ci} 16357e2e9c0cSopenharmony_ci 16367e2e9c0cSopenharmony_cifn is_implicitly_borrowed(ty: &syn::Type) -> bool { 16377e2e9c0cSopenharmony_ci is_implicitly_borrowed_reference(ty) || is_option(ty, is_implicitly_borrowed_reference) 16387e2e9c0cSopenharmony_ci} 16397e2e9c0cSopenharmony_ci 16407e2e9c0cSopenharmony_cifn is_implicitly_borrowed_reference(ty: &syn::Type) -> bool { 16417e2e9c0cSopenharmony_ci is_reference(ty, is_str) || is_reference(ty, is_slice_u8) 16427e2e9c0cSopenharmony_ci} 16437e2e9c0cSopenharmony_ci 16447e2e9c0cSopenharmony_ci// Whether the type looks like it might be `std::borrow::Cow<T>` where elem="T". 16457e2e9c0cSopenharmony_ci// This can have false negatives and false positives. 16467e2e9c0cSopenharmony_ci// 16477e2e9c0cSopenharmony_ci// False negative: 16487e2e9c0cSopenharmony_ci// 16497e2e9c0cSopenharmony_ci// use std::borrow::Cow as Pig; 16507e2e9c0cSopenharmony_ci// 16517e2e9c0cSopenharmony_ci// #[derive(Deserialize)] 16527e2e9c0cSopenharmony_ci// struct S<'a> { 16537e2e9c0cSopenharmony_ci// #[serde(borrow)] 16547e2e9c0cSopenharmony_ci// pig: Pig<'a, str>, 16557e2e9c0cSopenharmony_ci// } 16567e2e9c0cSopenharmony_ci// 16577e2e9c0cSopenharmony_ci// False positive: 16587e2e9c0cSopenharmony_ci// 16597e2e9c0cSopenharmony_ci// type str = [i16]; 16607e2e9c0cSopenharmony_ci// 16617e2e9c0cSopenharmony_ci// #[derive(Deserialize)] 16627e2e9c0cSopenharmony_ci// struct S<'a> { 16637e2e9c0cSopenharmony_ci// #[serde(borrow)] 16647e2e9c0cSopenharmony_ci// cow: Cow<'a, str>, 16657e2e9c0cSopenharmony_ci// } 16667e2e9c0cSopenharmony_cifn is_cow(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool { 16677e2e9c0cSopenharmony_ci let path = match ungroup(ty) { 16687e2e9c0cSopenharmony_ci syn::Type::Path(ty) => &ty.path, 16697e2e9c0cSopenharmony_ci _ => { 16707e2e9c0cSopenharmony_ci return false; 16717e2e9c0cSopenharmony_ci } 16727e2e9c0cSopenharmony_ci }; 16737e2e9c0cSopenharmony_ci let seg = match path.segments.last() { 16747e2e9c0cSopenharmony_ci Some(seg) => seg, 16757e2e9c0cSopenharmony_ci None => { 16767e2e9c0cSopenharmony_ci return false; 16777e2e9c0cSopenharmony_ci } 16787e2e9c0cSopenharmony_ci }; 16797e2e9c0cSopenharmony_ci let args = match &seg.arguments { 16807e2e9c0cSopenharmony_ci syn::PathArguments::AngleBracketed(bracketed) => &bracketed.args, 16817e2e9c0cSopenharmony_ci _ => { 16827e2e9c0cSopenharmony_ci return false; 16837e2e9c0cSopenharmony_ci } 16847e2e9c0cSopenharmony_ci }; 16857e2e9c0cSopenharmony_ci seg.ident == "Cow" 16867e2e9c0cSopenharmony_ci && args.len() == 2 16877e2e9c0cSopenharmony_ci && match (&args[0], &args[1]) { 16887e2e9c0cSopenharmony_ci (syn::GenericArgument::Lifetime(_), syn::GenericArgument::Type(arg)) => elem(arg), 16897e2e9c0cSopenharmony_ci _ => false, 16907e2e9c0cSopenharmony_ci } 16917e2e9c0cSopenharmony_ci} 16927e2e9c0cSopenharmony_ci 16937e2e9c0cSopenharmony_cifn is_option(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool { 16947e2e9c0cSopenharmony_ci let path = match ungroup(ty) { 16957e2e9c0cSopenharmony_ci syn::Type::Path(ty) => &ty.path, 16967e2e9c0cSopenharmony_ci _ => { 16977e2e9c0cSopenharmony_ci return false; 16987e2e9c0cSopenharmony_ci } 16997e2e9c0cSopenharmony_ci }; 17007e2e9c0cSopenharmony_ci let seg = match path.segments.last() { 17017e2e9c0cSopenharmony_ci Some(seg) => seg, 17027e2e9c0cSopenharmony_ci None => { 17037e2e9c0cSopenharmony_ci return false; 17047e2e9c0cSopenharmony_ci } 17057e2e9c0cSopenharmony_ci }; 17067e2e9c0cSopenharmony_ci let args = match &seg.arguments { 17077e2e9c0cSopenharmony_ci syn::PathArguments::AngleBracketed(bracketed) => &bracketed.args, 17087e2e9c0cSopenharmony_ci _ => { 17097e2e9c0cSopenharmony_ci return false; 17107e2e9c0cSopenharmony_ci } 17117e2e9c0cSopenharmony_ci }; 17127e2e9c0cSopenharmony_ci seg.ident == "Option" 17137e2e9c0cSopenharmony_ci && args.len() == 1 17147e2e9c0cSopenharmony_ci && match &args[0] { 17157e2e9c0cSopenharmony_ci syn::GenericArgument::Type(arg) => elem(arg), 17167e2e9c0cSopenharmony_ci _ => false, 17177e2e9c0cSopenharmony_ci } 17187e2e9c0cSopenharmony_ci} 17197e2e9c0cSopenharmony_ci 17207e2e9c0cSopenharmony_ci// Whether the type looks like it might be `&T` where elem="T". This can have 17217e2e9c0cSopenharmony_ci// false negatives and false positives. 17227e2e9c0cSopenharmony_ci// 17237e2e9c0cSopenharmony_ci// False negative: 17247e2e9c0cSopenharmony_ci// 17257e2e9c0cSopenharmony_ci// type Yarn = str; 17267e2e9c0cSopenharmony_ci// 17277e2e9c0cSopenharmony_ci// #[derive(Deserialize)] 17287e2e9c0cSopenharmony_ci// struct S<'a> { 17297e2e9c0cSopenharmony_ci// r: &'a Yarn, 17307e2e9c0cSopenharmony_ci// } 17317e2e9c0cSopenharmony_ci// 17327e2e9c0cSopenharmony_ci// False positive: 17337e2e9c0cSopenharmony_ci// 17347e2e9c0cSopenharmony_ci// type str = [i16]; 17357e2e9c0cSopenharmony_ci// 17367e2e9c0cSopenharmony_ci// #[derive(Deserialize)] 17377e2e9c0cSopenharmony_ci// struct S<'a> { 17387e2e9c0cSopenharmony_ci// r: &'a str, 17397e2e9c0cSopenharmony_ci// } 17407e2e9c0cSopenharmony_cifn is_reference(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool { 17417e2e9c0cSopenharmony_ci match ungroup(ty) { 17427e2e9c0cSopenharmony_ci syn::Type::Reference(ty) => ty.mutability.is_none() && elem(&ty.elem), 17437e2e9c0cSopenharmony_ci _ => false, 17447e2e9c0cSopenharmony_ci } 17457e2e9c0cSopenharmony_ci} 17467e2e9c0cSopenharmony_ci 17477e2e9c0cSopenharmony_cifn is_str(ty: &syn::Type) -> bool { 17487e2e9c0cSopenharmony_ci is_primitive_type(ty, "str") 17497e2e9c0cSopenharmony_ci} 17507e2e9c0cSopenharmony_ci 17517e2e9c0cSopenharmony_cifn is_slice_u8(ty: &syn::Type) -> bool { 17527e2e9c0cSopenharmony_ci match ungroup(ty) { 17537e2e9c0cSopenharmony_ci syn::Type::Slice(ty) => is_primitive_type(&ty.elem, "u8"), 17547e2e9c0cSopenharmony_ci _ => false, 17557e2e9c0cSopenharmony_ci } 17567e2e9c0cSopenharmony_ci} 17577e2e9c0cSopenharmony_ci 17587e2e9c0cSopenharmony_cifn is_primitive_type(ty: &syn::Type, primitive: &str) -> bool { 17597e2e9c0cSopenharmony_ci match ungroup(ty) { 17607e2e9c0cSopenharmony_ci syn::Type::Path(ty) => ty.qself.is_none() && is_primitive_path(&ty.path, primitive), 17617e2e9c0cSopenharmony_ci _ => false, 17627e2e9c0cSopenharmony_ci } 17637e2e9c0cSopenharmony_ci} 17647e2e9c0cSopenharmony_ci 17657e2e9c0cSopenharmony_cifn is_primitive_path(path: &syn::Path, primitive: &str) -> bool { 17667e2e9c0cSopenharmony_ci path.leading_colon.is_none() 17677e2e9c0cSopenharmony_ci && path.segments.len() == 1 17687e2e9c0cSopenharmony_ci && path.segments[0].ident == primitive 17697e2e9c0cSopenharmony_ci && path.segments[0].arguments.is_empty() 17707e2e9c0cSopenharmony_ci} 17717e2e9c0cSopenharmony_ci 17727e2e9c0cSopenharmony_ci// All lifetimes that this type could borrow from a Deserializer. 17737e2e9c0cSopenharmony_ci// 17747e2e9c0cSopenharmony_ci// For example a type `S<'a, 'b>` could borrow `'a` and `'b`. On the other hand 17757e2e9c0cSopenharmony_ci// a type `for<'a> fn(&'a str)` could not borrow `'a` from the Deserializer. 17767e2e9c0cSopenharmony_ci// 17777e2e9c0cSopenharmony_ci// This is used when there is an explicit or implicit `#[serde(borrow)]` 17787e2e9c0cSopenharmony_ci// attribute on the field so there must be at least one borrowable lifetime. 17797e2e9c0cSopenharmony_cifn borrowable_lifetimes( 17807e2e9c0cSopenharmony_ci cx: &Ctxt, 17817e2e9c0cSopenharmony_ci name: &str, 17827e2e9c0cSopenharmony_ci field: &syn::Field, 17837e2e9c0cSopenharmony_ci) -> Result<BTreeSet<syn::Lifetime>, ()> { 17847e2e9c0cSopenharmony_ci let mut lifetimes = BTreeSet::new(); 17857e2e9c0cSopenharmony_ci collect_lifetimes(&field.ty, &mut lifetimes); 17867e2e9c0cSopenharmony_ci if lifetimes.is_empty() { 17877e2e9c0cSopenharmony_ci let msg = format!("field `{}` has no lifetimes to borrow", name); 17887e2e9c0cSopenharmony_ci cx.error_spanned_by(field, msg); 17897e2e9c0cSopenharmony_ci Err(()) 17907e2e9c0cSopenharmony_ci } else { 17917e2e9c0cSopenharmony_ci Ok(lifetimes) 17927e2e9c0cSopenharmony_ci } 17937e2e9c0cSopenharmony_ci} 17947e2e9c0cSopenharmony_ci 17957e2e9c0cSopenharmony_cifn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) { 17967e2e9c0cSopenharmony_ci match ty { 17977e2e9c0cSopenharmony_ci #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] 17987e2e9c0cSopenharmony_ci syn::Type::Slice(ty) => { 17997e2e9c0cSopenharmony_ci collect_lifetimes(&ty.elem, out); 18007e2e9c0cSopenharmony_ci } 18017e2e9c0cSopenharmony_ci syn::Type::Array(ty) => { 18027e2e9c0cSopenharmony_ci collect_lifetimes(&ty.elem, out); 18037e2e9c0cSopenharmony_ci } 18047e2e9c0cSopenharmony_ci syn::Type::Ptr(ty) => { 18057e2e9c0cSopenharmony_ci collect_lifetimes(&ty.elem, out); 18067e2e9c0cSopenharmony_ci } 18077e2e9c0cSopenharmony_ci syn::Type::Reference(ty) => { 18087e2e9c0cSopenharmony_ci out.extend(ty.lifetime.iter().cloned()); 18097e2e9c0cSopenharmony_ci collect_lifetimes(&ty.elem, out); 18107e2e9c0cSopenharmony_ci } 18117e2e9c0cSopenharmony_ci syn::Type::Tuple(ty) => { 18127e2e9c0cSopenharmony_ci for elem in &ty.elems { 18137e2e9c0cSopenharmony_ci collect_lifetimes(elem, out); 18147e2e9c0cSopenharmony_ci } 18157e2e9c0cSopenharmony_ci } 18167e2e9c0cSopenharmony_ci syn::Type::Path(ty) => { 18177e2e9c0cSopenharmony_ci if let Some(qself) = &ty.qself { 18187e2e9c0cSopenharmony_ci collect_lifetimes(&qself.ty, out); 18197e2e9c0cSopenharmony_ci } 18207e2e9c0cSopenharmony_ci for seg in &ty.path.segments { 18217e2e9c0cSopenharmony_ci if let syn::PathArguments::AngleBracketed(bracketed) = &seg.arguments { 18227e2e9c0cSopenharmony_ci for arg in &bracketed.args { 18237e2e9c0cSopenharmony_ci match arg { 18247e2e9c0cSopenharmony_ci syn::GenericArgument::Lifetime(lifetime) => { 18257e2e9c0cSopenharmony_ci out.insert(lifetime.clone()); 18267e2e9c0cSopenharmony_ci } 18277e2e9c0cSopenharmony_ci syn::GenericArgument::Type(ty) => { 18287e2e9c0cSopenharmony_ci collect_lifetimes(ty, out); 18297e2e9c0cSopenharmony_ci } 18307e2e9c0cSopenharmony_ci syn::GenericArgument::AssocType(binding) => { 18317e2e9c0cSopenharmony_ci collect_lifetimes(&binding.ty, out); 18327e2e9c0cSopenharmony_ci } 18337e2e9c0cSopenharmony_ci syn::GenericArgument::Const(_) 18347e2e9c0cSopenharmony_ci | syn::GenericArgument::AssocConst(_) 18357e2e9c0cSopenharmony_ci | syn::GenericArgument::Constraint(_) 18367e2e9c0cSopenharmony_ci | _ => {} 18377e2e9c0cSopenharmony_ci } 18387e2e9c0cSopenharmony_ci } 18397e2e9c0cSopenharmony_ci } 18407e2e9c0cSopenharmony_ci } 18417e2e9c0cSopenharmony_ci } 18427e2e9c0cSopenharmony_ci syn::Type::Paren(ty) => { 18437e2e9c0cSopenharmony_ci collect_lifetimes(&ty.elem, out); 18447e2e9c0cSopenharmony_ci } 18457e2e9c0cSopenharmony_ci syn::Type::Group(ty) => { 18467e2e9c0cSopenharmony_ci collect_lifetimes(&ty.elem, out); 18477e2e9c0cSopenharmony_ci } 18487e2e9c0cSopenharmony_ci syn::Type::Macro(ty) => { 18497e2e9c0cSopenharmony_ci collect_lifetimes_from_tokens(ty.mac.tokens.clone(), out); 18507e2e9c0cSopenharmony_ci } 18517e2e9c0cSopenharmony_ci syn::Type::BareFn(_) 18527e2e9c0cSopenharmony_ci | syn::Type::Never(_) 18537e2e9c0cSopenharmony_ci | syn::Type::TraitObject(_) 18547e2e9c0cSopenharmony_ci | syn::Type::ImplTrait(_) 18557e2e9c0cSopenharmony_ci | syn::Type::Infer(_) 18567e2e9c0cSopenharmony_ci | syn::Type::Verbatim(_) => {} 18577e2e9c0cSopenharmony_ci 18587e2e9c0cSopenharmony_ci _ => {} 18597e2e9c0cSopenharmony_ci } 18607e2e9c0cSopenharmony_ci} 18617e2e9c0cSopenharmony_ci 18627e2e9c0cSopenharmony_cifn collect_lifetimes_from_tokens(tokens: TokenStream, out: &mut BTreeSet<syn::Lifetime>) { 18637e2e9c0cSopenharmony_ci let mut iter = tokens.into_iter(); 18647e2e9c0cSopenharmony_ci while let Some(tt) = iter.next() { 18657e2e9c0cSopenharmony_ci match &tt { 18667e2e9c0cSopenharmony_ci TokenTree::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => { 18677e2e9c0cSopenharmony_ci if let Some(TokenTree::Ident(ident)) = iter.next() { 18687e2e9c0cSopenharmony_ci out.insert(syn::Lifetime { 18697e2e9c0cSopenharmony_ci apostrophe: op.span(), 18707e2e9c0cSopenharmony_ci ident, 18717e2e9c0cSopenharmony_ci }); 18727e2e9c0cSopenharmony_ci } 18737e2e9c0cSopenharmony_ci } 18747e2e9c0cSopenharmony_ci TokenTree::Group(group) => { 18757e2e9c0cSopenharmony_ci let tokens = group.stream(); 18767e2e9c0cSopenharmony_ci collect_lifetimes_from_tokens(tokens, out); 18777e2e9c0cSopenharmony_ci } 18787e2e9c0cSopenharmony_ci _ => {} 18797e2e9c0cSopenharmony_ci } 18807e2e9c0cSopenharmony_ci } 18817e2e9c0cSopenharmony_ci} 1882