Skip to main content

rasn_derive_impl/
lib.rs

1#[macro_use]
2extern crate quote;
3
4mod asn_type;
5mod config;
6mod decode;
7mod encode;
8mod r#enum;
9mod ext;
10mod tag;
11
12use crate::ext::GenericsExt;
13use config::Config;
14use syn::{DataStruct, DeriveInput};
15
16const CRATE_NAME: &str = "rasn";
17
18pub fn decode_derive_inner(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
19    let config = Config::from_attributes(&input)?;
20    let name = &input.ident;
21    let mut generics = input.generics;
22    let crate_root = &config.crate_root;
23    generics.add_trait_bounds(crate_root, quote::format_ident!("Decode"));
24
25    match input.data {
26        // Unit structs are treated as ASN.1 NULL values.
27        syn::Data::Struct(DataStruct {
28            fields: syn::Fields::Unit,
29            ..
30        }) => Ok(quote! {
31            impl #crate_root::Decode for #name {
32                fn decode_with_tag_and_constraints<D: #crate_root::Decoder>(
33                    decoder: &mut D,
34                    tag: #crate_root::types::Tag,
35                    _: #crate_root::prelude::Constraints,
36                ) -> Result<Self, D::Error> {
37                    decoder.decode_null(tag).map(|_| #name)
38                }
39            }
40        }),
41        syn::Data::Struct(v) => decode::derive_struct_impl(name, generics, v, &config),
42        syn::Data::Enum(syn::DataEnum { variants, .. }) => r#enum::Enum {
43            name,
44            generics: &generics,
45            variants: &variants,
46            config: &config,
47        }
48        .impl_decode(),
49        _ => Err(syn::Error::new(
50            name.span(),
51            "Union types are not supported.",
52        )),
53    }
54}
55
56pub fn encode_derive_inner(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
57    let config = Config::from_attributes(&input)?;
58    let name = &input.ident;
59    let mut generics = input.generics;
60    let crate_root = &config.crate_root;
61    generics.add_trait_bounds(crate_root, quote::format_ident!("Encode"));
62
63    Ok(match input.data {
64        // Unit structs are treated as ASN.1 NULL values.
65        syn::Data::Struct(DataStruct {
66            fields: syn::Fields::Unit,
67            ..
68        }) => quote! {
69            impl #crate_root::Encode for #name {
70                fn encode_with_tag_and_constraints<'encoder, E: #crate_root::Encoder<'encoder>>(
71                    &self,
72                    encoder: &mut E,
73                    tag: #crate_root::types::Tag,
74                    constraints: #crate_root::prelude::Constraints,
75                    identifier: #crate_root::types::Identifier,
76                ) -> Result<(), E::Error> {
77                    encoder.encode_null(tag, identifier).map(drop)
78                }
79            }
80        },
81        syn::Data::Struct(v) => encode::derive_struct_impl(name, generics, v, &config)?,
82        syn::Data::Enum(syn::DataEnum { variants, .. }) => r#enum::Enum {
83            name,
84            generics: &generics,
85            variants: &variants,
86            config: &config,
87        }
88        .impl_encode()?,
89        _ => {
90            return Err(syn::Error::new(
91                name.span(),
92                "Union types are not supported.",
93            ));
94        }
95    })
96}
97
98pub fn asn_type_derive_inner(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
99    let config = Config::from_attributes(&input)?;
100    let name = &input.ident;
101    let mut generics = input.generics;
102    let crate_root = &config.crate_root;
103    for param in &mut generics.params {
104        if let syn::GenericParam::Type(type_param) = param {
105            type_param
106                .bounds
107                .push(syn::parse_quote!(#crate_root::AsnType));
108        }
109    }
110
111    Ok(match input.data {
112        syn::Data::Struct(v) => asn_type::derive_struct_impl(name, generics, v, &config)?,
113        syn::Data::Enum(syn::DataEnum { variants, .. }) => r#enum::Enum {
114            name,
115            generics: &generics,
116            variants: &variants,
117            config: &config,
118        }
119        .impl_asntype()?,
120        _ => {
121            return Err(syn::Error::new(
122                name.span(),
123                "Union types are not supported.",
124            ));
125        }
126    })
127}