blob: e878350e43b9bd7f6390b0f336ac8fe9fc118fa8 [file] [log] [blame]
use super::*;
#[test]
fn test_struct_info_roundtrip() {
let s = ItemEnum::Struct(Struct {
generics: Generics { params: vec![], where_predicates: vec![] },
kind: StructKind::Plain { fields: vec![], has_stripped_fields: false },
impls: vec![],
});
// JSON
let struct_json = serde_json::to_string(&s).unwrap();
let de_s = serde_json::from_str(&struct_json).unwrap();
assert_eq!(s, de_s);
// Bincode
let encoded: Vec<u8> = bincode::serialize(&s).unwrap();
let decoded: ItemEnum = bincode::deserialize(&encoded).unwrap();
assert_eq!(s, decoded);
}
#[test]
fn test_union_info_roundtrip() {
let u = ItemEnum::Union(Union {
generics: Generics { params: vec![], where_predicates: vec![] },
has_stripped_fields: false,
fields: vec![],
impls: vec![],
});
// JSON
let union_json = serde_json::to_string(&u).unwrap();
let de_u = serde_json::from_str(&union_json).unwrap();
assert_eq!(u, de_u);
// Bincode
let encoded: Vec<u8> = bincode::serialize(&u).unwrap();
let decoded: ItemEnum = bincode::deserialize(&encoded).unwrap();
assert_eq!(u, decoded);
}
#[cfg(feature = "rkyv_0_8")]
mod rkyv {
use std::fmt::Debug;
use rkyv::Archive;
use rkyv::api::high::{HighDeserializer, HighSerializer};
use rkyv::bytecheck::CheckBytes;
use rkyv::rancor::Strategy;
use rkyv::ser::allocator::ArenaHandle;
use rkyv::util::AlignedVec;
use rkyv::validation::Validator;
use rkyv::validation::archive::ArchiveValidator;
use rkyv::validation::shared::SharedValidator;
use crate::*;
#[test]
/// A test to exercise the (de)serialization roundtrip for a representative selection of types,
/// covering most of the rkyv-specific attributes we had to had.
fn test_rkyv_roundtrip() {
// Standard derives: a plain struct and union, mirroring the existing serde/bincode tests.
let s = ItemEnum::Struct(Struct {
generics: Generics { params: vec![], where_predicates: vec![] },
kind: StructKind::Plain { fields: vec![Id(1), Id(2)], has_stripped_fields: false },
impls: vec![Id(3)],
});
rkyv_roundtrip(&s);
let u = ItemEnum::Union(Union {
generics: Generics { params: vec![], where_predicates: vec![] },
has_stripped_fields: false,
fields: vec![Id(1)],
impls: vec![],
});
rkyv_roundtrip(&u);
// Extra trait derives, via rkyv(derive(PartialEq, Eq, PartialOrd, Ord, Hash)), on the archived type.
rkyv_roundtrip(&Id(99));
// Recursive cycle-breaking: `BorrowedRef` has omit_bounds on its `Box<Type>` field.
let ty = Type::BorrowedRef {
lifetime: Some("'a".to_string()),
is_mutable: false,
type_: Box::new(Type::Primitive("str".to_string())),
};
rkyv_roundtrip(&ty);
// `Slice` and `Tuple` are tuple-variant fields with omit_bounds on the unnamed field,
// which required special syntax (attribute inside the parentheses) to compile.
let ty = Type::Slice(Box::new(Type::Tuple(vec![
Type::Primitive("u32".to_string()),
Type::Generic("T".to_string()),
])));
rkyv_roundtrip(&ty);
// `Path` has serialize_bounds/deserialize_bounds and omit_bounds on its `args` field.
// `GenericArgs::AngleBracketed` exercises the full recursive chain: `Path` -> `GenericArgs` -> `GenericArg` -> `Type`.
let path = Path {
path: "std::option::Option".to_string(),
id: Id(42),
args: Some(Box::new(GenericArgs::AngleBracketed {
args: vec![GenericArg::Type(Type::Primitive("u32".to_string()))],
constraints: vec![],
})),
};
rkyv_roundtrip(&path);
// `FunctionPointer` is a `Box<FunctionPointer>` behind `omit_bounds` in `Type`.
// It transitively contains `Type` via `FunctionSignature`, exercising the cycle from the other direction.
let fp = Type::FunctionPointer(Box::new(FunctionPointer {
sig: FunctionSignature {
inputs: vec![("x".to_string(), Type::Primitive("i32".to_string()))],
output: Some(Type::Primitive("bool".to_string())),
is_c_variadic: false,
},
generic_params: vec![],
header: FunctionHeader {
is_const: false,
is_unsafe: false,
is_async: false,
abi: Abi::Rust,
},
}));
rkyv_roundtrip(&fp);
}
/// A helper function for roundtrip testing of rkyv-powered deserialization.
fn rkyv_roundtrip<T>(value: &T)
where
T: PartialEq
+ Debug
+ Archive
+ for<'a> rkyv::Serialize<
HighSerializer<AlignedVec, ArenaHandle<'a>, rkyv::rancor::Error>,
>,
T::Archived: rkyv::Deserialize<T, HighDeserializer<rkyv::rancor::Error>>
+ Debug
+ for<'a> CheckBytes<
Strategy<Validator<ArchiveValidator<'a>, SharedValidator>, rkyv::rancor::Error>,
>,
{
let bytes =
rkyv::api::high::to_bytes_in::<_, rkyv::rancor::Error>(value, AlignedVec::new())
.unwrap();
let archived = rkyv::api::high::access::<T::Archived, rkyv::rancor::Error>(&bytes)
.expect("Failed to access archived data");
let deserialized: T = rkyv::api::deserialize_using::<_, _, rkyv::rancor::Error>(
archived,
&mut rkyv::de::Pool::new(),
)
.unwrap();
assert_eq!(value, &deserialized);
}
}