serde_attributes/rename/
syn.rs

1use syn::{Lit, Meta, MetaNameValue, NestedMeta};
2
3use crate::{DESERIALIZE, SERIALIZE};
4
5use super::{Rename, RenameIndependent};
6
7/// [Ref](https://github.com/serde-rs/serde/blob/v1.0.127/serde_derive/src/internals/symbol.rs#L23)
8pub const RENAME: &str = "rename";
9
10impl Rename {
11    /// [Ref](https://github.com/serde-rs/serde/blob/v1.0.127/serde_derive/src/internals/attr.rs#L319-L333)
12    pub fn try_from_meta<'a>(meta: &'a Meta, path_name: &str) -> Result<Self, FromMetaError<'a>> {
13        match meta {
14            Meta::NameValue(meta_name_value) if meta_name_value.path.is_ident(path_name) => {
15                match &meta_name_value.lit {
16                    Lit::Str(s) => Ok(Self::Normal(s.value())),
17                    lit => Err(FromMetaError::LitTypeMismatch(lit)),
18                }
19            }
20            Meta::List(meta_list) if meta_list.path.is_ident(path_name) => {
21                let mut ser_name = None;
22                let mut de_name = None;
23
24                for nested_meta in &meta_list.nested {
25                    match nested_meta {
26                        NestedMeta::Meta(Meta::NameValue(meta_name_value)) => {
27                            if meta_name_value.path.is_ident(SERIALIZE) {
28                                match &meta_name_value.lit {
29                                    Lit::Str(s) => ser_name = Some(s.value()),
30                                    _ => {
31                                        return Err(FromMetaError::LitTypeMismatch(
32                                            &meta_name_value.lit,
33                                        ));
34                                    }
35                                }
36                            } else if meta_name_value.path.is_ident(DESERIALIZE) {
37                                match &meta_name_value.lit {
38                                    Lit::Str(s) => de_name = Some(s.value()),
39                                    _ => {
40                                        return Err(FromMetaError::LitTypeMismatch(
41                                            &meta_name_value.lit,
42                                        ));
43                                    }
44                                }
45                            } else {
46                                return Err(FromMetaError::NestedMetaPathMismatch(
47                                    nested_meta,
48                                    meta_name_value,
49                                ));
50                            }
51                        }
52                        nested_meta => {
53                            return Err(FromMetaError::NestedMetaTypeMismatch(nested_meta));
54                        }
55                    }
56                }
57                match (ser_name, de_name) {
58                    (None, None) => Err(FromMetaError::AtLeastOneOfSerAndDe),
59                    (None, Some(de_name)) => {
60                        Ok(Self::Independent(RenameIndependent::Deserialize(de_name)))
61                    }
62                    (Some(ser_name), None) => {
63                        Ok(Self::Independent(RenameIndependent::Serialize(ser_name)))
64                    }
65                    (Some(ser_name), Some(de_name)) => {
66                        Ok(Self::Independent(RenameIndependent::Both {
67                            serialize: ser_name,
68                            deserialize: de_name,
69                        }))
70                    }
71                }
72            }
73            meta => Err(FromMetaError::MetaTypeOrPathMismatch(meta)),
74        }
75    }
76}
77
78/// [Ref](https://github.com/serde-rs/serde/blob/v1.0.127/serde_derive/src/internals/attr.rs#L319-L333)
79impl<'a> core::convert::TryFrom<&'a Meta> for Rename {
80    type Error = FromMetaError<'a>;
81
82    fn try_from(meta: &'a Meta) -> Result<Self, Self::Error> {
83        Self::try_from_meta(meta, RENAME)
84    }
85}
86
87pub enum FromMetaError<'a> {
88    MetaTypeOrPathMismatch(&'a Meta),
89    LitTypeMismatch(&'a Lit),
90    NestedMetaTypeMismatch(&'a NestedMeta),
91    NestedMetaPathMismatch(&'a NestedMeta, &'a MetaNameValue),
92    AtLeastOneOfSerAndDe,
93}
94impl<'a> core::fmt::Debug for FromMetaError<'a> {
95    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
96        match self {
97            Self::MetaTypeOrPathMismatch(_) => write!(f, "MetaTypeOrPathMismatch"),
98            Self::LitTypeMismatch(_) => write!(f, "LitTypeMismatch"),
99            Self::NestedMetaTypeMismatch(_) => write!(f, "NestedMetaTypeMismatch"),
100            Self::NestedMetaPathMismatch(_, _) => write!(f, "NestedMetaPathMismatch"),
101            Self::AtLeastOneOfSerAndDe => write!(f, "AtLeastOneOfSerAndDe"),
102        }
103    }
104}
105impl<'a> core::fmt::Display for FromMetaError<'a> {
106    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
107        write!(f, "{self:?}")
108    }
109}
110#[cfg(feature = "std")]
111impl<'a> std::error::Error for FromMetaError<'a> {}