devela::_dep::rkyv::traits

Trait Archive

pub trait Archive {
    type Archived: Portable;
    type Resolver;

    const COPY_OPTIMIZATION: CopyOptimization<Self> = _;

    // Required method
    fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>);
}
Available on crate feature dep_rkyv only.
Expand description

A type that can be used without deserializing.

Archive is one of three basic traits used to work with zero-copy data and controls the layout of the data in its archived zero-copy representation. The Serialize trait helps transform types into that representation, and the Deserialize trait helps transform types back out.

Types that implement Archive must have a well-defined archived size. Unsized types can be supported using the ArchiveUnsized trait, along with SerializeUnsized and DeserializeUnsized.

Archiving is done depth-first, writing any data owned by a type before writing the data for the type itself. The type must be able to create the archived type from only its own data and its resolver.

Archived data is always treated as if it is tree-shaped, with the root owning its direct descendents and so on. Data that is not tree-shaped can be supported using special serializer and deserializer bounds (see ArchivedRc for example). In a buffer of serialized data, objects are laid out in reverse order. This means that the root object is located near the end of the buffer and leaf objects are located near the beginning.

§Examples

Most of the time, #[derive(Archive)] will create an acceptable implementation. You can use the #[rkyv(...)] attribute to control how the implementation is generated. See the Archive derive macro for more details.

use rkyv::{deserialize, rancor::Error, Archive, Deserialize, Serialize};

#[derive(Archive, Deserialize, Serialize, Debug, PartialEq)]
#[rkyv(
    // This will generate a PartialEq impl between our unarchived
    // and archived types
    compare(PartialEq),
    // Derives can be passed through to the generated type:
    derive(Debug),
)]
struct Test {
    int: u8,
    string: String,
    option: Option<Vec<i32>>,
}

fn main() {
    let value = Test {
        int: 42,
        string: "hello world".to_string(),
        option: Some(vec![1, 2, 3, 4]),
    };

    // Serializing is as easy as a single function call
    let _bytes = rkyv::to_bytes::<Error>(&value).unwrap();

    // Or you can customize your serialization for better performance or control
    // over resource usage
    use rkyv::{api::high::to_bytes_with_alloc, ser::allocator::Arena};

    let mut arena = Arena::new();
    let bytes =
        to_bytes_with_alloc::<_, Error>(&value, arena.acquire()).unwrap();

    // You can use the safe API for fast zero-copy deserialization
    let archived = rkyv::access::<ArchivedTest, Error>(&bytes[..]).unwrap();
    assert_eq!(archived, &value);

    // Or you can use the unsafe API for maximum performance
    let archived =
        unsafe { rkyv::access_unchecked::<ArchivedTest>(&bytes[..]) };
    assert_eq!(archived, &value);

    // And you can always deserialize back to the original type
    let deserialized = deserialize::<Test, Error>(archived).unwrap();
    assert_eq!(deserialized, value);
}

Note: the safe API requires the bytecheck feature.

Many of the core and standard library types already have Archive implementations available, but you may need to implement Archive for your own types in some cases the derive macro cannot handle.

In this example, we add our own wrapper that serializes a &'static str as if it’s owned. Normally you can lean on the archived version of String to do most of the work, or use the Inline to do exactly this. This example does everything to demonstrate how to implement Archive for your own types.

use core::{slice, str};

use rkyv::{
    access_unchecked,
    rancor::{Error, Fallible},
    ser::Writer,
    to_bytes,
    Archive, ArchiveUnsized, Archived, Portable, RelPtr, Serialize,
    SerializeUnsized, munge::munge, Place,
};

struct OwnedStr {
    inner: &'static str,
}

#[derive(Portable)]
#[repr(transparent)]
struct ArchivedOwnedStr {
    // This will be a relative pointer to our string
    ptr: RelPtr<str>,
}

impl ArchivedOwnedStr {
    // This will help us get the bytes of our type as a str again.
    fn as_str(&self) -> &str {
        unsafe {
            // The as_ptr() function of RelPtr will get a pointer the str
            &*self.ptr.as_ptr()
        }
    }
}

