scylla_macros/
parser.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use syn::{Data, DeriveInput, ExprLit, Fields, FieldsNamed, Lit};
use syn::{Expr, Meta};

/// Parses the tokens_input to a DeriveInput and returns the struct name from which it derives and
/// the named fields
pub(crate) fn parse_named_fields<'a>(
    input: &'a DeriveInput,
    current_derive: &str,
) -> Result<&'a FieldsNamed, syn::Error> {
    match &input.data {
        Data::Struct(data) => match &data.fields {
            Fields::Named(named_fields) => Ok(named_fields),
            _ => Err(syn::Error::new_spanned(
                data.struct_token,
                format!(
                    "derive({}) works only for structs with named fields",
                    current_derive
                ),
            )),
        },
        Data::Enum(e) => Err(syn::Error::new_spanned(
            e.enum_token,
            format!(
                "derive({}) works only for structs with named fields",
                current_derive
            ),
        )),
        Data::Union(u) => Err(syn::Error::new_spanned(
            u.union_token,
            format!(
                "derive({}) works only for structs with named fields",
                current_derive
            ),
        )),
    }
}

pub(crate) fn get_path(input: &DeriveInput) -> Result<proc_macro2::TokenStream, syn::Error> {
    let mut this_path: Option<proc_macro2::TokenStream> = None;
    for attr in input.attrs.iter() {
        if !attr.path().is_ident("scylla_crate") {
            continue;
        }
        match &attr.meta {
            Meta::NameValue(name_value) => {
                if let Expr::Lit(ExprLit {
                    lit: Lit::Str(lit), ..
                }) = &name_value.value
                {
                    let path = syn::Ident::new(&lit.value(), lit.span());
                    if this_path.is_none() {
                        this_path = Some(quote::quote!(#path::_macro_internal));
                    } else {
                        return Err(syn::Error::new_spanned(
                            &name_value.path,
                            "the `scylla_crate` attribute was set multiple times",
                        ));
                    }
                } else {
                    return Err(syn::Error::new_spanned(
                        &name_value.value,
                        "the `scylla_crate` attribute should be a string literal",
                    ));
                }
            }
            other => {
                return Err(syn::Error::new_spanned(
                    other,
                    "the `scylla_crate` attribute have a single value",
                ));
            }
        }
    }
    Ok(this_path.unwrap_or_else(|| quote::quote!(scylla::_macro_internal)))
}