schemars_derive/attr/
custom_meta.rs

1use quote::ToTokens;
2use syn::{parse::Parse, Meta, MetaList, MetaNameValue, Path};
3
4// An extended copy of `syn::Meta` with an additional `Not` variant
5#[derive(Clone)]
6pub enum CustomMeta {
7    Path(Path),
8    List(MetaList),
9    NameValue(MetaNameValue),
10    Not(Token![!], Path),
11}
12
13impl ToTokens for CustomMeta {
14    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
15        match self {
16            CustomMeta::Not(not, path) => {
17                not.to_tokens(tokens);
18                path.to_tokens(tokens);
19            }
20            CustomMeta::Path(meta) => meta.to_tokens(tokens),
21            CustomMeta::List(meta) => meta.to_tokens(tokens),
22            CustomMeta::NameValue(meta) => meta.to_tokens(tokens),
23        }
24    }
25}
26
27impl From<Meta> for CustomMeta {
28    fn from(value: Meta) -> Self {
29        match value {
30            Meta::Path(meta) => Self::Path(meta),
31            Meta::List(meta) => Self::List(meta),
32            Meta::NameValue(meta) => Self::NameValue(meta),
33        }
34    }
35}
36
37impl Parse for CustomMeta {
38    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
39        Ok(if input.peek(Token![!]) {
40            Self::Not(input.parse()?, input.parse()?)
41        } else {
42            Meta::parse(input)?.into()
43        })
44    }
45}
46
47impl CustomMeta {
48    pub fn path(&self) -> &Path {
49        match self {
50            CustomMeta::Not(_not, path) => path,
51            CustomMeta::Path(path) => path,
52            CustomMeta::List(meta) => &meta.path,
53            CustomMeta::NameValue(meta) => &meta.path,
54        }
55    }
56}