struct OwnedStrResolver {
    // This will be the position that the bytes of our string are stored at.
    // We'll use this to resolve the relative pointer of our
    // ArchivedOwnedStr.
    pos: usize,
}

// The Archive implementation defines the archived version of our type and
// determines how to turn the resolver into the archived form. The Serialize
// implementations determine how to make a resolver from the original value.
impl Archive for OwnedStr {
    type Archived = ArchivedOwnedStr;
    // This is the resolver we can create our Archived version from.
    type Resolver = OwnedStrResolver;

    // The resolve function consumes the resolver and produces the archived
    // value at the given position.
    fn resolve(
        &self,
        resolver: Self::Resolver,
        out: Place<Self::Archived>,
    ) {
        munge!(let ArchivedOwnedStr { ptr } = out);
        RelPtr::emplace_unsized(
            resolver.pos,
            self.inner.archived_metadata(),
            ptr,
        );
    }
}

// We restrict our serializer types with Writer because we need its
// capabilities to serialize the inner string. For other types, we might
// need more or less restrictive bounds on the type of S.
impl<S: Fallible + Writer + ?Sized> Serialize<S> for OwnedStr {
    fn serialize(
        &self,
        serializer: &mut S,
    ) -> Result<Self::Resolver, S::Error> {
        // This is where we want to write the bytes of our string and return
        // a resolver that knows where those bytes were written.
        // We also need to serialize the metadata for our str.
        Ok(OwnedStrResolver {
            pos: self.inner.serialize_unsized(serializer)?,
        })
    }
}

const STR_VAL: &'static str = "I'm in an OwnedStr!";
let value = OwnedStr { inner: STR_VAL };
// It works!
let buf = to_bytes::<Error>(&value).expect("failed to serialize");
let archived =
    unsafe { access_unchecked::<ArchivedOwnedStr>(buf.as_ref()) };
// Let's make sure our data got written correctly
assert_eq!(archived.as_str(), STR_VAL);

Provided Associated Constants§

const COPY_OPTIMIZATION: CopyOptimization<Self> = _

An optimization flag that allows the bytes of this type to be copied directly to a writer instead of calling serialize.

This optimization is disabled by default. To enable this optimization, you must unsafely attest that Self is trivially copyable using CopyOptimization::enable or CopyOptimization::enable_if.

Required Associated Types§

type Archived: Portable

The archived representation of this type.

In this form, the data can be used with zero-copy deserialization.

type Resolver

The resolver for this type. It must contain all the additional information from serializing needed to make the archived type from the normal type.

Required Methods§

fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>)

Creates the archived version of this value at the given position and writes it to the given output.

The output should be initialized field-by-field rather than by writing a whole struct. Performing a typed copy will mark all of the padding bytes as uninitialized, but they must remain set to the value they currently have. This prevents leaking uninitialized memory to the final archive.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

§

impl Archive for bool

§

impl Archive for char

§

impl Archive for f32

§

impl Archive for f64

§

impl Archive for i8

§

impl Archive for i16

§

impl Archive for i32

§

impl Archive for i64

§

impl Archive for i128

§

impl Archive for isize

§

impl Archive for u8

§

impl Archive for u16

§

impl Archive for u32

§

impl Archive for u64

§

impl Archive for u128

§

impl Archive for ()

§

impl Archive for usize

§

impl<T0> Archive for (T0,)
where T0: Archive,

§

type Archived = ArchivedTuple1<<T0 as Archive>::Archived>

§

type Resolver = (<T0 as Archive>::Resolver,)

§

fn resolve( &self, resolver: <(T0,) as Archive>::Resolver, out: Place<<(T0,) as Archive>::Archived>, )

§

impl<T0, T1> Archive for (T0, T1)
where T0: Archive, T1: Archive,

§

type Archived = ArchivedTuple2<<T0 as Archive>::Archived, <T1 as Archive>::Archived>

