1use std::str::FromStr;
2
3use proc_macro2::TokenStream;
4use quote::ToTokens;
5
6#[derive(Debug, Default)]
7pub struct FieldAnnotation {
8 pub rename: Option<String>,
10 pub skip: bool,
12 pub type_: Option<String>,
14 pub visibility: Visibility,
16}
17
18#[derive(Debug, Default)]
19pub struct ModelAnnotation {
20 pub derive: Option<Vec<String>>,
21 pub rename: Option<String>,
22 pub skip: bool,
23 pub visibility: Visibility,
24}
25
26#[derive(Debug, Default)]
27pub struct EnumAnnotation {
28 pub derive: Option<Vec<String>>,
29 pub rename: Option<String>,
30 pub skip: bool,
31 pub visibility: Visibility,
32}
33
34#[derive(Debug, Default)]
35pub struct EnumValueAnnotation {
36 pub rename: Option<String>,
37 pub skip: bool,
38}
39
40#[derive(Debug, Default)]
41pub struct TypeAnnotation {
42 pub derive: Option<Vec<String>>,
43 pub rename: Option<String>,
44 pub skip: bool,
45 pub type_: Option<String>,
47 pub visibility: Visibility,
48}
49
50#[derive(Debug, Clone, Copy)]
51pub enum Visibility {
52 Public,
55 Private,
57 Protected,
60}
61
62impl Default for Visibility {
63 fn default() -> Self {
64 Visibility::Public
65 }
66}
67
68impl ToTokens for Visibility {
69 fn to_tokens(&self, tokens: &mut TokenStream) {
70 match self {
71 Visibility::Public => quote::quote! { pub }.to_tokens(tokens),
72 Visibility::Private => quote::quote! {}.to_tokens(tokens),
73 Visibility::Protected => quote::quote! { pub(crate) }.to_tokens(tokens),
74 }
75 }
76}
77
78impl FromStr for FieldAnnotation {
79 type Err = String;
80
81 fn from_str(s: &str) -> Result<Self, Self::Err> {
82 let mut skip = false;
83 let mut rename = None;
84 let mut visibility = Visibility::default();
85 let mut type_ = None;
86
87 for line in s.lines() {
88 if line.trim().starts_with("@prs.") {
89 let func = line.trim_start_matches("@prs.");
90 let (op, val) = func.split_once('=').unwrap_or((func, "true"));
91
92 match op.trim() {
93 "skip" => {
94 skip = val.trim() != "false";
95 }
96 "type" => {
97 type_ = Some(val.trim().to_string());
98 }
99 "rename" => {
100 rename = Some(val.trim().to_string());
101 }
102 "visibility" => {
103 visibility = match val.trim() {
104 "private" => Visibility::Private,
105 "protected" => Visibility::Protected,
106 "public" => Visibility::Public,
107 _ => {
108 return Err(format!(
109 "Unknown visibility: {}
110Available options: private, protected (pub(crate)), public (pub)",
111 val
112 ));
113 }
114 };
115 }
116 _ => {
117 return Err(format!("Unknown field annotation: {}", func));
118 }
119 }
120 }
121 }
122
123 Ok(FieldAnnotation {
124 rename,
125 skip,
126 type_,
127 visibility,
128 })
129 }
130}
131
132impl From<String> for FieldAnnotation {
133 fn from(s: String) -> Self {
134 FieldAnnotation::from_str(&s).unwrap_or_default()
135 }
136}
137impl From<&String> for FieldAnnotation {
138 fn from(s: &String) -> Self {
139 FieldAnnotation::from_str(s).unwrap_or_default()
140 }
141}
142
143impl FromStr for ModelAnnotation {
144 type Err = String;
145
146 fn from_str(s: &str) -> Result<Self, Self::Err> {
147 let mut skip = false;
148 let mut rename = None;
149 let mut visibility = Visibility::default();
150 let mut derive = None;
151
152 for line in s.lines() {
153 if line.trim().starts_with("@prs.") {
154 let func = line.trim_start_matches("@prs.");
155 let (op, val) = func.split_once('=').unwrap_or((func, "true"));
156
157 match op.trim() {
158 "skip" => {
159 skip = val.trim() != "false";
160 }
161 "rename" => {
162 rename = Some(val.trim().to_string());
163 }
164 "visibility" => {
165 visibility = match val.trim() {
166 "private" => Visibility::Private,
167 "protected" => Visibility::Protected,
168 "public" => Visibility::Public,
169 _ => {
170 return Err(format!(
171 "Unknown visibility: {}
172Available options: private, protected (pub(crate)), public (pub)",
173 val
174 ));
175 }
176 };
177 }
178 "derive" => {
179 let derive_str = val.trim();
180 if derive_str.is_empty() {
181 return Err("Derive cannot be empty".to_string());
182 }
183 derive = Some(
184 derive_str
185 .split(',')
186 .map(|s| s.trim().to_string())
187 .collect(),
188 );
189 }
190 _ => {
191 return Err(format!("Unknown field annotation: {}", func));
192 }
193 }
194 }
195 }
196
197 Ok(ModelAnnotation {
198 skip,
199 rename,
200 visibility,
201 derive,
202 })
203 }
204}
205
206impl From<String> for ModelAnnotation {
207 fn from(s: String) -> Self {
208 ModelAnnotation::from_str(&s).unwrap_or_default()
209 }
210}
211impl From<&String> for ModelAnnotation {
212 fn from(s: &String) -> Self {
213 ModelAnnotation::from_str(s).unwrap_or_default()
214 }
215}
216
217impl FromStr for EnumAnnotation {
218 type Err = String;
219
220 fn from_str(s: &str) -> Result<Self, Self::Err> {
221 let mut skip = false;
222 let mut rename = None;
223 let mut visibility = Visibility::default();
224 let mut derive = None;
225
226 for line in s.lines() {
227 if line.trim().starts_with("@prs.") {
228 let func = line.trim_start_matches("@prs.");
229 let (op, val) = func.split_once('=').unwrap_or((func, "true"));
230
231 match op.trim() {
232 "skip" => {
233 skip = val.trim() != "false";
234 }
235 "rename" => {
236 rename = Some(val.trim().to_string());
237 }
238 "visibility" => {
239 visibility = match val.trim() {
240 "private" => Visibility::Private,
241 "protected" => Visibility::Protected,
242 "public" => Visibility::Public,
243 _ => {
244 return Err(format!(
245 "Unknown visibility: {}
246Available options: private, protected (pub(crate)), public (pub)",
247 val
248 ));
249 }
250 };
251 }
252 "derive" => {
253 let derive_str = val.trim();
254 if derive_str.is_empty() {
255 return Err("Derive cannot be empty".to_string());
256 }
257 derive = Some(
258 derive_str
259 .split(',')
260 .map(|s| s.trim().to_string())
261 .collect(),
262 );
263 }
264 _ => {
265 return Err(format!("Unknown field annotation: {}", func));
266 }
267 }
268 }
269 }
270
271 Ok(EnumAnnotation {
272 skip,
273 rename,
274 visibility,
275 derive,
276 })
277 }
278}
279
280impl From<String> for EnumAnnotation {
281 fn from(s: String) -> Self {
282 EnumAnnotation::from_str(&s).unwrap_or_default()
283 }
284}
285impl From<&String> for EnumAnnotation {
286 fn from(s: &String) -> Self {
287 EnumAnnotation::from_str(s).unwrap_or_default()
288 }
289}
290
291impl FromStr for TypeAnnotation {
292 type Err = String;
293
294 fn from_str(s: &str) -> Result<Self, Self::Err> {
295 let mut skip = false;
296 let mut rename = None;
297 let mut visibility = Visibility::default();
298 let mut derive = None;
299 let mut type_ = None;
300
301 for line in s.lines() {
302 if line.trim().starts_with("@prs.") {
303 let func = line.trim_start_matches("@prs.");
304 let (op, val) = func.split_once('=').unwrap_or((func, "true"));
305
306 match op.trim() {
307 "skip" => {
308 skip = val.trim() != "false";
309 }
310 "type" => {
311 type_ = Some(val.trim().to_string());
312 }
313 "rename" => {
314 rename = Some(val.trim().to_string());
315 }
316 "visibility" => {
317 visibility = match val.trim() {
318 "private" => Visibility::Private,
319 "protected" => Visibility::Protected,
320 "public" => Visibility::Public,
321 _ => {
322 return Err(format!(
323 "Unknown visibility: {}
324Available options: private, protected (pub(crate)), public (pub)",
325 val
326 ));
327 }
328 };
329 }
330 "derive" => {
331 let derive_str = val.trim();
332 if derive_str.is_empty() {
333 return Err("Derive cannot be empty".to_string());
334 }
335 derive = Some(
336 derive_str
337 .split(',')
338 .map(|s| s.trim().to_string())
339 .collect(),
340 );
341 }
342 _ => {
343 return Err(format!("Unknown field annotation: {}", func));
344 }
345 }
346 }
347 }
348
349 Ok(TypeAnnotation {
350 derive,
351 rename,
352 skip,
353 type_,
354 visibility,
355 })
356 }
357}
358
359impl From<String> for TypeAnnotation {
360 fn from(s: String) -> Self {
361 TypeAnnotation::from_str(&s).unwrap_or_default()
362 }
363}
364impl From<&String> for TypeAnnotation {
365 fn from(s: &String) -> Self {
366 TypeAnnotation::from_str(s).unwrap_or_default()
367 }
368}
369
370impl FromStr for EnumValueAnnotation {
371 type Err = String;
372
373 fn from_str(s: &str) -> Result<Self, Self::Err> {
374 let mut skip = false;
375 let mut rename = None;
376
377 for line in s.lines() {
378 if line.trim().starts_with("@prs.") {
379 let func = line.trim_start_matches("@prs.");
380 let (op, val) = func.split_once('=').unwrap_or((func, "true"));
381
382 match op.trim() {
383 "skip" => {
384 skip = val.trim() != "false";
385 }
386 "rename" => {
387 rename = Some(val.trim().to_string());
388 }
389 _ => {
390 return Err(format!("Unknown field annotation: {}", func));
391 }
392 }
393 }
394 }
395
396 Ok(EnumValueAnnotation { skip, rename })
397 }
398}
399
400impl From<String> for EnumValueAnnotation {
401 fn from(s: String) -> Self {
402 EnumValueAnnotation::from_str(&s).unwrap_or_default()
403 }
404}
405impl From<&String> for EnumValueAnnotation {
406 fn from(s: &String) -> Self {
407 EnumValueAnnotation::from_str(s).unwrap_or_default()
408 }
409}