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