§

type Resolver = (<T0 as Archive>::Resolver, <T1 as Archive>::Resolver)

§

fn resolve( &self, resolver: <(T0, T1) as Archive>::Resolver, out: Place<<(T0, T1) as Archive>::Archived>, )

§

impl<T0, T1, T2> Archive for (T0, T1, T2)
where T0: Archive, T1: Archive, T2: Archive,

§

type Archived = ArchivedTuple3<<T0 as Archive>::Archived, <T1 as Archive>::Archived, <T2 as Archive>::Archived>

§

type Resolver = (<T0 as Archive>::Resolver, <T1 as Archive>::Resolver, <T2 as Archive>::Resolver)

§

fn resolve( &self, resolver: <(T0, T1, T2) as Archive>::Resolver, out: Place<<(T0, T1, T2) as Archive>::Archived>, )

§

impl<T0, T1, T2, T3> Archive for (T0, T1, T2, T3)
where T0: Archive, T1: Archive, T2: Archive, T3: Archive,

§

type Archived = ArchivedTuple4<<T0 as Archive>::Archived, <T1 as Archive>::Archived, <T2 as Archive>::Archived, <T3 as Archive>::Archived>

§

type Resolver = (<T0 as Archive>::Resolver, <T1 as Archive>::Resolver, <T2 as Archive>::Resolver, <T3 as Archive>::Resolver)

§

fn resolve( &self, resolver: <(T0, T1, T2, T3) as Archive>::Resolver, out: Place<<(T0, T1, T2, T3) as Archive>::Archived>, )

§

impl<T0, T1, T2, T3, T4> Archive for (T0, T1, T2, T3, T4)
where T0: Archive, T1: Archive, T2: Archive, T3: Archive, T4: Archive,

§

type Archived = ArchivedTuple5<<T0 as Archive>::Archived, <T1 as Archive>::Archived, <T2 as Archive>::Archived, <T3 as Archive>::Archived, <T4 as Archive>::Archived>

§

type Resolver = (<T0 as Archive>::Resolver, <T1 as Archive>::Resolver, <T2 as Archive>::Resolver, <T3 as Archive>::Resolver, <T4 as Archive>::Resolver)

§

fn resolve( &self, resolver: <(T0, T1, T2, T3, T4) as Archive>::Resolver, out: Place<<(T0, T1, T2, T3, T4) as Archive>::Archived>, )

§

impl<T0, T1, T2, T3, T4, T5> Archive for (T0, T1, T2, T3, T4, T5)
where T0: Archive, T1: Archive, T2: Archive, T3: Archive, T4: Archive, T5: Archive,

§

type Archived = ArchivedTuple6<<T0 as Archive>::Archived, <T1 as Archive>::Archived, <T2 as Archive>::Archived, <T3 as Archive>::Archived, <T4 as Archive>::Archived, <T5 as Archive>::Archived>

§

type Resolver = (<T0 as Archive>::Resolver, <T1 as Archive>::Resolver, <T2 as Archive>::Resolver, <T3 as Archive>::Resolver, <T4 as Archive>::Resolver, <T5 as Archive>::Resolver)

§

fn resolve( &self, resolver: <(T0, T1, T2, T3, T4, T5) as Archive>::Resolver, out: Place<<(T0, T1, T2, T3, T4, T5) as Archive>::Archived>, )

§

impl<T0, T1, T2, T3, T4, T5, T6> Archive for (T0, T1, T2, T3, T4, T5, T6)
where T0: Archive, T1: Archive, T2: Archive, T3: Archive, T4: Archive, T5: Archive, T6: Archive,

§

type Archived = ArchivedTuple7<<T0 as Archive>::Archived, <T1 as Archive>::Archived, <T2 as Archive>::Archived, <T3 as Archive>::Archived, <T4 as Archive>::Archived, <T5 as Archive>::Archived, <T6 as Archive>::Archived>

§

