alox_48_derive/
lib.rs

1#![warn(rust_2018_idioms, clippy::all, clippy::pedantic)]
2use proc_macro::TokenStream;
3
4use syn::DeriveInput;
5
6mod de;
7mod ser;
8mod util;
9
10use darling::{
11    util::{Flag, Override},
12    FromDeriveInput,
13};
14use syn::{Ident, LitStr, Path, Type};
15
16#[derive(Debug, FromDeriveInput)]
17#[darling(attributes(marshal))]
18#[darling(supports(struct_any, enum_any))]
19struct TypeReciever {
20    ident: Ident,
21    data: darling::ast::Data<VariantReciever, FieldReciever>,
22
23    generics: syn::Generics,
24
25    alox_crate_path: Option<Path>,
26
27    class: Option<String>,
28
29    deny_unknown_fields: Flag,
30    enforce_class: Flag,
31
32    #[darling(rename = "default")]
33    default_fn: Option<Override<Path>>,
34    #[darling(rename = "from")]
35    from_type: Option<Type>,
36    #[darling(rename = "into")]
37    into_type: Option<Type>,
38    #[darling(rename = "try_from")]
39    try_from_type: Option<Type>,
40    #[darling(rename = "try_into")]
41    try_into_type: Option<Type>,
42
43    expecting: Option<String>,
44}
45
46#[derive(Debug, darling::FromField)]
47#[darling(attributes(marshal))]
48struct FieldReciever {
49    ident: Option<Ident>,
50    ty: Type,
51
52    rename: Option<LitStr>,
53
54    #[darling(rename = "default")]
55    default_fn: Option<Override<Path>>,
56
57    skip: Flag,
58    skip_serializing: Flag,
59    skip_deserializing: Flag,
60    byte_string: Flag,
61
62    #[darling(rename = "deserialize_with")]
63    deserialize_with_fn: Option<Path>,
64    #[darling(rename = "serialize_with")]
65    serialize_with_fn: Option<Path>,
66    #[darling(rename = "with")]
67    with_module: Option<Path>,
68}
69
70#[allow(dead_code)]
71#[derive(Debug, darling::FromVariant)]
72struct VariantReciever {
73    ident: Ident,
74    fields: darling::ast::Fields<FieldReciever>,
75
76    transparent: Flag,
77    class: Option<String>,
78}
79
80/// Derive `Deserialize` for a struct.
81///
82/// Does not currently support enums.
83///
84/// Type attributes:
85/// - `alox_crate_path`: The path to the alox-48 crate.
86/// - `class`: Override the class that the class enforcer checks for. By default, the class of structs is the struct name.
87/// - `deny_unknown_fields`: If set, the deserializer will error if it encounters a field not in the struct.
88/// - `enforce_class`: If set, the deserializer will enforce that the class matches.
89/// - `default`: The default function to use for a field. Leave empty to use `Default::default`.
90/// - `from`: Deserialize from a different type. That type must implement `Deserialize`.
91/// - `try_from`: Deserialize from a different type. That type must implement `TryFrom`, and its error type must implement `Display`.
92/// - `expecting`: The error message to use if deserialization fails.
93///
94/// Field attributes:
95/// - `rename`: Rename the field.
96/// - `default`: The default function to use for a field. Leave empty to use `Default::default`.
97/// - `skip` or `skip_deserializing`: Skip deserializing the field.
98/// - `deserialize_with`: Use a custom function to deserialize the field. That function must have the signature `fn(impl Deserializer<'de>) -> Result<T, DeError>`.
99/// - `with`: Like `deserialize_with`, but the function is in a module.
100#[proc_macro_derive(Deserialize, attributes(marshal))]
101pub fn derive_deserialize(item: TokenStream) -> TokenStream {
102    let input = syn::parse_macro_input!(item as DeriveInput);
103
104    de::derive_inner(&input).into()
105}
106
107/// Derive `Serialize` for a struct.
108///
109/// Does not currently support enums.
110///
111/// Type attributes:
112/// - `alox_crate_path`: The path to the alox-48 crate.
113/// - `class`: Override the class that this type is serialized as. By default, the class is the struct name.
114/// - `into`: Serialize to a different type. That type must implement `Serialize`, and `Self` must impl `Into<T> + Clone`.
115/// - `try_into`: Serialize to a different type. That type must implement `Serialize`, and Self must impl `TryInto<T> + Clone`.
116///
117/// Field attributes:
118/// - `rename`: Rename the field.
119/// - `skip` or `skip_serializing`: Skip serializing the field.
120/// - `serialize_with`: Use a custom function to serialize the field. That function must have the signature `fn(&T, impl Serializer) -> Result<S::Ok, SerError>`.
121/// - `with`: Like `serialize_with`, but the function is in a module.
122#[proc_macro_derive(Serialize, attributes(marshal))]
123pub fn derive_serialize(item: TokenStream) -> TokenStream {
124    let input = syn::parse_macro_input!(item as DeriveInput);
125
126    ser::derive_inner(&input).into()
127}
128
129// TODO tests