cbor_data_derive/
lib.rs

1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, Attribute, DeriveInput, Error, Fields, Meta, NestedMeta};
4
5mod read;
6mod write;
7
8#[proc_macro_derive(WriteCbor, attributes(cbor))]
9pub fn derive_write(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
10    let input = parse_macro_input!(input as DeriveInput);
11    let name = input.ident;
12    let (g_impl, g_type, g_where) = input.generics.split_for_impl();
13
14    let code = match write::code_write(input.data, input.attrs) {
15        Ok(code) => code,
16        Err(e) => {
17            return e
18                .into_iter()
19                .map(Error::into_compile_error)
20                .collect::<TokenStream>()
21                .into()
22        }
23    };
24
25    let ret = quote! {
26        impl #g_impl ::cbor_data::codec::WriteCbor for #name #g_type #g_where {
27            fn write_cbor<W: ::cbor_data::Writer>(&self, w: W) -> W::Output {
28                #code
29            }
30        }
31    };
32    ret.into()
33}
34
35#[proc_macro_derive(ReadCbor, attributes(cbor))]
36pub fn derive_read(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
37    let input = parse_macro_input!(input as DeriveInput);
38    let name = input.ident;
39    let (g_impl, g_type, g_where) = input.generics.split_for_impl();
40
41    let code = match read::code_read(input.data, input.attrs) {
42        Ok(code) => code,
43        Err(e) => {
44            return e
45                .into_iter()
46                .map(Error::into_compile_error)
47                .collect::<TokenStream>()
48                .into()
49        }
50    };
51
52    let name_string = name.to_string();
53    let ret = quote! {
54        impl #g_impl ::cbor_data::codec::ReadCbor for #name #g_type #g_where {
55            fn fmt(f: &mut impl ::std::fmt::Write) -> ::std::fmt::Result {
56                write!(f, #name_string)
57            }
58
59            fn read_cbor_impl(cbor: &::cbor_data::Cbor) -> ::cbor_data::codec::Result<Self>
60            where
61                Self: Sized,
62            {
63                #code
64            }
65        }
66    };
67    ret.into()
68}
69
70fn is_one_tuple(f: &Fields) -> bool {
71    match f {
72        Fields::Unnamed(f) => f.unnamed.len() == 1,
73        _ => false,
74    }
75}
76
77fn is_transparent(a: &&Attribute) -> bool {
78    if let Ok(Meta::List(l)) = a.parse_meta() {
79        l.path.is_ident("cbor")
80            && l.nested
81                .iter()
82                .any(|m| matches!(m, NestedMeta::Meta(Meta::Path(p)) if p.is_ident("transparent")))
83    } else {
84        false
85    }
86}