type Resolver = (<T0 as Archive>::Resolver, <T1 as Archive>::Resolver, <T2 as Archive>::Resolver, <T3 as Archive>::Resolver, <T4 as Archive>::Resolver, <T5 as Archive>::Resolver, <T6 as Archive>::Resolver)

§

fn resolve( &self, resolver: <(T0, T1, T2, T3, T4, T5, T6) as Archive>::Resolver, out: Place<<(T0, T1, T2, T3, T4, T5, T6) as Archive>::Archived>, )

§

impl<T0, T1, T2, T3, T4, T5, T6, T7> Archive for (T0, T1, T2, T3, T4, T5, T6, T7)
where T0: Archive, T1: Archive, T2: Archive, T3: Archive, T4: Archive, T5: Archive, T6: Archive, T7: Archive,

§

type Archived = ArchivedTuple8<<T0 as Archive>::Archived, <T1 as Archive>::Archived, <T2 as Archive>::Archived, <T3 as Archive>::Archived, <T4 as Archive>::Archived, <T5 as Archive>::Archived, <T6 as Archive>::Archived, <T7 as Archive>::Archived>

§

type Resolver = (<T0 as Archive>::Resolver, <T1 as Archive>::Resolver, <T2 as Archive>::Resolver, <T3 as Archive>::Resolver, <T4 as Archive>::Resolver, <T5 as Archive>::Resolver, <T6 as Archive>::Resolver, <T7 as Archive>::Resolver)

§

fn resolve( &self, resolver: <(T0, T1, T2, T3, T4, T5, T6, T7) as Archive>::Resolver, out: Place<<(T0, T1, T2, T3, T4, T5, T6, T7) as Archive>::Archived>, )

§

impl<T0, T1, T2, T3, T4, T5, T6, T7, T8> Archive for (T0, T1, T2, T3, T4, T5, T6, T7, T8)
where T0: Archive, T1: Archive, T2: Archive, T3: Archive, T4: Archive, T5: Archive, T6: Archive, T7: Archive, T8: Archive,

§

type Archived = ArchivedTuple9<<T0 as Archive>::Archived, <T1 as Archive>::Archived, <T2 as Archive>::Archived, <T3 as Archive>::Archived, <T4 as Archive>::Archived, <T5 as Archive>::Archived, <T6 as Archive>::Archived, <T7 as Archive>::Archived, <T8 as Archive>::Archived>

§

type Resolver = (<T0 as Archive>::Resolver, <T1 as Archive>::Resolver, <T2 as Archive>::Resolver, <T3 as Archive>::Resolver, <T4 as Archive>::Resolver, <T5 as Archive>::Resolver, <T6 as Archive>::Resolver, <T7 as Archive>::Resolver, <T8 as Archive>::Resolver)

§

fn resolve( &self, resolver: <(T0, T1, T2, T3, T4, T5, T6, T7, T8) as Archive>::Resolver, out: Place<<(T0, T1, T2, T3, T4, T5, T6, T7, T8) as Archive>::Archived>, )

§

impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> Archive for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)
where T0: Archive, T1: Archive, T2: Archive, T3: Archive, T4: Archive, T5: Archive, T6: Archive, T7: Archive, T8: Archive, T9: Archive,

§

type Archived = ArchivedTuple10<<T0 as Archive>::Archived, <T1 as Archive>::Archived, <T2 as Archive>::Archived, <T3 as Archive>::Archived, <T4 as Archive>::Archived, <T5 as Archive>::Archived, <T6 as Archive>::Archived, <T7 as Archive>::Archived, <T8 as Archive>::Archived, <T9 as Archive>::Archived>

§

type Resolver = (<T0 as Archive>::Resolver, <T1 as Archive>::Resolver, <T2 as Archive>::Resolver, <T3 as Archive>::Resolver, <T4 as Archive>::Resolver, <T5 as Archive>::Resolver, <T6 as Archive>::Resolver, <T7 as Archive>::Resolver, <T8 as Archive>::Resolver, <T9 as Archive>::Resolver)

