1#![deny(clippy::all)]
4#![deny(missing_docs)]
5
6extern crate proc_macro;
7
8mod attrs;
9mod cbor_bytes;
10mod decode;
11mod encode;
12mod types;
13mod util;
14
15use proc_macro::TokenStream;
16use syn::{parse_macro_input, spanned::Spanned, Data, DataEnum, DeriveInput, Ident};
17
18use crate::attrs::parse_cbor_enum_attrs;
19use crate::cbor_bytes::expand as expand_cbor_bytes;
20use crate::decode::{decode_enum, decode_struct};
21use crate::encode::{encode_enum, encode_struct};
22
23fn ensure_non_empty_enum(name: &Ident, data: &DataEnum, derive_name: &str) -> syn::Result<()> {
24 if data.variants.is_empty() {
25 return Err(syn::Error::new(
26 name.span(),
27 format!("{derive_name} does not support empty enums"),
28 ));
29 }
30
31 Ok(())
32}
33
34#[proc_macro_derive(CborEncode, attributes(cbor))]
35pub fn derive_cbor_encode(input: TokenStream) -> TokenStream {
37 let input = parse_macro_input!(input as DeriveInput);
38 let out = (|| -> syn::Result<proc_macro2::TokenStream> {
39 match &input.data {
40 Data::Struct(data) => encode_struct(&input.ident, &input.generics, data),
41 Data::Enum(data) => {
42 ensure_non_empty_enum(&input.ident, data, "CborEncode")?;
43 let attrs = parse_cbor_enum_attrs(&input.attrs)?;
44 encode_enum(&input.ident, &input.generics, data, &attrs)
45 }
46 Data::Union(u) => Err(syn::Error::new(
47 u.union_token.span(),
48 "CborEncode not supported for unions",
49 )),
50 }
51 })();
52
53 match out {
54 Ok(ts) => TokenStream::from(ts),
55 Err(e) => TokenStream::from(e.to_compile_error()),
56 }
57}
58
59#[proc_macro_derive(CborDecode, attributes(cbor))]
60pub fn derive_cbor_decode(input: TokenStream) -> TokenStream {
62 let input = parse_macro_input!(input as DeriveInput);
63 let out = (|| -> syn::Result<proc_macro2::TokenStream> {
64 match &input.data {
65 Data::Struct(data) => decode_struct(&input.ident, &input.generics, data),
66 Data::Enum(data) => {
67 ensure_non_empty_enum(&input.ident, data, "CborDecode")?;
68 let attrs = parse_cbor_enum_attrs(&input.attrs)?;
69 decode_enum(&input.ident, &input.generics, data, &attrs)
70 }
71 Data::Union(u) => Err(syn::Error::new(
72 u.union_token.span(),
73 "CborDecode not supported for unions",
74 )),
75 }
76 })();
77
78 match out {
79 Ok(ts) => TokenStream::from(ts),
80 Err(e) => TokenStream::from(e.to_compile_error()),
81 }
82}
83
84#[proc_macro]
86pub fn cbor_bytes(input: TokenStream) -> TokenStream {
87 expand_cbor_bytes(input)
88}