esrc_derive/
lib.rs

1use darling::FromDeriveInput;
2use proc_macro::TokenStream;
3use syn::{parse_macro_input, DeriveInput};
4
5mod envelope;
6mod event;
7mod util;
8mod version;
9
10#[derive(FromDeriveInput)]
11#[darling(attributes(esrc))]
12struct EsrcAttributes {
13    #[darling(default)]
14    pub event: event::EventMeta,
15    #[darling(default)]
16    pub serde: version::SerdeMeta,
17}
18
19macro_rules! impl_derive {
20    ($(#[$doc:meta])* $target:ident, $method:path $(,)?) => {
21        #[proc_macro_derive($target, attributes(esrc))]
22        #[allow(non_snake_case)]
23        $(#[$doc])*
24        pub fn $target(input: TokenStream) -> TokenStream {
25            let input = parse_macro_input!(input as DeriveInput);
26            let result = $method(input);
27
28            result.unwrap_or_else(|e| e.into_compile_error()).into()
29        }
30    };
31}
32
33impl_derive!(
34    /// Derive a DeserializeVersion implementation, with optional versioning.
35    ///
36    /// Deserialize this type according the the Deserialize implementation,
37    /// if the version number matches what is defined in SerializeVersion.
38    ///
39    /// An `esrc(serde(previous_version))` type can also be specfied; in this
40    /// case, that type's DeserializeVersion is used when the version does not
41    /// match. A successful result is then upcasted with the
42    /// [`From`](`std::convert::From`) implementation defined for the types.
43    ///
44    /// # Example
45    /// ```rust
46    /// # use esrc_derive::{DeserializeVersion, SerializeVersion};
47    /// use serde::{Deserialize, Serialize};
48    ///
49    /// #[derive(Deserialize, DeserializeVersion, Serialize, SerializeVersion)]
50    /// #[esrc(serde(version = 1))]
51    /// struct OldEvent;
52    ///
53    /// #[derive(Deserialize, DeserializeVersion, Serialize, SerializeVersion)]
54    /// #[esrc(serde(version = 2, previous_version = "OldEvent"))]
55    /// struct NewEvent;
56    ///
57    /// impl From<OldEvent> for NewEvent {
58    ///     fn from(value: OldEvent) -> Self {
59    ///         NewEvent
60    ///     }
61    /// }
62    /// ```
63    DeserializeVersion,
64    version::derive_deserialize_version,
65);
66
67impl_derive!(
68    /// Derive an Event implementation, with optional custom naming.
69    ///
70    /// This defines the Event's `name` as the name of the derived type, minus
71    /// the "Event" suffix (if present), unless attributes are specified:
72    /// * `esrc(event(name))` will override the name to the value specified.
73    ///   This is equivalent to implementing the trait manually.
74    /// * `esrc(event(keep_suffix))` will not remove an "Event" suffix that is
75    ///   present on the type name.
76    ///
77    /// # Example
78    /// ```rust
79    /// # use esrc::Event;
80    /// # use esrc_derive::Event;
81    ///
82    /// #[derive(Event)]
83    /// #[esrc(event(name = "BazEvent"))]
84    /// struct FooEvent;
85    ///
86    /// #[derive(Event)]
87    /// struct BarEvent;
88    ///
89    /// print!("{}", FooEvent::name()); // "BazEvent"
90    /// print!("{}", BarEvent::name()); // "Bar"
91    /// ```
92    Event, event::derive_event
93);
94
95impl_derive!(
96    /// Derive an EventGroup implementation for an enum type.
97    ///
98    /// This defines the EventGroup's `names` as a set of each variant's `name`
99    /// (each variant is expected to implement the Event trait).
100    ///
101    /// An `esrc(ignore)` attribute may be specified on individual variants to
102    /// prevent them from being included in this set (it also allows non-Event
103    /// variants to be included in the type).
104    EventGroup,
105    event::derive_event_group,
106);
107
108impl_derive!(
109    /// Derive a SerializeVersion implementation, defaulting to version 1.
110    ///
111    /// A custom version number can be specified as a positive integer with the
112    /// `esrc(serde(version))` attribute.
113    SerializeVersion,
114    version::derive_serialize_version,
115);
116
117impl_derive!(
118    /// Derive a TryFromEnvelope implementation for an enum type.
119    ///
120    /// This defines a method that uses the given Envelope's `name` to determine
121    /// which variant it should be deserialized as (each variant is expected to
122    /// implement the Event trait). If no match found, return an Invalid error.
123    ///
124    /// An `esrc(ignore)` attribute may be specified on individual variants to
125    /// prevent them from being included in this set (it also allows non-Event
126    /// variants to be included in the type).
127    TryFromEnvelope,
128    envelope::derive_try_from_envelope,
129);