§

fn resolve( &self, resolver: <(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) as Archive>::Resolver, out: Place<<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) as Archive>::Archived>, )

§

impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Archive for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)
where T0: Archive, T1: Archive, T2: Archive, T3: Archive, T4: Archive, T5: Archive, T6: Archive, T7: Archive, T8: Archive, T9: Archive, T10: Archive,

§

impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Archive for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)
where T0: Archive, T1: Archive, T2: Archive, T3: Archive, T4: Archive, T5: Archive, T6: Archive, T7: Archive, T8: Archive, T9: Archive, T10: Archive, T11: Archive,

§

impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Archive for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)
where T0: Archive, T1: Archive, T2: Archive, T3: Archive, T4: Archive, T5: Archive, T6: Archive, T7: Archive, T8: Archive, T9: Archive, T10: Archive, T11: Archive, T12: Archive,

§

impl<T, const N: usize> Archive for [T; N]
where T: Archive,

§

const COPY_OPTIMIZATION: CopyOptimization<[T; N]>

§

type Archived = [<T as Archive>::Archived; N]

§

type Resolver = [<T as Archive>::Resolver; N]

§

fn resolve( &self, resolver: <[T; N] as Archive>::Resolver, out: Place<<[T; N] as Archive>::Archived>, )

Implementors§

§

impl Archive for IpAddr

§

impl Archive for SocketAddr

§

impl Archive for Ipv4Addr

§

impl Archive for Ipv6Addr

§

impl Archive for SocketAddrV4

§

impl Archive for SocketAddrV6

Source§

impl Archive for Boxed

Available on crate feature alloc only.
§

impl Archive for NonZero<i8>

§

impl Archive for NonZero<i16>

§

impl Archive for NonZero<i32>

§

impl Archive for NonZero<i64>

§

impl Archive for NonZero<i128>

§

impl Archive for NonZero<isize>

§

impl Archive for NonZero<u8>

§

impl Archive for NonZero<u16>

§

impl Archive for NonZero<u32>

§

impl Archive for NonZero<u64>

§

impl Archive for NonZero<u128>

§

impl Archive for NonZero<usize>

§

impl Archive for PhantomPinned

§

impl Archive for RangeFull

§

impl Archive for String

§

impl Archive for CString

§

impl Archive for Duration

§

impl Archive for NonZeroI16_be

§

impl Archive for NonZeroI16_le

§

impl Archive for NonZeroI32_be

§

impl Archive for NonZeroI32_le

§

impl Archive for NonZeroI64_be

§

impl Archive for NonZeroI64_le

§

impl Archive for NonZeroI128_be

§

impl Archive for NonZeroI128_le

§

impl Archive for NonZeroU16_be

§

impl Archive for NonZeroU16_le

§

impl Archive for NonZeroU32_be

§

impl Archive for NonZeroU32_le

§

impl Archive for NonZeroU64_be

§

impl Archive for NonZeroU64_le

§

impl Archive for NonZeroU128_be

§

impl Archive for NonZeroU128_le

§

impl Archive for char_be

§

impl Archive for char_le

§

impl Archive for f32_be

§

impl Archive for f32_le

§

impl Archive for f64_be

§

impl Archive for f64_le

§

impl Archive for i16_be

§

impl Archive for i16_le

§

impl Archive for i32_be

§

impl Archive for i32_le

§

impl Archive for i64_be

§

impl Archive for i64_le

§

impl Archive for i128_be

§

impl Archive for i128_le

§

impl Archive for u16_be

§

impl Archive for u16_le

§

impl Archive for u32_be

§

impl Archive for u32_le

§

impl Archive for u64_be

§

impl Archive for u64_le

§

impl Archive for u128_be

§

impl Archive for u128_le

§

impl<BK, BV, K, V> Archive for EntryAdapter<BK, BV, K, V>
where BK: Borrow<K>, BV: Borrow<V>, K: Archive, V: Archive,

