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}