1use derive_inflection::Inflection;
10use syn::{Attribute, Lit, Result};
11
12#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum Tagged {
15 Externally,
17 Internally { tag: String },
19 Adjacently { tag: String, content: String },
21 Untagged,
23}
24
25#[derive(Debug, Clone, Default)]
27pub struct SerdeContainer {
28 pub rename: Option<String>,
29 pub rename_all: Option<Inflection>,
30 pub rename_all_fields: Option<Inflection>,
31 pub tag: Option<String>,
32 pub content: Option<String>,
33 pub untagged: bool,
34 pub transparent: bool,
35}
36
37impl SerdeContainer {
38 pub fn from_attrs(attrs: &[Attribute]) -> Result<Self> {
40 let mut this = Self::default();
41
42 for attr in attrs {
43 if !attr.path().is_ident("serde") {
44 continue;
45 }
46 attr.parse_nested_meta(|meta| {
47 if meta.path.is_ident("rename") {
49 let value: Lit = meta.value()?.parse()?;
50 if let Lit::Str(s) = value {
51 this.rename = Some(s.value());
52 }
53 } else if meta.path.is_ident("rename_all") {
54 let value: Lit = meta.value()?.parse()?;
55 if let Lit::Str(s) = value {
56 this.rename_all = Inflection::parse(&s.value());
57 }
58 } else if meta.path.is_ident("rename_all_fields") {
59 let value: Lit = meta.value()?.parse()?;
60 if let Lit::Str(s) = value {
61 this.rename_all_fields = Inflection::parse(&s.value());
62 }
63 } else if meta.path.is_ident("tag") {
64 let value: Lit = meta.value()?.parse()?;
65 if let Lit::Str(s) = value {
66 this.tag = Some(s.value());
67 }
68 } else if meta.path.is_ident("content") {
69 let value: Lit = meta.value()?.parse()?;
70 if let Lit::Str(s) = value {
71 this.content = Some(s.value());
72 }
73 } else if meta.path.is_ident("untagged") {
74 this.untagged = true;
75 } else if meta.path.is_ident("transparent") {
76 this.transparent = true;
77 } else {
78 let _ = meta.value().and_then(|v| v.parse::<Lit>()).ok();
80 }
81 Ok(())
82 })?;
83 }
84
85 Ok(this)
86 }
87
88 pub fn tagged(&self) -> Tagged {
90 if self.untagged {
91 Tagged::Untagged
92 } else if let (Some(tag), Some(content)) = (&self.tag, &self.content) {
93 Tagged::Adjacently {
94 tag: tag.clone(),
95 content: content.clone(),
96 }
97 } else if let Some(tag) = &self.tag {
98 Tagged::Internally { tag: tag.clone() }
99 } else {
100 Tagged::Externally
101 }
102 }
103}
104
105#[derive(Debug, Clone, Default)]
107pub struct SerdeField {
108 pub rename: Option<String>,
109 pub skip: bool,
110 pub skip_serializing: bool,
111 pub skip_serializing_if: bool,
112 pub skip_deserializing: bool,
113 pub flatten: bool,
114 pub has_default: bool,
115 pub with: bool,
116}
117
118impl SerdeField {
119 pub fn from_attrs(attrs: &[Attribute]) -> Result<Self> {
121 let mut this = Self::default();
122
123 for attr in attrs {
124 if !attr.path().is_ident("serde") {
125 continue;
126 }
127 attr.parse_nested_meta(|meta| {
128 if meta.path.is_ident("rename") {
129 let value: Lit = meta.value()?.parse()?;
130 if let Lit::Str(s) = value {
131 this.rename = Some(s.value());
132 }
133 } else if meta.path.is_ident("skip") {
134 this.skip = true;
135 } else if meta.path.is_ident("skip_serializing") {
136 this.skip_serializing = true;
137 } else if meta.path.is_ident("skip_serializing_if") {
138 let _ = meta.value().and_then(|v| v.parse::<Lit>()).ok();
139 this.skip_serializing_if = true;
140 } else if meta.path.is_ident("skip_deserializing") {
141 this.skip_deserializing = true;
142 } else if meta.path.is_ident("default") {
143 let _ = meta.value().and_then(|v| v.parse::<Lit>()).ok();
144 this.has_default = true;
145 } else if meta.path.is_ident("flatten") {
146 this.flatten = true;
147 } else if meta.path.is_ident("with") || meta.path.is_ident("serialize_with") {
148 let _ = meta.value().and_then(|v| v.parse::<Lit>()).ok();
149 this.with = true;
150 } else {
151 let _ = meta.value().and_then(|v| v.parse::<Lit>()).ok();
152 }
153 Ok(())
154 })?;
155 }
156
157 Ok(this)
158 }
159
160 pub fn maybe_omitted(&self) -> bool {
162 self.skip_serializing || self.skip_serializing_if
163 }
164}
165
166#[derive(Debug, Clone, Default)]
168pub struct SerdeVariant {
169 pub rename: Option<String>,
170 pub rename_all: Option<Inflection>,
171 pub skip: bool,
172 pub untagged: bool,
173}
174
175impl SerdeVariant {
176 pub fn from_attrs(attrs: &[Attribute]) -> Result<Self> {
178 let mut this = Self::default();
179
180 for attr in attrs {
181 if !attr.path().is_ident("serde") {
182 continue;
183 }
184 attr.parse_nested_meta(|meta| {
185 if meta.path.is_ident("rename") {
186 let value: Lit = meta.value()?.parse()?;
187 if let Lit::Str(s) = value {
188 this.rename = Some(s.value());
189 }
190 } else if meta.path.is_ident("rename_all") {
191 let value: Lit = meta.value()?.parse()?;
192 if let Lit::Str(s) = value {
193 this.rename_all = Inflection::parse(&s.value());
194 }
195 } else if meta.path.is_ident("skip") {
196 this.skip = true;
197 } else if meta.path.is_ident("untagged") {
198 this.untagged = true;
199 } else {
200 let _ = meta.value().and_then(|v| v.parse::<Lit>()).ok();
201 }
202 Ok(())
203 })?;
204 }
205
206 Ok(this)
207 }
208}