Trait rkyv::with::ArchiveWith
source · [−]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);