deserr_internal/
lib.rs

1extern crate proc_macro;
2
3mod attribute_parser;
4mod derive_enum;
5mod derive_named_fields;
6mod derive_struct;
7mod derive_user_provided_function;
8mod parse_type;
9
10use attribute_parser::TagType;
11use derive_named_fields::generate_named_fields_impl;
12use parse_type::{DerivedTypeInfo, TraitImplementationInfo, VariantData};
13use proc_macro::TokenStream;
14use proc_macro2::Span;
15use syn::{parse_macro_input, DeriveInput};
16
17#[proc_macro_derive(Deserr, attributes(deserr, serde))]
18pub fn derive_deserialize(input: TokenStream) -> TokenStream {
19    let input = parse_macro_input!(input as DeriveInput);
20
21    match DerivedTypeInfo::parse(input) {
22        Ok(derived_type_info) => match derived_type_info.data {
23            TraitImplementationInfo::Struct(fields) => {
24                derive_struct::generate_derive_struct_impl(derived_type_info.common, fields).into()
25            }
26            TraitImplementationInfo::Enum { tag, variants } => match tag {
27                TagType::Internal(tag_key) => derive_enum::generate_derive_tagged_enum_impl(
28                    derived_type_info.common,
29                    tag_key,
30                    variants,
31                )
32                .into(),
33                TagType::External
34                    if variants
35                        .iter()
36                        .all(|variant| matches!(variant.data, VariantData::Unit)) =>
37                {
38                    derive_enum::generate_derive_untagged_enum_impl(
39                        derived_type_info.common,
40                        variants,
41                    )
42                    .into()
43                }
44                TagType::External =>
45                    syn::Error::new(
46                        Span::call_site(),
47                        r#"Externally tagged enums are not supported yet by deserr. Add #[deserr(tag = "some_tag_key")]"#,
48                ).to_compile_error().into()
49            },
50            TraitImplementationInfo::UnfallibleUserProvidedFunction { from_attr } => {
51                derive_user_provided_function::generate_derive_from_user_function(
52                    derived_type_info.common,
53                    from_attr,
54                )
55                .into()
56            }
57            TraitImplementationInfo::FallibleUserProvidedFunction { try_from_attr } => {
58                derive_user_provided_function::generate_derive_try_from_user_function(
59                    derived_type_info.common,
60                    try_from_attr,
61                )
62                .into()
63            }
64        },
65        Err(e) => e.to_compile_error().into(),
66    }
67}