rkyv_derive/
lib.rs

1//! Procedural macros for `rkyv`.
2
3#![deny(
4    rustdoc::broken_intra_doc_links,
5    missing_docs,
6    rustdoc::missing_crate_level_docs
7)]
8
9mod archive;
10mod attributes;
11mod deserialize;
12mod repr;
13mod serde;
14mod serialize;
15mod util;
16mod with;
17
18extern crate proc_macro;
19
20use syn::{parse_macro_input, DeriveInput};
21
22/// Derives `Archive` for the labeled type.
23///
24/// # Attributes
25///
26/// Additional arguments can be specified using the `#[archive(...)]` and `#[archive_attr(...)]`
27/// attributes.
28///
29/// `#[archive(...)]` takes the following arguments:
30///
31/// - `archived = "..."`: Changes the name of the generated archived type to the given value. By
32///   default, archived types are named "Archived" + `the name of the type`.
33/// - `resolver = "..."`: Changes the name of the generated resolver type to the given value. By
34///   default, resolver types are named `the name of the type` + "Resolver".
35/// - `repr(...)`: *Deprecated, use `#[archive_attr(repr(...))]` instead.* Sets the representation
36///   for the archived type to the given representation. Available representation options may vary
37///   depending on features and type layout.
38/// - `compare(...)`: Implements common comparison operators between the original and archived
39///   types. Supported comparisons are `PartialEq` and `PartialOrd` (i.e.
40///   `#[archive(compare(PartialEq, PartialOrd))]`).
41/// - `bound(...)`: Adds additional bounds to trait implementations. This can be especially useful
42///   when dealing with recursive structures, where bounds may need to be omitted to prevent
43///   recursive type definitions. Use `archive = "..."` to specify `Archive` bounds,
44///   `serialize = "..."` to specify `Serialize` bounds, and `deserialize = "..."` to specify
45///   `Deserialize` bounds.
46/// - `check_bytes`: Derive `CheckBytes` on the archived type, in order to enable safe
47///   deserialization. Requires `validation` feature. Not compatible with `as = "..."`. In that
48///   case, use `#[derive(CheckBytes)]` on the archived type, and include a `use rkyv::bytecheck`
49///   statement.
50/// - `copy_safe`: States that the archived type is tightly packed with no padding bytes. This
51///   qualifies it for copy optimizations. (requires nightly)
52/// - `as = "..."`: Instead of generating a separate archived type, this type will archive as the
53///   named type. This is useful for types which are generic over their parameters.
54/// - `crate = "..."`: Chooses an alternative crate path to import rkyv from.
55///
56/// `#[archive_attr(...)]` adds the attributes passed as arguments as attributes to the generated
57/// type. This is commonly used with attributes like `derive(...)` to derive trait implementations
58/// for the archived type.
59///
60/// # Recursive types
61///
62/// This derive macro automatically adds a type bound `field: Archive` for each field type. This can
63/// cause an overflow while evaluating trait bounds if the structure eventually references its own
64/// type, as the implementation of `Archive` for a struct depends on each field type implementing it
65/// as well. Adding the attribute `#[omit_bounds]` to a field will suppress this trait bound and
66/// allow recursive structures. This may be too coarse for some types, in which case additional type
67/// bounds may be required with `bound(...)`.
68///
69/// # Wrappers
70///
71/// Wrappers transparently customize archived types by providing different implementations of core
72/// traits. For example, references cannot be archived, but the `Inline` wrapper serializes a
73/// reference as if it were a field of the struct. Wrappers can be applied to fields using the
74/// `#[with(...)]` attribute. Multiple wrappers can be used, and they are applied in reverse order
75/// (i.e. `#[with(A, B, C)]` will archive `MyType` as `With<With<With<MyType, C>, B, A>`).
76#[proc_macro_derive(Archive, attributes(archive, archive_attr, omit_bounds, with))]
77pub fn derive_archive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
78    let mut derive_input = parse_macro_input!(input as DeriveInput);
79    serde::receiver::replace_receiver(&mut derive_input);
80
81    match archive::derive(derive_input) {
82        Ok(result) => result.into(),
83        Err(e) => e.to_compile_error().into(),
84    }
85}
86
87/// Derives `Serialize` for the labeled type.
88///
89/// This macro also supports the `#[archive]`, `#[omit_bounds]`, and `#[with]` attributes. See
90/// [`Archive`] for more information.
91#[proc_macro_derive(Serialize, attributes(archive, omit_bounds, with))]
92pub fn derive_serialize(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
93    let mut derive_input = parse_macro_input!(input as DeriveInput);
94    serde::receiver::replace_receiver(&mut derive_input);
95
96    match serialize::derive(derive_input) {
97        Ok(result) => result.into(),
98        Err(e) => e.to_compile_error().into(),
99    }
100}
101
102/// Derives `Deserialize` for the labeled type.
103///
104/// This macro also supports the `#[archive]`, `#[omit_bounds]`, and `#[with]` attributes. See
105/// [`Archive`] for more information.
106#[proc_macro_derive(Deserialize, attributes(archive, omit_bounds, with))]
107pub fn derive_deserialize(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
108    let mut derive_input = parse_macro_input!(input as DeriveInput);
109    serde::receiver::replace_receiver(&mut derive_input);
110
111    match deserialize::derive(derive_input) {
112        Ok(result) => result.into(),
113        Err(e) => e.to_compile_error().into(),
114    }
115}