Skip to main content

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 portable;
13mod repr;
14mod serde;
15mod serialize;
16mod util;
17
18extern crate proc_macro;
19
20use syn::{parse_macro_input, DeriveInput};
21
22/// Derives `Portable` for the labeled type.
23#[proc_macro_derive(Portable, attributes(rkyv))]
24pub fn derive_portable(
25    input: proc_macro::TokenStream,
26) -> proc_macro::TokenStream {
27    let mut derive_input = parse_macro_input!(input as DeriveInput);
28    serde::receiver::replace_receiver(&mut derive_input);
29
30    match portable::derive(derive_input) {
31        Ok(result) => result.into(),
32        Err(e) => e.to_compile_error().into(),
33    }
34}
35
36/// Derives `Archive` for the labeled type.
37///
38/// # Attributes
39///
40/// Additional arguments can be specified using `#[rkyv(..)]`, which accepts
41/// the following arguments:
42///
43/// ## Types and fields
44///
45/// - `attr(..)`: Passes along attributes to the generated archived type.
46///
47/// ## Types only
48///
49/// - `derive(..)`: Adds the derives passed as arguments to the generated type.
50///   This is equivalent to `#[rkyv(attr(derive(..)))]`.
51/// - `crate = ..`: Chooses an alternative crate path to import rkyv from.
52/// - `compare(..)`: Implements common comparison operators between the original
53///   and archived types. Supported comparisons are `PartialEq` and `PartialOrd`
54///   (i.e. `#[rkyv(compare(PartialEq, PartialOrd))]`).
55/// - `{archive, serialize, deserialize}_bounds(..)`: Adds additional bounds to
56///   trait implementations. This can be useful for recursive types, where
57///   bounds may need to be omitted to prevent recursive trait impls.
58/// - `bytecheck(..)`: Passed through to the underlying `CheckBytes` derive for
59///   the archived type.
60/// - `as = ..`: Uses the given archived type instead of generating a new one.
61///   This is useful for types which are `Portable` and/or generic over their
62///   parameters.
63/// - `archived = ..`: Changes the name of the generated archived type. By
64///   default, archived types are named "Archived" + `the name of the type`.
65/// - `resolver = ..`: Changes the name of the generated resolver type. By
66///   default, resolver types are named `the name of the type` + "Resolver".
67/// - `remote = ..`: Generate a remote derive for the annotated type instead of
68///   a regular derive.
69///
70/// ## Fields only
71///
72/// - `with = ..`: Applies the given wrapper type to the field.
73/// - `omit_bounds`: Omits trait bounds for the annotated field in the generated
74///   impl.
75/// - `niche` or `niche = ..`: Makes the outer type nichable through the
76///   annotated field using the default niche or a specified one.
77///
78/// # Recursive types
79///
80/// This derive macro automatically adds a type bound `field: Archive` for each
81/// field type. This can cause an overflow while evaluating trait bounds if the
82/// structure eventually references its own type, as the implementation of
83/// `Archive` for a struct depends on each field type implementing it
84/// as well. Adding the attribute `#[rkyv(omit_bounds)]` to a field will
85/// suppress this trait bound and allow recursive structures. This may be too
86/// coarse for some types, in which case additional type bounds may be required
87/// with `{archive, serialize, deserialize}_bounds(..)`.
88///
89/// # Wrappers
90///
91/// Wrappers transparently customize archived types by providing different
92/// implementations of core traits. For example, references cannot be archived,
93/// but the `Inline` wrapper serializes a reference as if it were a field of the
94/// struct. Wrappers can be applied to fields using the `#[rkyv_with = ..]`
95/// attribute.
96#[proc_macro_derive(Archive, attributes(rkyv))]
97pub fn derive_archive(
98    input: proc_macro::TokenStream,
99) -> proc_macro::TokenStream {
100    let mut derive_input = parse_macro_input!(input as DeriveInput);
101    serde::receiver::replace_receiver(&mut derive_input);
102
103    match archive::derive(&mut derive_input) {
104        Ok(result) => result.into(),
105        Err(e) => e.to_compile_error().into(),
106    }
107}
108
109/// Derives `Serialize` for the labeled type.
110///
111/// This macro also supports the `#[rkyv]` attribute. See [`Archive`] for more
112/// information.
113#[proc_macro_derive(Serialize, attributes(rkyv))]
114pub fn derive_serialize(
115    input: proc_macro::TokenStream,
116) -> proc_macro::TokenStream {
117    let mut derive_input = parse_macro_input!(input as DeriveInput);
118    serde::receiver::replace_receiver(&mut derive_input);
119
120    match serialize::derive(derive_input) {
121        Ok(result) => result.into(),
122        Err(e) => e.to_compile_error().into(),
123    }
124}
125
126/// Derives `Deserialize` for the labeled type.
127///
128/// This macro also supports the `#[rkyv]` attribute. See [`Archive`] for more
129/// information.
130#[proc_macro_derive(Deserialize, attributes(rkyv))]
131pub fn derive_deserialize(
132    input: proc_macro::TokenStream,
133) -> proc_macro::TokenStream {
134    let mut derive_input = parse_macro_input!(input as DeriveInput);
135    serde::receiver::replace_receiver(&mut derive_input);
136
137    match deserialize::derive(derive_input) {
138        Ok(result) => result.into(),
139        Err(e) => e.to_compile_error().into(),
140    }
141}