serde_attributes/rename/
syn.rs1use syn::{Lit, Meta, MetaNameValue, NestedMeta};
2
3use crate::{DESERIALIZE, SERIALIZE};
4
5use super::{Rename, RenameIndependent};
6
7pub const RENAME: &str = "rename";
9
10impl Rename {
11 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
78impl<'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> {}