aldrin_macros/
lib.rs

1//! # Aldrin macros
2//!
3//! The macros in this crate are not generally meant to be used directly, but through re-exports in
4//! other crates.
5//!
6//! ## Procedural macros
7//!
8//! - [`generate`](generate!): Re-exported in crate `aldrin`
9//! - [`service`](service!): Re-exported in crate `aldrin`
10//!
11//! ## Derive macros
12//!
13//! - [`Tag`]
14//! - [`PrimaryTag`]
15//! - [`RefType`]
16//! - [`Serialize`]
17//! - [`Deserialize`]
18//! - [`Introspectable`]
19//! - [`KeyTag`]
20//! - [`PrimaryKeyTag`]
21//! - [`SerializeKey`]
22//!
23//! All derive macros are re-exported in both `aldrin` and `aldrin-core`.
24//!
25//! ### Attributes
26//!
27//! All derive macros support various attributes and some apply to multiple macros.
28//!
29//! #### Container attributes
30//!
31//! ##### `crate`
32//!
33//! - Applies to: [all derive macros](crate#derive-macros)
34//!
35//! The attribute `#[aldrin(crate = ...)` can be used to override the path of the `aldrin_core`
36//! crate. This is useful when `aldrin_core` is not a direct dependency, but only reexported
37//! somewhere. The default value depends on from where the macro is invoked, it's either
38//! `::aldrin::core` or `::aldrin_core`.
39//!
40//! ```
41//! mod my_reexports {
42//!     pub use aldrin_core as my_aldrin_core;
43//! }
44//!
45//! #[derive(
46//!     my_reexports::my_aldrin_core::Tag,
47//!     my_reexports::my_aldrin_core::PrimaryTag,
48//!     my_reexports::my_aldrin_core::RefType,
49//!     my_reexports::my_aldrin_core::Serialize,
50//!     my_reexports::my_aldrin_core::Deserialize,
51//! )]
52//! #[aldrin(crate = my_reexports::my_aldrin_core, ref_type)]
53//! struct Person {
54//!     name: String,
55//! }
56//! ```
57//!
58//! ##### `schema`
59//!
60//! - Applies to: [`Introspectable`]
61//!
62//! Deriving `Introspectable` requires specifying a schema name. It is an error if this attribute is
63//! missing.
64//!
65//! ```
66//! # use aldrin_core::Introspectable;
67//! #[derive(Introspectable)]
68//! #[aldrin(schema = "contacts")]
69//! struct Person {
70//!     name: String,
71//! }
72//! ```
73//!
74//! ##### `ref_type`
75//!
76//! - Applies to: [`RefType`], [`Serialize`] and [`SerializeKey`]
77//!
78//! Deriving `RefType` requires specifying an identifier for the type with the
79//! `#[aldrin(ref_type = ...)]` attribute. The `Serialize` and `SerializeKey` derive macro will then
80//! also generate implementations for that type.
81//!
82//! It is also possible to specifiy just `#[aldrin(ref_type)]` without an identifer. In this case, a
83//! default will be chosen by appending `Ref` to the name of the annotated type.
84//!
85//! ##### `newtype`
86//!
87//! - Applies to: [`Serialize`], [`Deserialize`], [`KeyTag`], [`PrimaryKeyTag`], [`SerializeKey`],
88//!   and [`DeserializeKey`].
89//!
90//! Specifying `#[aldrin(newtype)]` is possible for structs with exactly 1 field and makes them
91//! behave like that field. E.g., the type will no longer serialize as a struct, but directly as
92//! that field instead.
93//!
94//! ```
95//! # use aldrin_core::{
96//! #     Deserialize, DeserializeKey, KeyTag, PrimaryKeyTag, PrimaryTag, Serialize, SerializeKey,
97//! #     Tag,
98//! # };
99//! #[derive(
100//!     Tag,
101//!     KeyTag,
102//!     PrimaryTag,
103//!     PrimaryKeyTag,
104//!     Serialize,
105//!     SerializeKey,
106//!     Deserialize,
107//!     DeserializeKey,
108//! )]
109//! #[aldrin(newtype)]
110//! struct Name {
111//!     inner: String,
112//! }
113//! ```
114//!
115//! ##### `doc`
116//!
117//! - Applies to: [`Introspectable`]
118//!
119//! Provides an alternative doc string used only for deriving [`Introspectable`]. Note that this
120//! attribute can be used anywhere a regular doc comment can be used as well.
121//!
122//! If this is not provided then [`Introspectable`] will fall back to the regular doc comment (if
123//! present).
124//!
125//! Using this attribute can be desirable if the regular doc comment is Rust-specific, e.g. due to
126//! link conversion or other modifications.
127//!
128//! ```
129//! # use aldrin_core::{Introspectable};
130//! /// This doc comment will be rendered by rustdoc.
131//! #[derive(Introspectable)]
132//! #[aldrin(schema = "family_tree")]
133//! #[aldrin(doc = "This doc comment will be used for introspection.")]
134//! struct Name {
135//!     /// This doc comment will be rendered by rustdoc.
136//!     #[aldrin(doc = "This doc comment will be used for introspection.")]
137//!     inner: String,
138//! }
139//! ```
140//!
141//! #### Field and variant attributes
142//!
143//! ##### `id`
144//!
145//! - Applies to: [`Serialize`], [`Deserialize`] and [`Introspectable`]
146//!
147//! Use `#[aldrin(id = ...)]` to override the automatically defined id for a field or variant.
148//!
149//! Default ids start at 0 for the first field or variant and then increment by 1 for each
150//! subsequent field or variant.
151//!
152//! ```
153//! # use aldrin_core::{Deserialize, Introspectable, PrimaryTag, RefType, Serialize, Tag};
154//! #[derive(Tag, PrimaryTag, RefType, Serialize, Deserialize, Introspectable)]
155//! #[aldrin(schema = "family_tree", ref_type)]
156//! struct Person {
157//!     age: u8, // id = 0
158//!
159//!     #[aldrin(id = 5)]
160//!     name: String, // id = 5
161//!
162//!     siblings: Vec<Self>, // id = 6
163//! }
164//! ```
165//!
166//! ```
167//! # use aldrin_core::{Deserialize, Introspectable, PrimaryTag, RefType, Serialize, Tag};
168//! #[derive(Tag, PrimaryTag, RefType, Serialize, Deserialize, Introspectable)]
169//! #[aldrin(schema = "pets", ref_type)]
170//! enum Pet {
171//!     Dog, // id = 0
172//!
173//!     #[aldrin(id = 5)]
174//!     Cat, // id = 5
175//!
176//!     Alpaca, // id = 6
177//! }
178//! ```
179//!
180//! ##### `optional`
181//!
182//! - Applies to: [`Serialize`], [`Deserialize`] and [`Introspectable`]
183//!
184//! Use `#[aldrin(optional)]` to mark fields of a struct as optional. They must be of an `Option<T>`
185//! type.
186//!
187//! Optional fields are not serialized if `None` and are allowed to be missing when deserializing a
188//! value.
189//!
190//! ```
191//! # use aldrin_core::{Deserialize, Introspectable, PrimaryTag, RefType, Serialize, Tag};
192//! #[derive(Tag, PrimaryTag, RefType, Serialize, Deserialize, Introspectable)]
193//! #[aldrin(schema = "example", ref_type)]
194//! struct MyStruct {
195//!     required_field_1: i32,
196//!     required_field_2: Option<i32>,
197//!
198//!     #[aldrin(optional)]
199//!     optional_field: Option<i32>,
200//! }
201//! ```
202//!
203//! Both fields `required_field_1` and `required_field_2` will always be serialized and
204//! deserialization will fail if either is missing. Serialization of `optional_field` is skipped if
205//! it is `None`. If it's missing during deserialization, then it will be set to `None`.
206//!
207//! ##### `fallback`
208//!
209//! - Applies to: [`Serialize`], [`Deserialize`] and [`Introspectable`]
210//!
211//! The last field of a struct and the last variant of an enum can optionally be marked with
212//! `#[aldrin(fallback)]`. This will enable successful serialization and deserialization of unknown
213//! fields and variants. For structs, the field type must be `aldrin_core::UnknownFields`. For
214//! enums, the variant must have a single field of type `aldrin_core::UnknownVariant`.
215//!
216//! This attribute cannot be combined with `#[aldrin(optional)]`.
217//!
218//! Example of a struct with a fallback field:
219//! ```
220//! # use aldrin_core::{Deserialize, Introspectable, PrimaryTag, RefType, Serialize, Tag, UnknownFields};
221//! #[derive(Tag, PrimaryTag, RefType, Serialize, Deserialize, Introspectable)]
222//! #[aldrin(schema = "contacts", ref_type)]
223//! struct Person {
224//!     name: String,
225//!     age: u8,
226//!
227//!     #[aldrin(fallback)]
228//!     unknown_fields: UnknownFields,
229//! }
230//! ```
231//!
232//! Example of an enum with a fallback variant:
233//! ```
234//! # use aldrin_core::{Deserialize, Introspectable, PrimaryTag, RefType, Serialize, Tag, UnknownVariant};
235//! #[derive(Tag, PrimaryTag, RefType, Serialize, Deserialize, Introspectable)]
236//! #[aldrin(schema = "zoo", ref_type)]
237//! enum AnimalType {
238//!     Alpaca,
239//!     Pig,
240//!
241//!     #[aldrin(fallback)]
242//!     Unkown(UnknownVariant),
243//! }
244//! ```
245//!
246//! ##### `doc`
247//!
248//! - Applies to: [`Introspectable`]
249//!
250//! See [`doc` for containers](Self#doc).
251
252#![deny(missing_docs)]
253
254extern crate proc_macro;
255
256mod codegen;
257mod derive;
258mod doc_string;
259mod service;
260#[cfg(test)]
261mod test;
262mod util;
263
264use proc_macro2::TokenStream;
265use syn::{DeriveInput, Result};
266
267/// Generates code from an Aldrin schema.
268///
269/// This macro provides a front-end to the Aldrin code generator. It is an alternative to running
270/// the standalone `aldrin-gen` tool.
271///
272/// # Basic usage
273///
274/// The [`generate!`] macro takes one required argument, the path to the schema file. Paths can be
275/// relative to `Cargo.toml` file. This requires building with Cargo (or more specifically, the
276/// `CARGO_MANIFEST_DIR` environment variable). Building without Cargo currently supports only
277/// absolute paths.
278///
279/// The generated code depends only the `aldrin` crate. Make sure you have it specified as a
280/// dependency in your `Cargo.toml`.
281///
282/// ```
283/// # use aldrin_macros::generate;
284/// generate!("schemas/example1.aldrin");
285///
286/// fn main() {
287///     example1::MyStruct {
288///         field1: Some(1),
289///         field2: None,
290///     };
291/// }
292/// ```
293///
294/// This generates the module `example1` with the same content as if the stand-alone code generator
295/// was used.
296///
297/// The module has `pub` visibility, which is not always desired, especially in library crates. A
298/// common pattern is to put the generated modules inside an additional `schemas` module:
299///
300/// ```
301/// mod schemas {
302///     # use aldrin_macros::generate;
303///     generate!("schemas/example1.aldrin");
304/// }
305/// ```
306///
307/// If you have only a single schema, it is occasionally convenient to put the generated code inside
308/// another module (like above), but then also re-export everything into it:
309///
310/// ```
311/// mod schema {
312///     # use aldrin_macros::generate;
313///     generate!("schemas/example1.aldrin");
314///     pub use example1::*;
315/// }
316///
317/// fn main() {
318///     schema::MyStruct { // Note `schema` instead of `example1`.
319///         field1: Some(1),
320///         field2: None,
321///     };
322/// }
323/// ```
324///
325/// # Multiple schemas
326///
327/// It is possible to pass additional paths to the macro. Code will then be generated for all of
328/// them:
329///
330/// ```
331/// # use aldrin_macros::generate;
332/// generate! {
333///     "schemas/example1.aldrin",
334///     "schemas/example2.aldrin",
335/// }
336/// # fn main() {}
337/// ```
338///
339/// Any additional options (see below) will be applied to all schemas. If this is not desired, then
340/// the macro can be called multiple times instead.
341///
342/// # Include directories
343///
344/// You can specify include directories with `include = "path"`:
345///
346/// ```
347/// # use aldrin_macros::generate;
348/// generate! {
349///     "schemas/example3.aldrin",
350///     "schemas/example4.aldrin",
351///     include = "schemas",
352/// }
353///
354/// fn main() {
355///     example3::Foo {
356///         bar: Some(example4::Bar {
357///             baz: Some(12),
358///         }),
359///     };
360/// }
361/// ```
362///
363/// The `include` option can be repeated multiple times.
364///
365/// # Skipping server or client code
366///
367/// You can skip generating server or client code for services by setting `server = false` or
368/// `client = false`. This will only affect services and types defined inside (inline structs and
369/// enums), but not other top-level definitions.
370///
371/// Both settings default to `true`.
372///
373/// # Patching the generated code
374///
375/// You can specify additional patch files, which will be applied to the generated code. This allows
376/// for arbitrary changes, such as for example custom additional derives.
377///
378/// Patches can only be specified when generating code for a single schema.
379///
380/// ```
381/// # use aldrin_macros::generate;
382/// generate! {
383///     "schemas/example1.aldrin",
384///     patch = "schemas/example1-rename.patch",
385/// }
386///
387/// fn main() {
388///     example1::MyStructRenamed {
389///         field1: Some(1),
390///         field2: None,
391///     };
392/// }
393/// ```
394///
395/// Patches are applied in the order they are specified.
396///
397/// ```
398/// # use aldrin_macros::generate;
399/// generate! {
400///     "schemas/example1.aldrin",
401///     patch = "schemas/example1-rename.patch",
402///     patch = "schemas/example1-rename-again.patch",
403/// }
404///
405/// fn main() {
406///     example1::MyStructRenamedAgain {
407///         field1: Some(1),
408///         field2: None,
409///     };
410/// }
411/// ```
412///
413/// # Enabling introspection
414///
415/// To enable introspection support, pass `introspection = true` to the macro. This additionally
416/// requires enabling the `introspection` Cargo feature of the `aldrin` crate.
417///
418/// ```
419/// # use aldrin_macros::generate;
420/// generate! {
421///     "schemas/example1.aldrin",
422///     introspection = true,
423/// }
424/// ```
425///
426/// It is also possible to conditionally enable introspection based on some Cargo feature by setting
427/// `introspection_if`. This implies setting `introspection = true`. The following example will have
428/// introspection code generated, but guards of the form `#[cfg(feature = "introspection")]` added.
429///
430/// ```
431/// # use aldrin_macros::generate;
432/// generate! {
433///     "schemas/example1.aldrin",
434///     introspection_if = "introspection",
435/// }
436/// ```
437///
438/// # Errors and warnings
439///
440/// Any errors from the schemas will be shown as part of the regular compiler output and no code
441/// will be generated.
442///
443/// Warnings are currently not emitted, due to limitations on stable Rust. Unfortunately, this may
444/// suppress important diagnostics about your schemas. You can use the option
445/// `warnings_as_errors = true` to treat all warnings as errors.
446///
447/// ```compile_fail
448/// # use aldrin_macros::generate;
449/// generate! {
450///     "schemas/example5.aldrin",
451///     warnings_as_errors = true,
452/// }
453/// # fn main() {}
454/// ```
455///
456/// # Overriding the path of the `aldrin` crate
457///
458/// The macro assumes per default that the `aldrin` crate is available as `::aldrin`. This can be
459/// overridden with the `crate` attribute. Note that [`generate!`] creates a new module and that
460/// path resolution starts inside that module.
461///
462/// ```
463/// # use aldrin_macros::generate;
464/// # fn main() {}
465/// mod my_reexports {
466///     pub use aldrin as my_aldrin;
467/// }
468///
469/// generate! {
470///     "schemas/example1.aldrin",
471///     crate = super::my_reexports::my_aldrin,
472/// }
473/// ```
474#[manyhow::manyhow]
475#[proc_macro]
476pub fn generate(args: codegen::Args, emitter: &mut manyhow::Emitter) -> manyhow::Result {
477    codegen::generate(args, emitter)
478}
479
480/// Defines a service and proxy type.
481///
482/// The form this macro takes closely resembles that of services in Aldrin schema, but it uses
483/// actual Rust expressions and types.
484///
485/// ```
486/// # use aldrin::core::ServiceUuid;
487/// # use aldrin_macros::{service, Deserialize, PrimaryTag, RefType, Serialize, Tag};
488/// # use uuid::uuid;
489/// service! {
490///     pub service Echo {
491///         uuid = ServiceUuid(uuid!("ee98534d-345a-4399-a656-07fd9c39a96e"));
492///         version = 1;
493///
494///         fn echo @ 1 {
495///             args = String;
496///             ok = String;
497///             err = Error;
498///         }
499///
500///         fn echo_all @ 2 {
501///             args = String;
502///             err = Error;
503///         }
504///
505///         event echoed_to_all @ 1 = String;
506///     }
507/// }
508///
509/// #[derive(Tag, PrimaryTag, RefType, Serialize, Deserialize)]
510/// #[aldrin(ref_type)]
511/// pub enum Error {
512///     EmptyString,
513/// }
514/// ```
515///
516/// # Overriding the path to the `aldrin` crate
517///
518/// Use the `#[aldrin(crate = ...)]` attribute to override the path to the `aldrin` crate.
519///
520/// ```
521/// # use aldrin::core::ServiceUuid;
522/// # use aldrin_macros::service;
523/// # use uuid::uuid;
524/// mod my_reexports {
525///     pub use aldrin as my_aldrin;
526/// }
527///
528/// service! {
529///     #[aldrin(crate = my_reexports::my_aldrin)]
530///     pub service Ping {
531///         uuid = ServiceUuid(uuid!("b6633b9f-c26d-4987-8ec0-5c8e526290f9"));
532///         version = 1;
533///     }
534/// }
535/// ```
536///
537/// # Generating only client or server code
538///
539/// Client and server code generation can be disabled individually with the
540/// `#[aldrin(client = false)]` and `#[aldrin(server = false)]` attributes.
541///
542/// The following examples uses `client = false` and thus no `PingProxy` type will be generated.
543///
544/// ```
545/// # use aldrin::core::ServiceUuid;
546/// # use aldrin_macros::service;
547/// # use uuid::uuid;
548/// service! {
549///     #[aldrin(client = false)]
550///     pub service Ping {
551///         uuid = ServiceUuid(uuid!("b6633b9f-c26d-4987-8ec0-5c8e526290f9"));
552///         version = 1;
553///     }
554/// }
555/// ```
556///
557/// # Introspection
558///
559/// The `Introspectable` trait can be implemented automatically by specifying the
560/// `#[aldrin(introspection)]` attribute. It also requires the `#[aldrin(schema = "...")]` attribute
561/// and all referenced types must be `Introspectable`.
562///
563/// ```
564/// # use aldrin::core::ServiceUuid;
565/// # use aldrin_macros::service;
566/// # use uuid::uuid;
567/// service! {
568///     #[aldrin(schema = "ping", introspection)]
569///     pub service Ping {
570///         uuid = ServiceUuid(uuid!("b6633b9f-c26d-4987-8ec0-5c8e526290f9"));
571///         version = 1;
572///     }
573/// }
574/// ```
575///
576/// It is also possible to implement `Introspectable` conditionally depending on some Cargo feature
577/// with the `#[aldrin(introspection_if = "...")]` attribute.
578///
579/// ```
580/// # use aldrin::core::ServiceUuid;
581/// # use aldrin_macros::service;
582/// # use uuid::uuid;
583/// service! {
584///     #[aldrin(schema = "ping", introspection_if = "introspection")]
585///     pub service Ping {
586///         uuid = ServiceUuid(uuid!("b6633b9f-c26d-4987-8ec0-5c8e526290f9"));
587///         version = 1;
588///     }
589/// }
590/// ```
591#[manyhow::manyhow]
592#[proc_macro]
593pub fn service(svc: service::Service) -> TokenStream {
594    svc.generate()
595}
596
597/// Derive macro for the `Tag` trait.
598///
599/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
600/// information about the supported attributes.
601///
602/// Relevant attributes:
603/// - [`crate`](crate#crate)
604#[manyhow::manyhow]
605#[proc_macro_derive(Tag, attributes(aldrin))]
606pub fn tag_from_core(input: DeriveInput) -> Result<TokenStream> {
607    derive::gen_tag_from_core(input)
608}
609
610/// Derive macro for the `Tag` trait.
611///
612/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
613/// information about the supported attributes.
614///
615/// Relevant attributes:
616/// - [`crate`](crate#crate)
617#[doc(hidden)]
618#[manyhow::manyhow]
619#[proc_macro_derive(TagFromAldrin, attributes(aldrin))]
620pub fn tag_from_aldrin(input: DeriveInput) -> Result<TokenStream> {
621    derive::gen_tag_from_aldrin(input)
622}
623
624/// Derive macro for the `PrimaryTag` trait.
625///
626/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
627/// information about the supported attributes.
628///
629/// Relevant attributes:
630/// - [`crate`](crate#crate)
631#[manyhow::manyhow]
632#[proc_macro_derive(PrimaryTag, attributes(aldrin))]
633pub fn primary_tag_from_core(input: DeriveInput) -> Result<TokenStream> {
634    derive::gen_primary_tag_from_core(input)
635}
636
637/// Derive macro for the `PrimaryTag` trait.
638///
639/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
640/// information about the supported attributes.
641///
642/// Relevant attributes:
643/// - [`crate`](crate#crate)
644#[doc(hidden)]
645#[manyhow::manyhow]
646#[proc_macro_derive(PrimaryTagFromAldrin, attributes(aldrin))]
647pub fn primary_tag_from_aldrin(input: DeriveInput) -> Result<TokenStream> {
648    derive::gen_primary_tag_from_aldrin(input)
649}
650
651/// Derive macro for ref types.
652///
653/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
654/// information about the supported attributes.
655///
656/// Relevant attributes:
657/// - [`crate`](crate#crate)
658/// - [`ref_type`](crate#ref_type)
659#[manyhow::manyhow]
660#[proc_macro_derive(RefType, attributes(aldrin))]
661pub fn ref_type_from_core(input: DeriveInput) -> Result<TokenStream> {
662    derive::gen_ref_type_from_core(input)
663}
664
665/// Derive macro for ref types.
666///
667/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
668/// information about the supported attributes.
669///
670/// Relevant attributes:
671/// - [`crate`](crate#crate)
672/// - [`ref_type`](crate#ref_type)
673#[doc(hidden)]
674#[manyhow::manyhow]
675#[proc_macro_derive(RefTypeFromAldrin, attributes(aldrin))]
676pub fn ref_type_from_aldrin(input: DeriveInput) -> Result<TokenStream> {
677    derive::gen_ref_type_from_aldrin(input)
678}
679
680/// Derive macro for the `Serialize` trait.
681///
682/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
683/// information about the supported attributes.
684///
685/// Relevant attributes:
686/// - [`crate`](crate#crate)
687/// - [`ref_type`](crate#ref_type)
688/// - [`newtype`](crate#newtype)
689/// - [`id`](crate#id)
690/// - [`optional`](crate#optional)
691/// - [`fallback`](crate#fallback)
692#[manyhow::manyhow]
693#[proc_macro_derive(Serialize, attributes(aldrin))]
694pub fn serialize_from_core(input: DeriveInput) -> Result<TokenStream> {
695    derive::gen_serialize_from_core(input)
696}
697
698/// Derive macro for the `Serialize` trait.
699///
700/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
701/// information about the supported attributes.
702///
703/// Relevant attributes:
704/// - [`crate`](crate#crate)
705/// - [`ref_type`](crate#ref_type)
706/// - [`newtype`](crate#newtype)
707/// - [`id`](crate#id)
708/// - [`optional`](crate#optional)
709/// - [`fallback`](crate#fallback)
710#[doc(hidden)]
711#[manyhow::manyhow]
712#[proc_macro_derive(SerializeFromAldrin, attributes(aldrin))]
713pub fn serialize_from_aldrin(input: DeriveInput) -> Result<TokenStream> {
714    derive::gen_serialize_from_aldrin(input)
715}
716
717/// Derive macro for the `Deserialize` trait.
718///
719/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
720/// information about the supported attributes.
721///
722/// Relevant attributes:
723/// - [`crate`](crate#crate)
724/// - [`newtype`](crate#newtype)
725/// - [`id`](crate#id)
726/// - [`optional`](crate#optional)
727/// - [`fallback`](crate#fallback)
728#[manyhow::manyhow]
729#[proc_macro_derive(Deserialize, attributes(aldrin))]
730pub fn deserialize_from_core(input: DeriveInput) -> Result<TokenStream> {
731    derive::gen_deserialize_from_core(input)
732}
733
734/// Derive macro for the `Deserialize` trait.
735///
736/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
737/// information about the supported attributes.
738///
739/// Relevant attributes:
740/// - [`crate`](crate#crate)
741/// - [`newtype`](crate#newtype)
742/// - [`id`](crate#id)
743/// - [`optional`](crate#optional)
744/// - [`fallback`](crate#fallback)
745#[doc(hidden)]
746#[manyhow::manyhow]
747#[proc_macro_derive(DeserializeFromAldrin, attributes(aldrin))]
748pub fn deserialize_from_aldrin(input: DeriveInput) -> Result<TokenStream> {
749    derive::gen_deserialize_from_aldrin(input)
750}
751
752/// Derive macro for the `Introspectable` trait.
753///
754/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
755/// information about the supported attributes.
756///
757/// Relevant attributes:
758/// - [`crate`](crate#crate)
759/// - [`schema`](crate#schema)
760/// - [`id`](crate#id)
761/// - [`optional`](crate#optional)
762/// - [`fallback`](crate#fallback)
763#[manyhow::manyhow]
764#[proc_macro_derive(Introspectable, attributes(aldrin))]
765pub fn introspectable_from_core(input: DeriveInput) -> Result<TokenStream> {
766    derive::gen_introspectable_from_core(input)
767}
768
769/// Derive macro for the `Introspectable` trait.
770///
771/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
772/// information about the supported attributes.
773///
774/// Relevant attributes:
775/// - [`crate`](crate#crate)
776/// - [`schema`](crate#schema)
777/// - [`id`](crate#id)
778/// - [`optional`](crate#optional)
779/// - [`fallback`](crate#fallback)
780#[doc(hidden)]
781#[manyhow::manyhow]
782#[proc_macro_derive(IntrospectableFromAldrin, attributes(aldrin))]
783pub fn introspectable_from_aldrin(input: DeriveInput) -> Result<TokenStream> {
784    derive::gen_introspectable_from_aldrin(input)
785}
786
787/// Derive macro for the `KeyTag` trait.
788///
789/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
790/// information about the supported attributes.
791///
792/// Relevant attributes:
793/// - [`crate`](crate#crate)
794/// - [`newtype`](crate#newtype)
795#[manyhow::manyhow]
796#[proc_macro_derive(KeyTag, attributes(aldrin))]
797pub fn key_tag_from_core(input: DeriveInput) -> Result<TokenStream> {
798    derive::gen_key_tag_from_core(input)
799}
800
801/// Derive macro for the `KeyTag` trait.
802///
803/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
804/// information about the supported attributes.
805///
806/// Relevant attributes:
807/// - [`crate`](crate#crate)
808/// - [`newtype`](crate#newtype)
809#[doc(hidden)]
810#[manyhow::manyhow]
811#[proc_macro_derive(KeyTagFromAldrin, attributes(aldrin))]
812pub fn key_tag_from_aldrin(input: DeriveInput) -> Result<TokenStream> {
813    derive::gen_key_tag_from_aldrin(input)
814}
815
816/// Derive macro for the `PrimaryKeyTag` trait.
817///
818/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
819/// information about the supported attributes.
820///
821/// Relevant attributes:
822/// - [`crate`](crate#crate)
823/// - [`newtype`](crate#newtype)
824#[manyhow::manyhow]
825#[proc_macro_derive(PrimaryKeyTag, attributes(aldrin))]
826pub fn primary_key_tag_from_core(input: DeriveInput) -> Result<TokenStream> {
827    derive::gen_primary_key_tag_from_core(input)
828}
829
830/// Derive macro for the `PrimaryKeyTag` trait.
831///
832/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
833/// information about the supported attributes.
834///
835/// Relevant attributes:
836/// - [`crate`](crate#crate)
837/// - [`newtype`](crate#newtype)
838#[doc(hidden)]
839#[manyhow::manyhow]
840#[proc_macro_derive(PrimaryKeyTagFromAldrin, attributes(aldrin))]
841pub fn primary_key_tag_from_aldrin(input: DeriveInput) -> Result<TokenStream> {
842    derive::gen_primary_key_tag_from_aldrin(input)
843}
844
845/// Derive macro for the `SerializeKey` trait.
846///
847/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
848/// information about the supported attributes.
849///
850/// Relevant attributes:
851/// - [`crate`](crate#crate)
852/// - [`newtype`](crate#newtype)
853/// - [`ref_type`](crate#ref_type)
854#[manyhow::manyhow]
855#[proc_macro_derive(SerializeKey, attributes(aldrin))]
856pub fn serialize_key_from_core(input: DeriveInput) -> Result<TokenStream> {
857    derive::gen_serialize_key_from_core(input)
858}
859
860/// Derive macro for the `SerializeKey` trait.
861///
862/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
863/// information about the supported attributes.
864///
865/// Relevant attributes:
866/// - [`crate`](crate#crate)
867/// - [`newtype`](crate#newtype)
868#[doc(hidden)]
869#[manyhow::manyhow]
870#[proc_macro_derive(SerializeKeyFromAldrin, attributes(aldrin))]
871pub fn serialize_key_from_aldrin(input: DeriveInput) -> Result<TokenStream> {
872    derive::gen_serialize_key_from_aldrin(input)
873}
874
875/// Derive macro for the `DeserializeKey` trait.
876///
877/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
878/// information about the supported attributes.
879///
880/// Relevant attributes:
881/// - [`crate`](crate#crate)
882/// - [`newtype`](crate#newtype)
883#[manyhow::manyhow]
884#[proc_macro_derive(DeserializeKey, attributes(aldrin))]
885pub fn deserialize_key_from_core(input: DeriveInput) -> Result<TokenStream> {
886    derive::gen_deserialize_key_from_core(input)
887}
888
889/// Derive macro for the `DeserializeKey` trait.
890///
891/// See the [crate-level](crate#attributes) documentation in the `aldrin-macros` crate for more
892/// information about the supported attributes.
893///
894/// Relevant attributes:
895/// - [`crate`](crate#crate)
896/// - [`newtype`](crate#newtype)
897#[doc(hidden)]
898#[manyhow::manyhow]
899#[proc_macro_derive(DeserializeKeyFromAldrin, attributes(aldrin))]
900pub fn deserialize_key_from_aldrin(input: DeriveInput) -> Result<TokenStream> {
901    derive::gen_deserialize_key_from_aldrin(input)
902}