pub trait ArchiveWith<F: ?Sized> {
type Archived;
type Resolver;
// Required method
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);
Required Associated Types§
Required Methods§
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.