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_flattened(attrs: &[syn::Attribute]) -> bool {
57 find_serde_meta(attrs, |meta| {
58 if meta.path.is_ident("flatten") {
59 Some(true)
60 } else {
61 None
62 }
63 })
64 .unwrap_or(false)
65}
66
67pub fn is_skipped(attrs: &[syn::Attribute]) -> bool {
69 find_serde_meta(attrs, |meta| {
70 if meta.path.is_ident("skip") || meta.path.is_ident("skip_serializing") {
71 Some(true)
72 } else {
73 None
74 }
75 })
76 .unwrap_or(false)
77}
78
79pub fn parse_enum_tagging(attrs: &[syn::Attribute]) -> EnumTagging {
85 let mut tag = None;
86 let mut content = None;
87 let mut untagged = false;
88
89 for attr in attrs {
90 if !attr.path().is_ident("serde") {
91 continue;
92 }
93 let _ = attr.parse_nested_meta(|meta| {
94 if meta.path.is_ident("untagged") {
95 untagged = true;
96 } else if meta.path.is_ident("tag")
97 && let Ok(value) = meta.value()
98 && let Ok(lit) = value.parse::<syn::LitStr>()
99 {
100 tag = Some(lit.value());
101 } else if meta.path.is_ident("content")
102 && let Ok(value) = meta.value()
103 && let Ok(lit) = value.parse::<syn::LitStr>()
104 {
105 content = Some(lit.value());
106 }
107 Ok(())
108 });
109 }
110
111 if untagged {
112 EnumTagging::Untagged
113 } else if let Some(tag) = tag {
114 if let Some(content) = content {
115 EnumTagging::Adjacent { tag, content }
116 } else {
117 EnumTagging::Internal { tag }
118 }
119 } else {
120 EnumTagging::External
121 }
122}
123
124pub fn has_default(attrs: &[syn::Attribute]) -> bool {
126 find_serde_meta(attrs, |meta| {
127 if meta.path.is_ident("default") {
128 Some(true)
129 } else {
130 None
131 }
132 })
133 .unwrap_or(false)
134}