1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//! Procedural macros for `rkyv`.

#![deny(
    rustdoc::broken_intra_doc_links,
    missing_docs,
    rustdoc::missing_crate_level_docs
)]

mod archive;
mod attributes;
mod deserialize;
mod portable;
mod repr;
mod serde;
mod serialize;
mod util;

extern crate proc_macro;

use syn::{parse_macro_input, DeriveInput};

/// Derives `Portable` for the labeled type.
#[proc_macro_derive(Portable, attributes(rkyv))]
pub fn derive_portable(
    input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    let mut derive_input = parse_macro_input!(input as DeriveInput);
    serde::receiver::replace_receiver(&mut derive_input);

    match portable::derive(derive_input) {
        Ok(result) => result.into(),
        Err(e) => e.to_compile_error().into(),
    }
}

/// Derives `Archive` for the labeled type.
///
/// # Attributes
///
/// Additional arguments can be specified using `#[rkyv(..)]`, which accepts
/// the following arguments:
///
/// ## Types and fields
///
/// - `attr(..)`: Passes along attributes to the generated archived type.
///
/// ## Types only
///
/// - `derive(..)`: Adds the derives passed as arguments to the generated type.
///   This is equivalent to `#[rkyv(attr(derive(..)))]`.
/// - `crate = ..`: Chooses an alternative crate path to import rkyv from.
/// - `compare(..)`: Implements common comparison operators between the original
///   and archived types. Supported comparisons are `PartialEq` and `PartialOrd`
///   (i.e. `#[rkyv(compare(PartialEq, PartialOrd))]`).
/// - `{archive, serialize, deserialize}_bounds(..)`: Adds additional bounds to
///   trait implementations. This can be useful for recursive types, where
///   bounds may need to be omitted to prevent recursive trait impls.
/// - `bytecheck(..)`: Passed through to the underlying `CheckBytes` derive for
///   the archived type.
/// - `as = ..`: Uses the given archived type instead of generating a new one.
///   This is useful for types which are `Portable` and/or generic over their
///   parameters.
/// - `archived = ..`: Changes the name of the generated archived type. By
///   default, archived types are named "Archived" + `the name of the type`.
/// - `resolver = ..`: Changes the name of the generated resolver type. By
///   default, resolver types are named `the name of the type` + "Resolver".
/// - `remote = ..`: Generate a remote derive for the annotated type instead of
///   a regular derive.
///
/// ## Fields only
///
/// - `with = ..`: Applies the given wrapper type to the field.
/// - `omit_bounds`: Omits trait bounds for the annotated field in the generated
///   impl.
///
/// # Recursive types
///
/// This derive macro automatically adds a type bound `field: Archive` for each
/// field type. This can cause an overflow while evaluating trait bounds if the
/// structure eventually references its own type, as the implementation of
/// `Archive` for a struct depends on each field type implementing it
/// as well. Adding the attribute `#[rkyv(omit_bounds)]` to a field will
/// suppress this trait bound and allow recursive structures. This may be too
/// coarse for some types, in which case additional type bounds may be required
/// with `{archive, serialize, deserialize}_bounds(..)`.
///
/// # Wrappers
///
/// Wrappers transparently customize archived types by providing different
/// implementations of core traits. For example, references cannot be archived,
/// but the `Inline` wrapper serializes a reference as if it were a field of the
/// struct. Wrappers can be applied to fields using the `#[rkyv_with = ..]`
/// attribute.
#[proc_macro_derive(Archive, attributes(rkyv))]
pub fn derive_archive(
    input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    let mut derive_input = parse_macro_input!(input as DeriveInput);
    serde::receiver::replace_receiver(&mut derive_input);

    match archive::derive(&mut derive_input) {
        Ok(result) => result.into(),
        Err(e) => e.to_compile_error().into(),
    }
}

/// Derives `Serialize` for the labeled type.
///
/// This macro also supports the `#[rkyv]` attribute. See [`Archive`] for more
/// information.
#[proc_macro_derive(Serialize, attributes(rkyv))]
pub fn derive_serialize(
    input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    let mut derive_input = parse_macro_input!(input as DeriveInput);
    serde::receiver::replace_receiver(&mut derive_input);

    match serialize::derive(derive_input) {
        Ok(result) => result.into(),
        Err(e) => e.to_compile_error().into(),
    }
}

/// Derives `Deserialize` for the labeled type.
///
/// This macro also supports the `#[rkyv]` attribute. See [`Archive`] for more
/// information.
#[proc_macro_derive(Deserialize, attributes(rkyv))]
pub fn derive_deserialize(
    input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    let mut derive_input = parse_macro_input!(input as DeriveInput);
    serde::receiver::replace_receiver(&mut derive_input);

    match deserialize::derive(derive_input) {
        Ok(result) => result.into(),
        Err(e) => e.to_compile_error().into(),
    }
}