rkyv/
lib.rs

1//! # rkyv
2//!
3//! rkyv (*archive*) is a zero-copy deserialization framework for Rust.
4//!
5//! It's similar to other zero-copy deserialization frameworks such as
6//! [Cap'n Proto](https://capnproto.org) and [FlatBuffers](https://google.github.io/flatbuffers).
7//! However, while the former have external schemas and heavily restricted data types, rkyv allows
8//! all serialized types to be defined in code and can serialize a wide variety of types that the
9//! others cannot. Additionally, rkyv is designed to have little to no overhead, and in most cases
10//! will perform exactly the same as native types.
11//!
12//! ## Design
13//!
14//! Like [serde](https://serde.rs), rkyv uses Rust's powerful trait system to serialize data without
15//! the need for reflection. Despite having a wide array of features, you also only pay for what you
16//! use. If your data checks out, the serialization process can be as simple as a `memcpy`! Like
17//! serde, this allows rkyv to perform at speeds similar to handwritten serializers.
18//!
19//! Unlike serde, rkyv produces data that is guaranteed deserialization free. If you wrote your data
20//! to disk, you can just `mmap` your file into memory, cast a pointer, and your data is ready to
21//! use. This makes it ideal for high-performance and IO-bound applications.
22//!
23//! Limited data mutation is supported through `Pin` APIs, and archived values can be truly
24//! deserialized with [`Deserialize`] if full mutation capabilities are needed.
25//!
26//! [The book](https://rkyv.org) has more details on the design and capabilities of rkyv.
27//!
28//! ## Type support
29//!
30//! rkyv has a hashmap implementation that is built for zero-copy deserialization, so you can
31//! serialize your hashmaps with abandon. The implementation performs perfect hashing with the
32//! compress, hash and displace algorithm to use as little memory as possible while still performing
33//! fast lookups.
34//!
35//! It also comes with a B+ tree implementation that is built for maximum performance by splitting
36//! data into easily-pageable 4KB segments. This makes it perfect for building immutable databases
37//! and structures for bulk data.
38//!
39//! rkyv also has support for contextual serialization, deserialization, and validation. It can
40//! properly serialize and deserialize shared pointers like `Rc` and `Arc`, and can be extended to
41//! support custom contextual types.
42//!
43//! Finally, rkyv makes it possible to serialize trait objects and use them *as trait objects*
44//! without deserialization. See the `archive_dyn` crate for more details.
45//!
46//! ## Tradeoffs
47//!
48//! While rkyv is a great format for final data, it lacks a full schema system and isn't well
49//! equipped for data migration and schema upgrades. If your use case requires these capabilities,
50//! you may need additional libraries the build these features on top of rkyv. You can use other
51//! serialization frameworks like serde with the same types as rkyv conflict-free.
52//!
53//! ## Features
54//!
55//! - `alloc`: Enables types that require the `alloc` crate. Enabled by default.
56//! - `arbitrary_enum_discriminant`: Enables the `arbitrary_enum_discriminant` feature for stable
57//!   multibyte enum discriminants using `archive_le` and `archive_be`. Requires nightly.
58//! - `archive_be`: Forces archives into a big-endian format. This guarantees cross-endian
59//!   compatibility optimized for big-endian architectures.
60//! - `archive_le`: Forces archives into a little-endian format. This guarantees cross-endian
61//!   compatibility optimized for little-endian architectures.
62//! - `copy`: Enables copy optimizations for packed copyable data types. Requires nightly.
63//! - `copy_unsafe`: Automatically opts all potentially copyable types into copy optimization. This
64//!   broadly improves performance but may cause uninitialized bytes to be copied to the output.
65//!   Requires nightly.
66//! - `size_16`: Archives integral `*size` types as 16-bit integers. This is intended to be used
67//!   only for small archives and may not handle large, more general data.
68//! - `size_32`: Archives integral `*size` types as 32-bit integers. Enabled by default.
69//! - `size_64`: Archives integral `*size` types as 64-bit integers. This is intended to be used
70//!   only for very large archives and may cause unnecessary data bloat.
71//! - `std`: Enables standard library support. Enabled by default.
72//! - `strict`: Guarantees that types will have the same representations across platforms and
73//!   compilations. This is already the case in practice, but this feature provides a guarantee
74//!   along with C type compatibility.
75//!
76//!   *Note*: Enabling `strict` will disable [`Archive`] implementations for tuples, as tuples
77//!   do not have a C type layout. Making a generic `Tuple<T1, T2>` and deriving [`Archive`] for it
78//!   should provide similar functionality.
79//! - `validation`: Enables validation support through `bytecheck`.
80//!
81//! ## Crate support
82//!
83//! Some common crates need to be supported by rkyv before an official integration has been made.
84//! Support is provided by rkyv for these crates, but in the future crates should depend on rkyv and
85//! provide their own implementations. The crates that already have support provided by rkyv should
86//! work toward integrating the implementations into themselves.
87//!
88//! Crates supported by rkyv:
89//!
90//! - [`indexmap`](https://docs.rs/indexmap)
91//! - [`rend`](https://docs.rs/rend) *Enabled automatically when using endian-specific archive
92//!   features.*
93//! - [`tinyvec`](https://docs.rs/tinyvec)
94//! - [`uuid`](https://docs.rs/uuid)
95//!
96//! Support for each of these crates can be enabled with a feature of the same name. Additionally,
97//! the following external crate features are available:
98//!
99//! - `alloc` with `tinyvec/alloc`: Supports types behind the `alloc` feature in `tinyvec`.
100//! - `std` with `uuid/std`: Enables the `std` feature in `uuid`.
101//!
102//! ## Examples
103//!
104//! - See [`Archive`] for examples of how to use rkyv through the derive macro and manual
105//!   implementation.
106//! - For more details on the derive macro and its capabilities, see
107//!   [`Archive`](macro@Archive).
108//! - Fully worked examples using rkyv are available in the
109//!   [`examples` directory](https://github.com/rkyv/rkyv/tree/master/examples) of the source repo.
110
111#![deny(
112    rustdoc::broken_intra_doc_links,
113    missing_docs,
114    rustdoc::missing_crate_level_docs
115)]
116#![cfg_attr(not(feature = "std"), no_std)]
117#![cfg_attr(
118    feature = "copy",
119    feature(auto_traits),
120    feature(min_specialization),
121    feature(negative_impls),
122    feature(rustc_attrs)
123)]
124#![doc(html_favicon_url = r#"
125    data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'
126    viewBox='0 0 26.458 26.458'%3E%3Cpath d='M0 0v26.458h26.458V0zm9.175 3.772l8.107 8.106
127    2.702-2.702 2.702 13.512-13.512-2.702 2.703-2.702-8.107-8.107z'/%3E%3C/svg%3E
128"#)]
129#![doc(html_logo_url = r#"
130    data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="100" height="100"
131    viewBox="0 0 26.458 26.458"%3E%3Cpath d="M0 0v26.458h26.458V0zm9.175 3.772l8.107 8.106
132    2.702-2.702 2.702 13.512-13.512-2.702 2.703-2.702-8.107-8.107z"/%3E%3C/svg%3E
133"#)]
134// Only use this feature if you know what you're doing!
135#![cfg_attr(feature = "copy", allow(internal_features))]
136
137#[cfg(all(feature = "alloc", not(feature = "std")))]
138extern crate alloc;
139#[cfg(feature = "std")]
140extern crate std;
141
142#[doc(hidden)]
143#[macro_use]
144pub mod macros;
145
146#[cfg(feature = "bitvec")]
147pub mod bitvec;
148pub mod boxed;
149pub mod collections;
150#[cfg(feature = "copy")]
151pub mod copy;
152pub mod de;
153// This is pretty unfortunate. CStr doesn't rely on the rest of std, but it's not in core.
154// If CStr ever gets moved into `core` then this module will no longer need cfg(feature = "std")
155#[cfg(feature = "std")]
156pub mod ffi;
157mod impls;
158pub mod net;
159pub mod niche;
160pub mod ops;
161pub mod option;
162pub mod rc;
163pub mod rel_ptr;
164pub mod result;
165pub mod ser;
166pub mod string;
167pub mod time;
168pub mod util;
169#[cfg(feature = "validation")]
170pub mod validation;
171pub mod vec;
172pub mod with;
173
174#[cfg(feature = "rend")]
175pub use rend;
176
177#[cfg(feature = "validation")]
178#[cfg_attr(doc_cfg, doc(cfg(feature = "validation")))]
179pub use bytecheck::{self, CheckBytes};
180use core::alloc::Layout;
181use ptr_meta::Pointee;
182pub use rkyv_derive::{Archive, Deserialize, Serialize};
183pub use util::*;
184#[cfg(feature = "validation")]
185#[cfg_attr(doc_cfg, doc(cfg(feature = "validation")))]
186pub use validation::{
187    check_archived_root_with_context, check_archived_value_with_context,
188    validators::{check_archived_root, check_archived_value, from_bytes},
189};
190
191/// A type that can produce an error.
192///
193/// This trait is always implemented by serializers and deserializers. Its purpose is to provide an
194/// error type without restricting what other capabilities the type must provide.
195///
196/// When writing implementations for [`Serialize`] and [`Deserialize`], it's best practice to bound
197/// the serializer or deserializer by `Fallible` and then require that the serialized types support
198/// it (i.e. `S: Fallible, MyType: Serialize<S>`).
199pub trait Fallible {
200    /// The error produced by any failing methods.
201    type Error: 'static;
202}
203
204/// A fallible type that cannot produce errors.
205///
206/// This type can be used to serialize and deserialize types that cannot fail to serialize or
207/// deserialize.
208#[derive(Debug)]
209pub struct Infallible;
210
211impl Fallible for Infallible {
212    type Error = core::convert::Infallible;
213}
214
215impl Default for Infallible {
216    fn default() -> Self {
217        Infallible
218    }
219}
220
221/// A type that can be used without deserializing.
222///
223/// `Archive` is one of three basic traits used to work with zero-copy data and controls the layout
224/// of the data in its archived zero-copy representation. The [`Serialize`] trait helps transform
225/// types into that representation, and the [`Deserialize`] trait helps transform types back out.
226///
227/// Types that implement `Archive` must have a well-defined archived size. Unsized types can be
228/// supported using the [`ArchiveUnsized`] trait, along with [`SerializeUnsized`] and
229/// [`DeserializeUnsized`].
230///
231/// Archiving is done depth-first, writing any data owned by a type before writing the data for the
232/// type itself. The type must be able to create the archived type from only its own data and its
233/// resolver.
234///
235/// Archived data is always treated as if it is tree-shaped, with the root owning its direct
236/// descendents and so on. Data that is not tree-shaped can be supported using special serializer
237/// and deserializer bounds (see [`ArchivedRc`](crate::rc::ArchivedRc) for example). In a buffer of
238/// serialized data, objects are laid out in *reverse order*. This means that the root object is
239/// located near the end of the buffer and leaf objects are located near the beginning.
240///
241/// # Examples
242///
243/// Most of the time, `#[derive(Archive)]` will create an acceptable implementation. You can use the
244/// `#[archive(...)]` and `#[archive_attr(...)]` attributes to control how the implementation is
245/// generated. See the [`Archive`](macro@Archive) derive macro for more details.
246///
247/// ```
248/// use rkyv::{Archive, Deserialize, Serialize};
249///
250/// #[derive(Archive, Deserialize, Serialize, Debug, PartialEq)]
251/// // This will generate a PartialEq impl between our unarchived and archived types
252/// #[archive(compare(PartialEq))]
253/// // We can pass attributes through to generated types with archive_attr
254/// #[archive_attr(derive(Debug))]
255/// struct Test {
256///     int: u8,
257///     string: String,
258///     option: Option<Vec<i32>>,
259/// }
260///
261/// let value = Test {
262///     int: 42,
263///     string: "hello world".to_string(),
264///     option: Some(vec![1, 2, 3, 4]),
265/// };
266///
267/// // Serializing is as easy as a single function call
268/// let bytes = rkyv::to_bytes::<_, 256>(&value).unwrap();
269///
270/// // Or you can customize your serialization for better performance
271/// // and compatibility with #![no_std] environments
272/// use rkyv::ser::{Serializer, serializers::AllocSerializer};
273///
274/// let mut serializer = AllocSerializer::<0>::default();
275/// serializer.serialize_value(&value).unwrap();
276/// let bytes = serializer.into_serializer().into_inner();
277///
278/// // You can use the safe API with the validation feature turned on,
279/// // or you can use the unsafe API (shown here) for maximum performance
280/// let archived = unsafe { rkyv::archived_root::<Test>(&bytes[..]) };
281/// assert_eq!(archived, &value);
282///
283/// // And you can always deserialize back to the original type
284/// let deserialized: Test = archived.deserialize(&mut rkyv::Infallible).unwrap();
285/// assert_eq!(deserialized, value);
286/// ```
287///
288/// _Note: the safe API requires the `validation` feature._
289///
290/// Many of the core and standard library types already have `Archive` implementations available,
291/// but you may need to implement `Archive` for your own types in some cases the derive macro cannot
292/// handle.
293///
294/// In this example, we add our own wrapper that serializes a `&'static str` as if it's owned.
295/// Normally you can lean on the archived version of `String` to do most of the work, or use the
296/// [`Inline`](crate::with::Inline) to do exactly this. This example does everything to demonstrate
297/// how to implement `Archive` for your own types.
298///
299/// ```
300/// use core::{slice, str};
301/// use rkyv::{
302///     archived_root,
303///     ser::{Serializer, serializers::AlignedSerializer},
304///     out_field,
305///     AlignedVec,
306///     Archive,
307///     Archived,
308///     ArchiveUnsized,
309///     MetadataResolver,
310///     RelPtr,
311///     Serialize,
312///     SerializeUnsized,
313/// };
314///
315/// struct OwnedStr {
316///     inner: &'static str,
317/// }
318///
319/// struct ArchivedOwnedStr {
320///     // This will be a relative pointer to our string
321///     ptr: RelPtr<str>,
322/// }
323///
324/// impl ArchivedOwnedStr {
325///     // This will help us get the bytes of our type as a str again.
326///     fn as_str(&self) -> &str {
327///         unsafe {
328///             // The as_ptr() function of RelPtr will get a pointer the str
329///             &*self.ptr.as_ptr()
330///         }
331///     }
332/// }
333///
334/// struct OwnedStrResolver {
335///     // This will be the position that the bytes of our string are stored at.
336///     // We'll use this to resolve the relative pointer of our
337///     // ArchivedOwnedStr.
338///     pos: usize,
339///     // The archived metadata for our str may also need a resolver.
340///     metadata_resolver: MetadataResolver<str>,
341/// }
342///
343/// // The Archive implementation defines the archived version of our type and
344/// // determines how to turn the resolver into the archived form. The Serialize
345/// // implementations determine how to make a resolver from the original value.
346/// impl Archive for OwnedStr {
347///     type Archived = ArchivedOwnedStr;
348///     // This is the resolver we can create our Archived version from.
349///     type Resolver = OwnedStrResolver;
350///
351///     // The resolve function consumes the resolver and produces the archived
352///     // value at the given position.
353///     unsafe fn resolve(
354///         &self,
355///         pos: usize,
356///         resolver: Self::Resolver,
357///         out: *mut Self::Archived,
358///     ) {
359///         // We have to be careful to add the offset of the ptr field,
360///         // otherwise we'll be using the position of the ArchivedOwnedStr
361///         // instead of the position of the relative pointer.
362///         let (fp, fo) = out_field!(out.ptr);
363///         self.inner.resolve_unsized(
364///             pos + fp,
365///             resolver.pos,
366///             resolver.metadata_resolver,
367///             fo,
368///         );
369///     }
370/// }
371///
372/// // We restrict our serializer types with Serializer because we need its
373/// // capabilities to archive our type. For other types, we might need more or
374/// // less restrictive bounds on the type of S.
375/// impl<S: Serializer + ?Sized> Serialize<S> for OwnedStr {
376///     fn serialize(
377///         &self,
378///         serializer: &mut S
379///     ) -> Result<Self::Resolver, S::Error> {
380///         // This is where we want to write the bytes of our string and return
381///         // a resolver that knows where those bytes were written.
382///         // We also need to serialize the metadata for our str.
383///         Ok(OwnedStrResolver {
384///             pos: self.inner.serialize_unsized(serializer)?,
385///             metadata_resolver: self.inner.serialize_metadata(serializer)?
386///         })
387///     }
388/// }
389///
390/// let mut serializer = AlignedSerializer::new(AlignedVec::new());
391/// const STR_VAL: &'static str = "I'm in an OwnedStr!";
392/// let value = OwnedStr { inner: STR_VAL };
393/// // It works!
394/// serializer.serialize_value(&value).expect("failed to archive test");
395/// let buf = serializer.into_inner();
396/// let archived = unsafe { archived_root::<OwnedStr>(buf.as_ref()) };
397/// // Let's make sure our data got written correctly
398/// assert_eq!(archived.as_str(), STR_VAL);
399/// ```
400pub trait Archive {
401    /// The archived representation of this type.
402    ///
403    /// In this form, the data can be used with zero-copy deserialization.
404    type Archived;
405
406    /// The resolver for this type. It must contain all the additional information from serializing
407    /// needed to make the archived type from the normal type.
408    type Resolver;
409
410    /// Creates the archived version of this value at the given position and writes it to the given
411    /// output.
412    ///
413    /// The output should be initialized field-by-field rather than by writing a whole struct.
414    /// Performing a typed copy will mark all of the padding bytes as uninitialized, but they must
415    /// remain set to the value they currently have. This prevents leaking uninitialized memory to
416    /// the final archive.
417    ///
418    /// # Safety
419    ///
420    /// - `pos` must be the position of `out` within the archive
421    /// - `resolver` must be the result of serializing this object
422    unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived);
423}
424
425/// Converts a type to its archived form.
426///
427/// Objects perform any supportive serialization during [`serialize`](Serialize::serialize). For
428/// types that reference nonlocal (pointed-to) data, this is when that data must be serialized to
429/// the output. These types will need to bound `S` to implement [`Serializer`](ser::Serializer) and
430/// any other required traits (e.g. [`SharedSerializeRegistry`](ser::SharedSerializeRegistry)). They
431/// should then serialize their dependencies during `serialize`.
432///
433/// See [`Archive`] for examples of implementing `Serialize`.
434pub trait Serialize<S: Fallible + ?Sized>: Archive {
435    /// Writes the dependencies for the object and returns a resolver that can create the archived
436    /// type.
437    fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error>;
438}
439
440/// Converts a type back from its archived form.
441///
442/// Some types may require specific deserializer capabilities, such as `Rc` and `Arc`. In these
443/// cases, the deserializer type `D` should be bound so that it implements traits that provide those
444/// capabilities (e.g. [`SharedDeserializeRegistry`](de::SharedDeserializeRegistry)).
445///
446/// This can be derived with [`Deserialize`](macro@Deserialize).
447pub trait Deserialize<T, D: Fallible + ?Sized> {
448    /// Deserializes using the given deserializer
449    fn deserialize(&self, deserializer: &mut D) -> Result<T, D::Error>;
450}
451
452/// A counterpart of [`Archive`] that's suitable for unsized types.
453///
454/// Unlike `Archive`, types that implement `ArchiveUnsized` must be serialized separately from their
455/// owning object. For example, whereas an `i32` might be laid out as part of a larger struct, a
456/// `Box<i32>` would serialize the `i32` somewhere in the archive and the `Box` would point to it as
457/// part of the larger struct. Because of this, the equivalent [`Resolver`](Archive::Resolver) type
458/// for `ArchiveUnsized` is always a `usize` representing the position of the serialized value.
459///
460/// `ArchiveUnsized` is automatically implemented for all types that implement [`Archive`]. Nothing
461/// special needs to be done to use them with types like `Box`, `Rc`, and `Arc`. It is also already
462/// implemented for slices and string slices, and the `rkyv_dyn` crate can be used to archive trait
463/// objects. Other unsized types must manually implement `ArchiveUnsized`.
464///
465/// # Examples
466///
467/// This example shows how to manually implement `ArchiveUnsized` for an unsized type. Special care
468/// must be taken to ensure that the types are laid out correctly.
469///
470/// ```
471/// use core::{mem::transmute, ops::{Deref, DerefMut}};
472/// use ptr_meta::Pointee;
473/// use rkyv::{
474///     from_archived,
475///     to_archived,
476///     archived_unsized_value,
477///     ser::{serializers::AlignedSerializer, Serializer},
478///     AlignedVec,
479///     Archive,
480///     Archived,
481///     ArchivedMetadata,
482///     ArchivePointee,
483///     ArchiveUnsized,
484///     FixedUsize,
485///     RelPtr,
486///     Serialize,
487///     SerializeUnsized,
488/// };
489///
490/// // We're going to be dealing mostly with blocks that have a trailing slice
491/// pub struct Block<H, T: ?Sized> {
492///     head: H,
493///     tail: T,
494/// }
495///
496/// impl<H, T> Pointee for Block<H, [T]> {
497///     type Metadata = usize;
498/// }
499///
500/// // For blocks with trailing slices, we need to store the length of the slice
501/// // in the metadata.
502/// pub struct BlockSliceMetadata {
503///     len: Archived<usize>,
504/// }
505///
506/// // ArchivePointee is automatically derived for sized types because pointers
507/// // to sized types don't need to store any extra information. Because we're
508/// // making an unsized block, we need to define what metadata gets stored with
509/// // our data pointer.
510/// impl<H, T> ArchivePointee for Block<H, [T]> {
511///     // This is the extra data that needs to get stored for blocks with
512///     // trailing slices
513///     type ArchivedMetadata = BlockSliceMetadata;
514///
515///     // We need to be able to turn our archived metadata into regular
516///     // metadata for our type
517///     fn pointer_metadata(
518///         archived: &Self::ArchivedMetadata
519///     ) -> <Self as Pointee>::Metadata {
520///         from_archived!(archived.len) as usize
521///     }
522/// }
523///
524/// // We're implementing ArchiveUnsized for just Block<H, [T]>. We can still
525/// // implement Archive for blocks with sized tails and they won't conflict.
526/// impl<H: Archive, T: Archive> ArchiveUnsized for Block<H, [T]> {
527///     // We'll reuse our block type as our archived type.
528///     type Archived = Block<Archived<H>, [Archived<T>]>;
529///
530///     // This is where we'd put any resolve data for our metadata.
531///     // Most of the time, this can just be () because most metadata is Copy,
532///     // but the option is there if you need it.
533///     type MetadataResolver = ();
534///
535///     // Here's where we make the metadata for our pointer.
536///     // This also gets the position and resolver for the metadata, but we
537///     // don't need it in this case.
538///     unsafe fn resolve_metadata(
539///         &self,
540///         _: usize,
541///         _: Self::MetadataResolver,
542///         out: *mut ArchivedMetadata<Self>,
543///     ) {
544///         unsafe {
545///             out.write(BlockSliceMetadata {
546///                 len: to_archived!(self.tail.len() as FixedUsize),
547///             });
548///         }
549///     }
550/// }
551///
552/// // The bounds we use on our serializer type indicate that we need basic
553/// // serializer capabilities, and then whatever capabilities our head and tail
554/// // types need to serialize themselves.
555/// impl<
556///     H: Serialize<S>,
557///     T: Serialize<S>,
558///     S: Serializer + ?Sized
559/// > SerializeUnsized<S> for Block<H, [T]> {
560///     // This is where we construct our unsized type in the serializer
561///     fn serialize_unsized(
562///         &self,
563///         serializer: &mut S
564///     ) -> Result<usize, S::Error> {
565///         // First, we archive the head and all the tails. This will make sure
566///         // that when we finally build our block, we don't accidentally mess
567///         // up the structure with serialized dependencies.
568///         let head_resolver = self.head.serialize(serializer)?;
569///         let mut resolvers = Vec::new();
570///         for tail in self.tail.iter() {
571///             resolvers.push(tail.serialize(serializer)?);
572///         }
573///         // Now we align our serializer for our archived type and write it.
574///         // We can't align for unsized types so we treat the trailing slice
575///         // like an array of 0 length for now.
576///         serializer.align_for::<Block<Archived<H>, [Archived<T>; 0]>>()?;
577///         let result = unsafe {
578///             serializer.resolve_aligned(&self.head, head_resolver)?
579///         };
580///         serializer.align_for::<Archived<T>>()?;
581///         for (item, resolver) in self.tail.iter().zip(resolvers.drain(..)) {
582///             unsafe {
583///                 serializer.resolve_aligned(item, resolver)?;
584///             }
585///         }
586///         Ok(result)
587///     }
588///
589///     // This is where we serialize the metadata for our type. In this case,
590///     // we do all the work in resolve and don't need to do anything here.
591///     fn serialize_metadata(
592///         &self,
593///         serializer: &mut S
594///     ) -> Result<Self::MetadataResolver, S::Error> {
595///         Ok(())
596///     }
597/// }
598///
599/// let value = Block {
600///     head: "Numbers 1-4".to_string(),
601///     tail: [1, 2, 3, 4],
602/// };
603/// // We have a Block<String, [i32; 4]> but we want to it to be a
604/// // Block<String, [i32]>, so we need to do more pointer transmutation
605/// let ptr = (&value as *const Block<String, [i32; 4]>).cast::<()>();
606/// let unsized_value = unsafe {
607///     &*transmute::<(*const (), usize), *const Block<String, [i32]>>((ptr, 4))
608/// };
609///
610/// let mut serializer = AlignedSerializer::new(AlignedVec::new());
611/// let pos = serializer.serialize_unsized_value(unsized_value)
612///     .expect("failed to archive block");
613/// let buf = serializer.into_inner();
614///
615/// let archived_ref = unsafe {
616///     archived_unsized_value::<Block<String, [i32]>>(buf.as_slice(), pos)
617/// };
618/// assert_eq!(archived_ref.head, "Numbers 1-4");
619/// assert_eq!(archived_ref.tail.len(), 4);
620/// assert_eq!(archived_ref.tail, [1, 2, 3, 4]);
621/// ```
622pub trait ArchiveUnsized: Pointee {
623    /// The archived counterpart of this type. Unlike `Archive`, it may be unsized.
624    ///
625    /// This type must implement [`ArchivePointee`], a trait that helps make valid pointers using
626    /// archived pointer metadata.
627    type Archived: ArchivePointee + ?Sized;
628
629    /// The resolver for the metadata of this type.
630    ///
631    /// Because the pointer metadata must be archived with the relative pointer and not with the
632    /// structure itself, its resolver must be passed back to the structure holding the pointer.
633    type MetadataResolver;
634
635    /// Creates the archived version of the metadata for this value at the given position and writes
636    /// it to the given output.
637    ///
638    /// The output should be initialized field-by-field rather than by writing a whole struct.
639    /// Performing a typed copy will mark all of the padding bytes as uninitialized, but they must
640    /// remain set to the value they currently have. This prevents leaking uninitialized memory to
641    /// the final archive.
642    ///
643    /// # Safety
644    ///
645    /// - `pos` must be the position of `out` within the archive
646    /// - `resolver` must be the result of serializing this object's metadata
647    unsafe fn resolve_metadata(
648        &self,
649        pos: usize,
650        resolver: Self::MetadataResolver,
651        out: *mut ArchivedMetadata<Self>,
652    );
653
654    /// Resolves a relative pointer to this value with the given `from` and `to` and writes it to
655    /// the given output.
656    ///
657    /// The output should be initialized field-by-field rather than by writing a whole struct.
658    /// Performing a typed copy will mark all of the padding bytes as uninitialized, but they must
659    /// remain set to the value they currently have. This prevents leaking uninitialized memory to
660    /// the final archive.
661    ///
662    /// # Safety
663    ///
664    /// - `from` must be the position of `out` within the archive
665    /// - `to` must be the position of some `Self::Archived` within the archive
666    /// - `resolver` must be the result of serializing this object
667    #[inline]
668    unsafe fn resolve_unsized(
669        &self,
670        from: usize,
671        to: usize,
672        resolver: Self::MetadataResolver,
673        out: *mut RelPtr<Self::Archived>,
674    ) {
675        RelPtr::resolve_emplace(from, to, self, resolver, out);
676    }
677}
678
679/// An archived type with associated metadata for its relative pointer.
680///
681/// This is mostly used in the context of smart pointers and unsized types, and is implemented for
682/// all sized types by default.
683pub trait ArchivePointee: Pointee {
684    /// The archived version of the pointer metadata for this type.
685    type ArchivedMetadata;
686
687    /// Converts some archived metadata to the pointer metadata for itself.
688    fn pointer_metadata(archived: &Self::ArchivedMetadata) -> <Self as Pointee>::Metadata;
689}
690
691/// A counterpart of [`Serialize`] that's suitable for unsized types.
692///
693/// See [`ArchiveUnsized`] for examples of implementing `SerializeUnsized`.
694pub trait SerializeUnsized<S: Fallible + ?Sized>: ArchiveUnsized {
695    /// Writes the object and returns the position of the archived type.
696    fn serialize_unsized(&self, serializer: &mut S) -> Result<usize, S::Error>;
697
698    /// Serializes the metadata for the given type.
699    fn serialize_metadata(&self, serializer: &mut S) -> Result<Self::MetadataResolver, S::Error>;
700}
701
702/// A counterpart of [`Deserialize`] that's suitable for unsized types.
703pub trait DeserializeUnsized<T: Pointee + ?Sized, D: Fallible + ?Sized>: ArchivePointee {
704    /// Deserializes a reference to the given value.
705    ///
706    /// # Safety
707    ///
708    /// `out` must point to memory with the layout returned by `deserialized_layout`.
709    unsafe fn deserialize_unsized(
710        &self,
711        deserializer: &mut D,
712        alloc: impl FnMut(Layout) -> *mut u8,
713    ) -> Result<*mut (), D::Error>;
714
715    /// Deserializes the metadata for the given type.
716    fn deserialize_metadata(&self, deserializer: &mut D) -> Result<T::Metadata, D::Error>;
717}
718
719/// The native type that `usize` is converted to for archiving.
720///
721/// This will be `u16`, `u32`, or `u64` when the `size_16`, `size_32`, or `size_64` features are
722/// enabled, respectively.
723pub type FixedUsize = pick_size_type!(u16, u32, u64);
724/// The native type that `isize` is converted to for archiving.
725///
726/// This will be `i16`, `i32`, or `i64` when the `size_16`, `size_32`, or `size_64` features are
727/// enabled, respectively.
728pub type FixedIsize = pick_size_type!(i16, i32, i64);
729
730/// The default raw relative pointer.
731///
732/// This will use an archived [`FixedIsize`] to hold the offset.
733pub type RawRelPtr = rel_ptr::RawRelPtr<Archived<isize>>;
734/// The default relative pointer.
735///
736/// This will use an archived [`FixedIsize`] to hold the offset.
737pub type RelPtr<T> = rel_ptr::RelPtr<T, Archived<isize>>;
738
739/// Alias for the archived version of some [`Archive`] type.
740///
741/// This can be useful for reducing the lengths of type definitions.
742pub type Archived<T> = <T as Archive>::Archived;
743/// Alias for the resolver for some [`Archive`] type.
744///
745/// This can be useful for reducing the lengths of type definitions.
746pub type Resolver<T> = <T as Archive>::Resolver;
747/// Alias for the archived metadata for some [`ArchiveUnsized`] type.
748///
749/// This can be useful for reducing the lengths of type definitions.
750pub type ArchivedMetadata<T> =
751    <<T as ArchiveUnsized>::Archived as ArchivePointee>::ArchivedMetadata;
752/// Alias for the metadata resolver for some [`ArchiveUnsized`] type.
753///
754/// This can be useful for reducing the lengths of type definitions.
755pub type MetadataResolver<T> = <T as ArchiveUnsized>::MetadataResolver;