Trait ArchiveWith
pub trait ArchiveWith<F>where
F: ?Sized,{
type Archived: Portable;
type Resolver;
// Required method
fn resolve_with(
field: &F,
resolver: Self::Resolver,
out: Place<Self::Archived>,
);
}
dep_rkyv
only.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§
type Resolver
type Resolver
The resolver of a Self
with F
.
Required Methods§
fn resolve_with(field: &F, resolver: Self::Resolver, out: Place<Self::Archived>)
fn resolve_with(field: &F, resolver: Self::Resolver, out: Place<Self::Archived>)
Resolves the archived type using a reference to the field type F
.
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.