vector_config_macros/ast/
mod.rs1use darling::{ast::NestedMeta, error::Accumulator, util::path_to_string, FromMeta};
2use quote::ToTokens;
3use serde_derive_internals::{ast as serde_ast, attr as serde_attr};
4
5mod container;
6mod field;
7mod util;
8mod variant;
9
10pub use container::Container;
11pub use field::Field;
12use syn::Expr;
13pub use variant::Variant;
14use vector_config_common::constants;
15
16const INVALID_VALUE_EXPR: &str =
17 "got function call-style literal value but could not parse as expression";
18
19#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum Style {
24 Struct,
26
27 Tuple,
29
30 Newtype,
32
33 Unit,
35}
36
37impl From<serde_ast::Style> for Style {
38 fn from(style: serde_ast::Style) -> Self {
39 match style {
40 serde_ast::Style::Struct => Style::Struct,
41 serde_ast::Style::Tuple => Style::Tuple,
42 serde_ast::Style::Newtype => Style::Newtype,
43 serde_ast::Style::Unit => Style::Unit,
44 }
45 }
46}
47
48#[derive(Clone, Debug, PartialEq, Eq)]
52pub enum Tagging {
53 External,
59
60 Internal { tag: String },
66
67 Adjacent { tag: String, content: String },
73
74 None,
80}
81
82impl Tagging {
83 pub fn as_enum_metadata(&self) -> Vec<LazyCustomAttribute> {
89 match self {
90 Self::External => vec![LazyCustomAttribute::kv(
91 constants::DOCS_META_ENUM_TAGGING,
92 "external",
93 )],
94 Self::Internal { tag } => vec![
95 LazyCustomAttribute::kv(constants::DOCS_META_ENUM_TAGGING, "internal"),
96 LazyCustomAttribute::kv(constants::DOCS_META_ENUM_TAG_FIELD, tag),
97 ],
98 Self::Adjacent { tag, content } => vec![
99 LazyCustomAttribute::kv(constants::DOCS_META_ENUM_TAGGING, "adjacent"),
100 LazyCustomAttribute::kv(constants::DOCS_META_ENUM_TAG_FIELD, tag),
101 LazyCustomAttribute::kv(constants::DOCS_META_ENUM_CONTENT_FIELD, content),
102 ],
103 Self::None => vec![LazyCustomAttribute::kv(
104 constants::DOCS_META_ENUM_TAGGING,
105 "untagged",
106 )],
107 }
108 }
109}
110
111impl From<&serde_attr::TagType> for Tagging {
112 fn from(tag: &serde_attr::TagType) -> Self {
113 match tag {
114 serde_attr::TagType::External => Tagging::External,
115 serde_attr::TagType::Internal { tag } => Tagging::Internal { tag: tag.clone() },
116 serde_attr::TagType::Adjacent { tag, content } => Tagging::Adjacent {
117 tag: tag.clone(),
118 content: content.clone(),
119 },
120 serde_attr::TagType::None => Tagging::None,
121 }
122 }
123}
124
125pub enum Data<'a> {
129 Enum(Vec<Variant<'a>>),
130 Struct(Style, Vec<Field<'a>>),
131}
132
133#[derive(Clone, Debug)]
142pub enum LazyCustomAttribute {
143 Flag(String),
145
146 KeyValue {
148 key: String,
149 value: proc_macro2::TokenStream,
150 },
151}
152
153impl LazyCustomAttribute {
154 pub fn kv<K, V>(key: K, value: V) -> Self
155 where
156 K: std::fmt::Display,
157 V: ToTokens,
158 {
159 Self::KeyValue {
160 key: key.to_string(),
161 value: value.to_token_stream(),
162 }
163 }
164}
165
166#[derive(Clone, Debug)]
168pub struct Metadata {
169 items: Vec<LazyCustomAttribute>,
170}
171
172impl Metadata {
173 pub fn attributes(&self) -> impl Iterator<Item = LazyCustomAttribute> {
174 self.items.clone().into_iter()
175 }
176}
177
178impl FromMeta for Metadata {
179 fn from_list(items: &[NestedMeta]) -> darling::Result<Self> {
180 let mut errors = Accumulator::default();
181
182 if items.is_empty() {
184 errors.push(darling::Error::too_few_items(1));
185 }
186
187 errors = errors.checkpoint()?;
188
189 let meta_items = items
191 .iter()
192 .filter_map(|nmeta| match nmeta {
193 NestedMeta::Meta(meta) => match meta {
194 syn::Meta::Path(path) => Some(LazyCustomAttribute::Flag(path_to_string(path))),
195 syn::Meta::List(_) => {
196 errors.push(darling::Error::unexpected_type("list").with_span(nmeta));
197 None
198 }
199 syn::Meta::NameValue(nv) => match &nv.value {
200 Expr::Lit(expr) => {
201 match &expr.lit {
202 syn::Lit::Str(s) => {
208 if s.value().ends_with("()") {
209 if let Ok(expr) = s.parse::<Expr>() {
210 Some(LazyCustomAttribute::KeyValue {
211 key: path_to_string(&nv.path),
212 value: expr.to_token_stream(),
213 })
214 } else {
215 errors.push(
216 darling::Error::custom(INVALID_VALUE_EXPR)
217 .with_span(nmeta),
218 );
219 None
220 }
221 } else {
222 Some(LazyCustomAttribute::KeyValue {
223 key: path_to_string(&nv.path),
224 value: s.value().to_token_stream(),
225 })
226 }
227 }
228 lit => Some(LazyCustomAttribute::KeyValue {
229 key: path_to_string(&nv.path),
230 value: lit.to_token_stream(),
231 }),
232 }
233 }
234 expr => {
235 errors
236 .push(darling::Error::unexpected_expr_type(expr).with_span(nmeta));
237 None
238 }
239 },
240 },
241 NestedMeta::Lit(_) => {
242 errors.push(darling::Error::unexpected_type("literal").with_span(nmeta));
243 None
244 }
245 })
246 .collect::<Vec<_>>();
247
248 errors.finish_with(Metadata { items: meta_items })
249 }
250}