logo
pub trait ArchiveWith<F: ?Sized> {
    type Archived;
    type Resolver;
    unsafe fn resolve_with(
        field: &F,
        pos: usize,
        resolver: Self::Resolver,
        out: *mut Self::Archived
    ); }
Expand description

A variant of Archive that works with With wrappers.

Creating a wrapper allows users to customize how fields are archived easily without changing the unarchived type.

This trait allows wrapper types to transparently change the archive behaviors for struct fields. When a field is serialized, its reference may be converted to a With reference, and that reference may be serialized instead. With references look for implementations of ArchiveWith to determine how a wrapped field should be treated.

Example

use rkyv::{
    archived_root,
    ser::{
        serializers::AllocSerializer,
        Serializer,
    },
    with::{
        ArchiveWith,
        DeserializeWith,
        SerializeWith,
    },
    Archive,
    Archived,
    Deserialize,
    Fallible,
    Infallible,
    Resolver,
    Serialize,
};

struct Incremented;

impl ArchiveWith<i32> for Incremented {
    type Archived = Archived<i32>;
    type Resolver = Resolver<i32>;

    unsafe fn resolve_with(field: &i32, pos: usize, _: (), out: *mut Self::Archived) {
        let incremented = field + 1;
        incremented.resolve(pos, (), out);
    }
}

impl<S: Fallible + ?Sized> SerializeWith<i32, S> for Incremented
where
    i32: Serialize<S>,
{
    fn serialize_with(field: &i32, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
        let incremented = field + 1;
        incremented.serialize(serializer)
    }
}

impl<D: Fallible + ?Sized> DeserializeWith<Archived<i32>, i32, D> for Incremented
where
    Archived<i32>: Deserialize<i32, D>,
{
    fn deserialize_with(field: &Archived<i32>, deserializer: &mut D) -> Result<i32, D::Error> {
        Ok(field.deserialize(deserializer)? - 1)
    }
}

#[derive(Archive, Deserialize, Serialize)]
struct Example {
    #[with(Incremented)]
    a: i32,
    // Another i32 field, but not incremented this time
    b: i32,
}

let value = Example {
    a: 4,
    b: 9,
};

let mut serializer = AllocSerializer::<4096>::default();
serializer.serialize_value(&value).unwrap();
let buf = serializer.into_serializer().into_inner();

let archived = unsafe { archived_root::<Example>(buf.as_ref()) };
// The wrapped field has been incremented
assert_eq!(archived.a, 5);
// ... and the unwrapped field has not
assert_eq!(archived.b, 9);

let deserialized: Example = archived.deserialize(&mut Infallible).unwrap();
// The wrapped field is back to normal
assert_eq!(deserialized.a, 4);
// ... and the unwrapped field is unchanged
assert_eq!(deserialized.b, 9);

Associated Types

The archived type of a With<F, Self>.

The resolver of a With<F, Self>.

Required methods

Resolves the archived type using a reference to the field type F.

Safety
  • pos must be the position of out within the archive
  • resolver must be the result of serializing field

Implementors