§

impl<F, W> Archive for With<F, W>
where W: ArchiveWith<F>, F: ?Sized,

§

type Archived = <W as ArchiveWith<F>>::Archived

§

type Resolver = <W as ArchiveWith<F>>::Resolver

§

impl<K> Archive for BTreeSet<K>
where K: Archive + Ord, <K as Archive>::Archived: Ord,

§

impl<K, S> Archive for devela::all::HashSet<K, S>
where K: Archive + Hash + Eq, <K as Archive>::Archived: Hash + Eq,

§

impl<K, S> Archive for devela::_dep::_std::collections::HashSet<K, S>
where K: Archive + Hash + Eq, <K as Archive>::Archived: Hash + Eq,

§

impl<K, V> Archive for BTreeMap<K, V>
where K: Archive + Ord, V: Archive, <K as Archive>::Archived: Ord,

§

impl<K, V, S> Archive for devela::all::HashMap<K, V, S>
where V: Archive, K: Archive + Hash + Eq, <K as Archive>::Archived: Hash + Eq,

§

impl<K, V, S> Archive for devela::_dep::_std::collections::HashMap<K, V, S>
where V: Archive, K: Archive + Hash + Eq, <K as Archive>::Archived: Hash + Eq,

§

impl<T> Archive for Option<T>
where T: Archive,

§

impl<T> Archive for Bound<T>
where T: Archive,

Source§

impl<T> Archive for BareBox<T>
where T: Archive,

§

impl<T> Archive for Box<T>
where T: ArchiveUnsized + ?Sized,

§

impl<T> Archive for ManuallyDrop<T>
where T: Archive,

§

impl<T> Archive for PhantomData<T>
where T: ?Sized,

§

impl<T> Archive for Range<T>
where T: Archive,

§

impl<T> Archive for RangeFrom<T>
where T: Archive,

§

impl<T> Archive for RangeInclusive<T>
where T: Archive,

§

impl<T> Archive for RangeTo<T>
where T: Archive,

§

impl<T> Archive for RangeToInclusive<T>
where T: Archive,

§

impl<T> Archive for Rc<T>
where T: ArchiveUnsized + ?Sized,

§

impl<T> Archive for devela::all::RcWeak<T>
where T: ArchiveUnsized + ?Sized,

§

impl<T> Archive for Vec<T>
where T: Archive,

§

impl<T> Archive for VecDeque<T>
where T: Archive,

§

impl<T> Archive for Arc<T>
where T: ArchiveUnsized + ?Sized,

§

impl<T> Archive for devela::work::ArcWeak<T>
where T: ArchiveUnsized + ?Sized,

§

impl<T, U> Archive for Result<T, U>
where T: Archive, U: Archive,

Source§

impl<T, const C: usize, const R: usize, const CR: usize, const RMAJ: bool, S: Storage> Archive for Array2d<T, C, R, CR, RMAJ, S>
where Array<T, CR, S>: Archive,

Source§

type Archived = ArchivedArray2d<T, C, R, CR, RMAJ, S>

Source§

type Resolver = Array2dResolver<T, C, R, CR, RMAJ, S>

Source§

impl<T, const CAP: usize, IDX, S: Storage> Archive for Destaque<T, CAP, IDX, S>
where Array<T, CAP, S>: Archive, IDX: Archive,

Source§

type Archived = ArchivedDestaque<T, CAP, IDX, S>

Source§

type Resolver = DestaqueResolver<T, CAP, IDX, S>

Source§

impl<T, const CAP: usize, IDX, S: Storage> Archive for Stack<T, CAP, IDX, S>
where Array<T, CAP, S>: Archive, IDX: Archive,

Source§

type Archived = ArchivedStack<T, CAP, IDX, S>

Source§

type Resolver = StackResolver<T, CAP, IDX, S>

Source§

impl<T, const CAP: usize, S: Storage> Archive for Array<T, CAP, S>
where S::Stored<[T; CAP]>: Archive,