Coverage Report

Created: 2024-10-16 07:58

/rust/registry/src/index.crates.io-6f17d22bba15001f/rkyv-0.7.44/src/lib.rs
Line
Count
Source (jump to first uncovered line)
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")))]
138
extern crate alloc;
139
#[cfg(feature = "std")]
140
extern crate std;
141
142
#[doc(hidden)]
143
#[macro_use]
144
pub mod macros;
145
146
#[cfg(feature = "bitvec")]
147
pub mod bitvec;
148
pub mod boxed;
149
pub mod collections;
150
#[cfg(feature = "copy")]
151
pub mod copy;
152
pub 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")]
156
pub mod ffi;
157
mod impls;
158
pub mod net;
159
pub mod niche;
160
pub mod ops;
161
pub mod option;
162
pub mod rc;
163
pub mod rel_ptr;
164
pub mod result;
165
pub mod ser;
166
pub mod string;
167
pub mod time;
168
pub mod util;
169
#[cfg(feature = "validation")]
170
pub mod validation;
171
pub mod vec;
172
pub mod with;
173
174
#[cfg(feature = "rend")]
175
pub use rend;
176
177
#[cfg(feature = "validation")]
178
#[cfg_attr(doc_cfg, doc(cfg(feature = "validation")))]
179
pub use bytecheck::{self, CheckBytes};
180
use core::alloc::Layout;
181
use ptr_meta::Pointee;
182
pub use rkyv_derive::{Archive, Deserialize, Serialize};
183
pub use util::*;
184
#[cfg(feature = "validation")]
185
#[cfg_attr(doc_cfg, doc(cfg(feature = "validation")))]
186
pub 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>`).
199
pub 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)]
209
pub struct Infallible;
210
211
impl Fallible for Infallible {
212
    type Error = core::convert::Infallible;
213
}
214
215
impl Default for Infallible {
216
0
    fn default() -> Self {
217
0
        Infallible
218
0
    }
Unexecuted instantiation: <rkyv::Infallible as core::default::Default>::default
Unexecuted instantiation: <rkyv::Infallible as core::default::Default>::default
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
/// ```
400
pub 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`.
434
pub 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).
447
pub 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
/// ```
622
pub 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
511k
    unsafe fn resolve_unsized(
669
511k
        &self,
670
511k
        from: usize,
671
511k
        to: usize,
672
511k
        resolver: Self::MetadataResolver,
673
511k
        out: *mut RelPtr<Self::Archived>,
674
511k
    ) {
675
511k
        RelPtr::resolve_emplace(from, to, self, resolver, out);
676
511k
    }
<wasmer_types::module::ModuleInfo as rkyv::ArchiveUnsized>::resolve_unsized
Line
Count
Source
668
30.0k
    unsafe fn resolve_unsized(
669
30.0k
        &self,
670
30.0k
        from: usize,
671
30.0k
        to: usize,
672
30.0k
        resolver: Self::MetadataResolver,
673
30.0k
        out: *mut RelPtr<Self::Archived>,
674
30.0k
    ) {
675
30.0k
        RelPtr::resolve_emplace(from, to, self, resolver, out);
676
30.0k
    }
<[wasmer_types::initializers::OwnedDataInitializer] as rkyv::ArchiveUnsized>::resolve_unsized
Line
Count
Source
668
30.0k
    unsafe fn resolve_unsized(
669
30.0k
        &self,
670
30.0k
        from: usize,
671
30.0k
        to: usize,
672
30.0k
        resolver: Self::MetadataResolver,
673
30.0k
        out: *mut RelPtr<Self::Archived>,
674
30.0k
    ) {
675
30.0k
        RelPtr::resolve_emplace(from, to, self, resolver, out);
676
30.0k
    }
<[wasmer_types::types::Type] as rkyv::ArchiveUnsized>::resolve_unsized
Line
Count
Source
668
309k
    unsafe fn resolve_unsized(
669
309k
        &self,
670
309k
        from: usize,
671
309k
        to: usize,
672
309k
        resolver: Self::MetadataResolver,
673
309k
        out: *mut RelPtr<Self::Archived>,
674
309k
    ) {
675
309k
        RelPtr::resolve_emplace(from, to, self, resolver, out);
676
309k
    }
<[wasmer_types::indexes::FunctionIndex] as rkyv::ArchiveUnsized>::resolve_unsized
Line
Count
Source
668
84.5k
    unsafe fn resolve_unsized(
669
84.5k
        &self,
670
84.5k
        from: usize,
671
84.5k
        to: usize,
672
84.5k
        resolver: Self::MetadataResolver,
673
84.5k
        out: *mut RelPtr<Self::Archived>,
674
84.5k
    ) {
675
84.5k
        RelPtr::resolve_emplace(from, to, self, resolver, out);
676
84.5k
    }
<[u8] as rkyv::ArchiveUnsized>::resolve_unsized
Line
Count
Source
668
57.0k
    unsafe fn resolve_unsized(
669
57.0k
        &self,
670
57.0k
        from: usize,
671
57.0k
        to: usize,
672
57.0k
        resolver: Self::MetadataResolver,
673
57.0k
        out: *mut RelPtr<Self::Archived>,
674
57.0k
    ) {
675
57.0k
        RelPtr::resolve_emplace(from, to, self, resolver, out);
676
57.0k
    }
Unexecuted instantiation: <core::ffi::c_str::CStr as rkyv::ArchiveUnsized>::resolve_unsized
Unexecuted instantiation: <str as rkyv::ArchiveUnsized>::resolve_unsized
Unexecuted instantiation: <wasmer_types::module::ModuleInfo as rkyv::ArchiveUnsized>::resolve_unsized
Unexecuted instantiation: <[wasmer_types::initializers::OwnedDataInitializer] as rkyv::ArchiveUnsized>::resolve_unsized
Unexecuted instantiation: <[wasmer_types::types::Type] as rkyv::ArchiveUnsized>::resolve_unsized
Unexecuted instantiation: <[wasmer_types::indexes::FunctionIndex] as rkyv::ArchiveUnsized>::resolve_unsized
Unexecuted instantiation: <[u8] as rkyv::ArchiveUnsized>::resolve_unsized
Unexecuted instantiation: <core::ffi::c_str::CStr as rkyv::ArchiveUnsized>::resolve_unsized
Unexecuted instantiation: <str as rkyv::ArchiveUnsized>::resolve_unsized
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.
683
pub 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`.
694
pub 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.
703
pub 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.
723
pub 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.
728
pub 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.
733
pub type RawRelPtr = rel_ptr::RawRelPtr<Archived<isize>>;
734
/// The default relative pointer.
735
///
736
/// This will use an archived [`FixedIsize`] to hold the offset.
737
pub 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.
742
pub 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.
746
pub 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.
750
pub 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.
755
pub type MetadataResolver<T> = <T as ArchiveUnsized>::MetadataResolver;