vercel_rpc_cli/parser/
serde.rs1use crate::model::{EnumTagging, RenameRule};
2
3fn find_serde_meta<T>(
6 attrs: &[syn::Attribute],
7 mut visitor: impl FnMut(&syn::meta::ParseNestedMeta) -> Option<T>,
8) -> Option<T> {
9 let mut result = None;
10 for attr in attrs {
11 if !attr.path().is_ident("serde") {
12 continue;
13 }
14 let _ = attr.parse_nested_meta(|meta| {
15 if let Some(value) = visitor(&meta) {
16 result = Some(value);
17 }
18 Ok(())
19 });
20 }
21 result
22}
23
24pub fn parse_rename_all(attrs: &[syn::Attribute]) -> Option<RenameRule> {
26 find_serde_meta(attrs, |meta| {
27 if !meta.path.is_ident("rename_all") {
28 return None;
29 }
30 let value = meta.value().ok()?.parse::<syn::LitStr>().ok()?;
31 match value.value().parse::<RenameRule>() {
32 Ok(rule) => Some(rule),
33 Err(e) => {
34 eprintln!(
35 "warning: unknown rename_all value \"{}\" — {e}; attribute ignored",
36 value.value(),
37 );
38 None
39 }
40 }
41 })
42}
43
44pub fn parse_rename(attrs: &[syn::Attribute]) -> Option<String> {
46 find_serde_meta(attrs, |meta| {
47 if !meta.path.is_ident("rename") {
48 return None;
49 }
50 let value = meta.value().ok()?.parse::<syn::LitStr>().ok()?;
51 Some(value.value())
52 })
53}
54
55pub fn is_skipped(attrs: &[syn::Attribute]) -> bool {
57 find_serde_meta(attrs, |meta| {
58 if meta.path.is_ident("skip") || meta.path.is_ident("skip_serializing") {
59 Some(true)
60 } else {
61 None
62 }
63 })
64 .unwrap_or(false)
65}
66
67pub fn parse_enum_tagging(attrs: &[syn::Attribute]) -> EnumTagging {
73 let mut tag = None;
74 let mut content = None;
75 let mut untagged = false;
76
77 for attr in attrs {
78 if !attr.path().is_ident("serde") {
79 continue;
80 }
81 let _ = attr.parse_nested_meta(|meta| {
82 if meta.path.is_ident("untagged") {
83 untagged = true;
84 } else if meta.path.is_ident("tag")
85 && let Ok(value) = meta.value()
86 && let Ok(lit) = value.parse::<syn::LitStr>()
87 {
88 tag = Some(lit.value());
89 } else if meta.path.is_ident("content")
90 && let Ok(value) = meta.value()
91 && let Ok(lit) = value.parse::<syn::LitStr>()
92 {
93 content = Some(lit.value());
94 }
95 Ok(())
96 });
97 }
98
99 if untagged {
100 EnumTagging::Untagged
101 } else if let Some(tag) = tag {
102 if let Some(content) = content {
103 EnumTagging::Adjacent { tag, content }
104 } else {
105 EnumTagging::Internal { tag }
106 }
107 } else {
108 EnumTagging::External
109 }
110}
111
112pub fn has_default(attrs: &[syn::Attribute]) -> bool {
114 find_serde_meta(attrs, |meta| {
115 if meta.path.is_ident("default") {
116 Some(true)
117 } else {
118 None
119 }
120 })
121 .unwrap_or(false)
122}