| use std::fmt::Debug; | |
| use serde::Serialize; | |
| use serde::de::DeserializeOwned; | |
| use super::*; | |
| fn check_roundtrips<T: Serialize + DeserializeOwned + PartialEq + Debug>(t: T) { | |
| let ser_json = serde_json::to_string(&t).expect("should be able to serialize to json"); | |
| let de_json: T = | |
| serde_json::from_str(&ser_json).expect("should be able to deserialize from json"); | |
| assert_eq!(t, de_json, "value should be the same after json roundtrip"); | |
| let ser_postcard = | |
| ::postcard::to_allocvec(&t).expect("should be able to serialize to postcard"); | |
| let de_postcard: T = | |
| ::postcard::from_bytes(&ser_postcard).expect("should be able to deserialze from postcard"); | |
| assert_eq!(t, de_postcard, "value should be the same after postcard rountrip"); | |
| } | |
| #[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![], | |
| }); | |
| check_roundtrips(s); | |
| } | |
| #[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![], | |
| }); | |
| check_roundtrips(u); | |
| } | |
| #[test] | |
| fn test_stability() { | |
| check_roundtrips(Stability { | |
| feature: "guam_dotcom".to_owned(), | |
| level: StabilityLevel::Stable { since: None }, | |
| }); | |
| check_roundtrips(Stability { | |
| feature: "bing_mexico".to_owned(), | |
| level: StabilityLevel::Unstable, | |
| }); | |
| } | |
| #[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/postcard 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); | |
| } | |
| } |