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);