pub trait ArchiveWith<F: ?Sized> {
type Archived: Portable;
type Resolver;
// Required method
fn resolve_with(
field: &F,
resolver: Self::Resolver,
out: Place<Self::Archived>,
);
}Expand description
A variant of Archive that works 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 and enum fields. When a field is serialized, it may use the implementations for the wrapper type and the given field instead of the implementation for the type itself.
Only a single implementation of Archive may be written
for each type, but multiple implementations of ArchiveWith can be written
for the same type because it is parametric over the wrapper type. This is
used with the #[rkyv(with = ..)] macro attribute to provide a more
flexible interface for serialization.
§Example
use rkyv::{
access_unchecked, deserialize,
rancor::{Error, Fallible, Infallible, ResultExt as _},
to_bytes,
with::{ArchiveWith, DeserializeWith, SerializeWith},
Archive, Archived, Deserialize, Place, Resolver, Serialize,
};
struct Incremented;
impl ArchiveWith<i32> for Incremented {
type Archived = Archived<i32>;
type Resolver = Resolver<i32>;
fn resolve_with(field: &i32, _: (), out: Place<Self::Archived>) {
let incremented = field + 1;
incremented.resolve((), out);
}
}
impl<S> SerializeWith<i32, S> for Incremented
where
S: Fallible + ?Sized,
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> DeserializeWith<Archived<i32>, i32, D> for Incremented
where
D: Fallible + ?Sized,
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 {
#[rkyv(with = Incremented)]
a: i32,
// Another i32 field, but not incremented this time
b: i32,
}
let value = Example { a: 4, b: 9 };
let buf = to_bytes::<Error>(&value).unwrap();
let archived =
unsafe { access_unchecked::<Archived<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 = deserialize::<Example, Infallible>(archived).always_ok();
// 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.