use std::{fmt::Debug, num::NonZeroU64, path::PathBuf}; use rkyv::{ ser::Serializer, with::{ArchiveWith, AsString, CopyOptimize, DeserializeWith, Map, Niche, SerializeWith, With}, AlignedVec, Archive, Archived, Infallible, }; use rkyv_with::{ArchiveWith, DeserializeWith}; use serializer::CustomSerializer; use crate::with_noop::WithNoop; mod serializer { use std::{alloc::Layout, ptr::NonNull}; use rkyv::{ ser::{serializers::AllocSerializer, ScratchSpace, Serializer}, with::AsStringError, AlignedVec, Fallible, }; /// Custom serializer so we can use the `AsString` wrapper #[derive(Default)] pub struct CustomSerializer { inner: AllocSerializer, } impl CustomSerializer { pub fn into_bytes(self) -> AlignedVec { self.inner.into_serializer().into_inner() } } impl Fallible for CustomSerializer { type Error = CustomSerializerError< as Fallible>::Error>; } impl Serializer for CustomSerializer { #[inline] fn pos(&self) -> usize { self.inner.pos() } #[inline] fn write(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { self.inner .write(bytes) .map_err(CustomSerializerError::Inner) } } impl ScratchSpace for CustomSerializer { unsafe fn push_scratch(&mut self, layout: Layout) -> Result, Self::Error> { self.inner .push_scratch(layout) .map_err(CustomSerializerError::Inner) } unsafe fn pop_scratch( &mut self, ptr: NonNull, layout: Layout, ) -> Result<(), Self::Error> { self.inner .pop_scratch(ptr, layout) .map_err(CustomSerializerError::Inner) } } #[derive(Debug)] pub enum CustomSerializerError { Inner(E), AsStringError(AsStringError), } impl From for CustomSerializerError { fn from(err: AsStringError) -> Self { Self::AsStringError(err) } } } mod with_noop { use rkyv::{ with::{ArchiveWith, DeserializeWith, SerializeWith}, Archive, Archived, Deserialize, Fallible, Serialize, }; /// Usable as rkyv With-wrapper which doesn't to anything /// and just uses the type's Archive/Deserialize/Serialize impls. pub struct WithNoop; impl ArchiveWith for WithNoop { type Archived = ::Archived; type Resolver = ::Resolver; unsafe fn resolve_with( field: &F, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived, ) { field.resolve(pos, resolver, out) } } impl, S: Fallible> SerializeWith for WithNoop { fn serialize_with( field: &F, serializer: &mut S, ) -> Result::Error> { field.serialize(serializer) } } impl DeserializeWith, F, D> for WithNoop where F: Archive, Archived: Deserialize, D: Fallible, { fn deserialize_with( field: &Archived, deserializer: &mut D, ) -> Result::Error> { field.deserialize(deserializer) } } } fn serialize(remote: &Remote) -> AlignedVec where Wrapper: SerializeWith>, { let mut serializer = CustomSerializer::<8>::default(); let with = With::::cast(remote); serializer.serialize_value(with).unwrap(); serializer.into_bytes() } fn archive(bytes: &[u8]) -> &>::Archived where Wrapper: ArchiveWith, { unsafe { rkyv::archived_root::>(bytes) } } fn roundtrip(remote: &Remote) where Wrapper: ArchiveWith + SerializeWith> + DeserializeWith>, Remote, Infallible>, Remote: Debug + PartialEq, { let bytes = serialize::(remote); let archived = archive::(&bytes); let deserialized: Remote = Wrapper::deserialize_with(archived, &mut Infallible).unwrap(); assert_eq!(remote, &deserialized); } #[test] fn named_struct() { #[derive(Debug, PartialEq)] struct Remote { a: u8, b: Vec, c: Option, d: Vec, } #[derive(Archive, ArchiveWith, DeserializeWith)] #[archive_with(from(Remote::))] struct Example { a: u8, #[with(CopyOptimize)] b: Vec, #[with(Niche)] #[archive_with(from(Option), via(Niche))] c: Option, #[archive_with(from(Vec), via(WithNoop, Map))] d: Vec, } let remote = Remote { a: 0, b: Vec::new(), c: None, d: Vec::new(), }; roundtrip::, _>(&remote); } #[test] fn unnamed_struct() { #[derive(Debug, PartialEq)] struct Remote(u8, Vec, Option, Vec); #[derive(Archive, ArchiveWith, DeserializeWith)] #[archive_with(from(Remote::))] struct Example( u8, #[with(CopyOptimize)] Vec, #[with(Niche)] #[archive_with(from(Option), via(Niche))] Option, #[archive_with(from(Vec), via(WithNoop, Map))] Vec, ); let remote = Remote(0, Vec::new(), None, Vec::new()); roundtrip::, _>(&remote); } #[test] fn unit_struct() { #[derive(Debug, PartialEq)] struct Remote; #[derive(Archive, ArchiveWith, DeserializeWith)] #[archive_with(from(Remote))] struct Example; let remote = Remote; roundtrip::(&remote); } #[test] fn full_enum() { #[derive(Debug, PartialEq)] enum Remote { A, B(u8), C { a: Vec, b: Option, c: Vec, }, } #[allow(unused)] #[derive(Archive, ArchiveWith, DeserializeWith)] #[archive_with(from(Remote::))] enum Example { A, B(u8), C { #[with(CopyOptimize)] a: Vec, #[with(Niche)] #[archive_with(from(Option), via(Niche))] b: Option, #[archive_with(from(Vec), via(WithNoop, Map))] c: Vec, }, } for remote in [ Remote::A, Remote::B(0), Remote::C { a: Vec::new(), b: None, c: Vec::new(), }, ] { roundtrip::, _>(&remote); } } #[test] fn named_struct_private() { mod remote { #[derive(Copy, Clone, Default)] pub struct Remote { inner: [u8; 4], } impl Remote { pub fn into_inner(self) -> [u8; 4] { self.inner } pub fn to_inner(&self) -> [u8; 4] { self.inner } pub fn as_inner(&self) -> &[u8; 4] { &self.inner } } } #[derive(Archive, ArchiveWith)] #[archive_with(from(remote::Remote))] struct ExampleByVal { #[archive_with(getter = "remote::Remote::into_inner", getter_owned)] inner: [u8; 4], } #[derive(Archive, ArchiveWith)] #[archive_with(from(remote::Remote))] struct ExampleByRef { #[archive_with(getter = "remote::Remote::to_inner")] inner: [u8; 4], } #[derive(Archive, ArchiveWith)] #[archive_with(from(remote::Remote))] struct ExampleThroughRef { #[archive_with(getter = "remote::Remote::as_inner", getter_ref)] inner: [u8; 4], } let remote = remote::Remote::default(); let _ = archive::(&serialize::(&remote)); let _ = archive::(&serialize::(&remote)); let _ = archive::(&serialize::(&remote)); } #[test] fn unnamed_struct_private() { mod remote { #[derive(Copy, Clone, Default)] pub struct Remote([u8; 4]); impl Remote { pub fn into_inner(self) -> [u8; 4] { self.0 } pub fn as_inner(&self) -> [u8; 4] { self.0 } } } #[derive(Archive, ArchiveWith)] #[archive_with(from(remote::Remote))] struct ExampleByRef(#[archive_with(getter = "remote::Remote::as_inner")] [u8; 4]); #[derive(Archive, ArchiveWith)] #[archive_with(from(remote::Remote))] struct ExampleByVal( #[archive_with(getter = "remote::Remote::into_inner", getter_owned)] [u8; 4], ); let remote = remote::Remote::default(); let _ = archive::(&serialize::(&remote)); let _ = archive::(&serialize::(&remote)); }