enum_update_derive/
lib.rs

1#![warn(missing_docs)]
2//! Derive macros for `enum-update`.
3//!
4//! See the repository README.md for more information.
5use proc_macro::TokenStream;
6mod parse;
7use parse::{convert_ident_to_case, EnumPatch};
8mod construction;
9use construction::{EnumConstructionInfo, EnumConstructionVariant};
10use quote::TokenStreamExt;
11
12/// Generates an enum representing updates to a given struct.
13/// See the README.md for an overview.
14///
15/// The [`EnumUpdate`] macro works by creating a list of "variant groups"
16/// with each group representing a modification to the state struct. By
17/// default, a variant group is constructed for each struct member.
18/// An enum variant is generated for each variant group containing all
19/// changes for fields in that group.
20///
21/// ## Available attributes:
22///
23/// ### `variant_group`
24/// Specifies that a field should belong to an extra group.
25/// ```ignore
26/// #[derive(EnumUpdate)]
27/// pub struct TimeSeriesData {
28///     #[variant_group(RecordOne)]
29///     time: u32,
30///     #[variant_group(RecordOne)]
31///     value_one: u32,
32///     #[variant_group]
33///     value_two: u32
34/// }
35/// ```
36/// will generate
37/// ```
38/// pub enum TimeSeriesDataUpdate {
39///     RecordOne {
40///         time: u32,
41///         value_one: u32,
42///     },
43///     ValueTwo { value_two: u32 },
44/// }
45/// ```
46///
47/// ### `enum_update`
48/// Passes on any provided attributes to the generated enum.
49/// ```ignore
50/// #[derive(EnumUpdate)]
51/// #[enum_update(derive(Debug))]
52/// pub struct State {
53///     #[variant_group]
54///     value: u32
55/// }
56/// ```
57/// will generate
58/// ```
59/// #[derive(Debug)]
60/// pub enum StateUpdate {
61///     Value { value: u32 }
62/// }
63/// ```
64#[proc_macro_derive(EnumUpdate, attributes(variant_group, enum_update))]
65pub fn enum_update_derive(inputs: TokenStream) -> TokenStream {
66    enum_update_derive_impl(inputs).unwrap_or_else(|e| e.to_compile_error().into())
67}
68
69fn enum_update_derive_impl(inputs: TokenStream) -> syn::Result<TokenStream> {
70    let parsed = syn::parse(inputs)?;
71    let receiver = EnumPatch::from_item_struct(&parsed)?;
72    let construction = receiver.to_construction();
73    let mut output = construction.generate_enum();
74    output.append_all(construction.generate_enum_patch_impl());
75    Ok(output.into())
76}
77
78/// Generates setter methods that also return enum updates.
79///
80/// Must be used together with [`EnumUpdate`].
81/// See the README.md for more examples.
82#[proc_macro_derive(
83    EnumUpdateSetters,
84    attributes(variant_group, skip_default, rename_default, enum_update)
85)]
86pub fn enum_update_setters_derive(inputs: TokenStream) -> TokenStream {
87    enum_update_setters_derive_impl(inputs).unwrap_or_else(|e| e.to_compile_error().into())
88}
89fn enum_update_setters_derive_impl(inputs: TokenStream) -> syn::Result<TokenStream> {
90    let parsed = syn::parse(inputs)?;
91    let receiver = EnumPatch::from_item_struct(&parsed)?;
92    let construction = receiver.to_construction();
93    Ok(construction.generate_setters().into())
94}