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
//! Procedural macros for `rkyv`.
#![deny(
rustdoc::broken_intra_doc_links,
missing_docs,
rustdoc::missing_crate_level_docs
)]
mod archive;
mod attributes;
mod deserialize;
mod repr;
mod serde;
mod serialize;
mod util;
mod with;
extern crate proc_macro;
use syn::{parse_macro_input, DeriveInput};
/// Derives `Archive` for the labeled type.
///
/// # Attributes
///
/// Additional arguments can be specified using the `#[archive(...)]` and `#[archive_attr(...)]`
/// attributes.
///
/// `#[archive(...)]` takes the following arguments:
///
/// - `archived = "..."`: Changes the name of the generated archived type to the given value. By
/// default, archived types are named "Archived" + `the name of the type`.
/// - `resolver = "..."`: Changes the name of the generated resolver type to the given value. By
/// default, resolver types are named `the name of the type` + "Resolver".
/// - `repr(...)`: *Deprecated, use `#[archive_attr(repr(...))]` instead.* Sets the representation
/// for the archived type to the given representation. Available representation options may vary
/// depending on features and type layout.
/// - `compare(...)`: Implements common comparison operators between the original and archived
/// types. Supported comparisons are `PartialEq` and `PartialOrd` (i.e.
/// `#[archive(compare(PartialEq, PartialOrd))]`).
/// - `bound(...)`: Adds additional bounds to trait implementations. This can be especially useful
/// when dealing with recursive structures, where bounds may need to be omitted to prevent
/// recursive type definitions. Use `archive = "..."` to specify `Archive` bounds,
/// `serialize = "..."` to specify `Serialize` bounds, and `deserialize = "..."` to specify
/// `Deserialize` bounds.
/// - `copy_safe`: States that the archived type is tightly packed with no padding bytes. This
/// qualifies it for copy optimizations. (requires nightly)
/// - `as = "..."`: Instead of generating a separate archived type, this type will archive as the
/// named type. This is useful for types which are generic over their parameters.
/// - `crate = "..."`: Chooses an alternative crate path to import rkyv from.
///
/// `#[archive_attr(...)]` adds the attributes passed as arguments as attributes to the generated
/// type. This is commonly used with attributes like `derive(...)` to derive trait implementations
/// for the archived type.
///
/// # 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 `#[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 `bound(...)`.
///
/// # 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
/// `#[with(...)]` attribute. Mutliple wrappers can be used, and they are applied in reverse order
/// (i.e. `#[with(A, B, C)]` will archive `MyType` as `With<With<With<MyType, C>, B, A>`).
#[proc_macro_derive(Archive, attributes(archive, archive_attr, omit_bounds, with))]
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(derive_input) {
Ok(result) => result.into(),
Err(e) => e.to_compile_error().into(),
}
}
/// Derives `Serialize` for the labeled type.
///
/// This macro also supports the `#[archive]`, `#[omit_bounds]`, and `#[with]` attributes. See
/// [`Archive`] for more information.
#[proc_macro_derive(Serialize, attributes(archive, omit_bounds, with))]
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 `#[archive]`, `#[omit_bounds]`, and `#[with]` attributes. See
/// [`Archive`] for more information.
#[proc_macro_derive(Deserialize, attributes(archive, omit_bounds, with))]
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(),
}
}