humphrey_json_derive/
lib.rs1#![warn(missing_docs)]
6#![warn(clippy::missing_docs_in_private_items)]
7
8extern crate proc_macro;
9
10mod enum_type;
11mod named_struct;
12mod tuple_struct;
13
14use proc_macro::TokenStream;
15
16use syn::spanned::Spanned;
17use syn::{parse_macro_input, Data, DeriveInput, Error};
18
19#[proc_macro_derive(FromJson, attributes(rename))]
23pub fn derive_from_json(input: TokenStream) -> TokenStream {
24 let ast = parse_macro_input!(input as DeriveInput);
25
26 match &ast.data.clone() {
27 Data::Struct(r#struct) => {
28 if r#struct
29 .fields
30 .iter()
31 .map(|field| field.ident.clone())
32 .all(|ident| ident.is_some())
33 && !r#struct.fields.is_empty()
34 {
35 named_struct::from_json_named_struct(ast, r#struct)
36 } else if !r#struct.fields.is_empty() {
37 tuple_struct::from_json_tuple_struct(ast, r#struct)
38 } else {
39 Error::new(ast.span(), "`FromJson` cannot be derived for empty structs")
40 .to_compile_error()
41 .into()
42 }
43 }
44
45 Data::Enum(r#enum) => {
46 if !r#enum
47 .variants
48 .iter()
49 .any(|variant| !variant.fields.is_empty())
50 {
51 enum_type::from_json_enum(ast, r#enum)
52 } else {
53 Error::new(
54 ast.span(),
55 "`FromJson` cannot be derived for enums with data variants",
56 )
57 .to_compile_error()
58 .into()
59 }
60 }
61
62 _ => Error::new(
63 ast.span(),
64 "`FromJson` can only be derived for non-empty structs and enums",
65 )
66 .to_compile_error()
67 .into(),
68 }
69}
70
71#[proc_macro_derive(IntoJson, attributes(rename))]
75pub fn derive_into_json(input: TokenStream) -> TokenStream {
76 let ast = parse_macro_input!(input as DeriveInput);
77
78 match &ast.data.clone() {
79 Data::Struct(r#struct) => {
80 if r#struct
81 .fields
82 .iter()
83 .map(|field| field.ident.clone())
84 .all(|ident| ident.is_some())
85 && !r#struct.fields.is_empty()
86 {
87 named_struct::into_json_named_struct(ast, r#struct)
88 } else if !r#struct.fields.is_empty() {
89 tuple_struct::into_json_tuple_struct(ast, r#struct)
90 } else {
91 Error::new(ast.span(), "`IntoJson` cannot be derived for empty structs")
92 .to_compile_error()
93 .into()
94 }
95 }
96
97 Data::Enum(r#enum) => {
98 if !r#enum
99 .variants
100 .iter()
101 .any(|variant| !variant.fields.is_empty())
102 {
103 enum_type::into_json_enum(ast, r#enum)
104 } else {
105 Error::new(
106 ast.span(),
107 "`IntoJson` cannot be derived for enums with data variants",
108 )
109 .to_compile_error()
110 .into()
111 }
112 }
113
114 _ => Error::new(
115 ast.span(),
116 "`IntoJson` can only be derived for non-empty structs and enums",
117 )
118 .to_compile_error()
119 .into(),
120 }
121}