use epserde::prelude::*;
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
use alloc::rc::Rc;
use core::ops::ControlFlow;
#[cfg(feature = "std")]
use std::{
hash::{BuildHasherDefault, DefaultHasher},
ops::{Bound, RangeBounds, RangeInclusive},
rc::Rc,
};
const TEST_STRS: &[&str] = &["abc\0\x0a🔥\u{0d2bdf}", ""];
#[test]
fn test_box_str() {
for &test_str in TEST_STRS {
let s = test_str;
{
let mut cursor = <AlignedCursor>::new();
let mut schema = unsafe { s.serialize_with_schema(&mut cursor).unwrap() };
schema.0.sort_by_key(|a| a.offset);
cursor.set_position(0);
let full_copy = unsafe { <Box<str>>::deserialize_full(&mut cursor).unwrap() };
assert_eq!(s, &*full_copy);
let eps_copy = unsafe { <Box<str>>::deserialize_eps(cursor.as_bytes()).unwrap() };
assert_eq!(s, eps_copy);
let eps_copy = unsafe { String::deserialize_eps(cursor.as_bytes()).unwrap() };
assert_eq!(s, eps_copy);
}
let s = test_str.to_string();
{
let mut cursor = <AlignedCursor>::new();
let mut schema = unsafe { s.serialize_with_schema(&mut cursor).unwrap() };
schema.0.sort_by_key(|a| a.offset);
cursor.set_position(0);
let full_copy = unsafe { String::deserialize_full(&mut cursor).unwrap() };
assert_eq!(s, full_copy);
let eps_copy = unsafe { <Box<str>>::deserialize_eps(cursor.as_bytes()).unwrap() };
assert_eq!(s, eps_copy);
let eps_copy = unsafe { String::deserialize_eps(cursor.as_bytes()).unwrap() };
assert_eq!(s, eps_copy);
}
let s = test_str.to_string().into_boxed_str();
{
let mut cursor = <AlignedCursor>::new();
unsafe { s.serialize(&mut cursor).unwrap() };
cursor.set_position(0);
let full_copy = unsafe { <Box<str>>::deserialize_full(&mut cursor).unwrap() };
assert_eq!(s, full_copy);
let eps_copy = unsafe { <Box<str>>::deserialize_eps(cursor.as_bytes()).unwrap() };
assert_eq!(s.as_ref(), eps_copy);
let eps_copy = unsafe { String::deserialize_eps(cursor.as_bytes()).unwrap() };
assert_eq!(s.as_ref(), eps_copy);
}
}
}
fn test_generic<T>(s: T)
where
T: Serialize + Deserialize + PartialEq + core::fmt::Debug,
for<'a> DeserType<'a, T>: PartialEq<T> + core::fmt::Debug,
{
{
let mut cursor = <AlignedCursor<Aligned16>>::new();
let mut schema = unsafe { s.serialize_with_schema(&mut cursor).unwrap() };
schema.0.sort_by_key(|a| a.offset);
cursor.set_position(0);
let full_copy = unsafe { <T>::deserialize_full(&mut cursor).unwrap() };
assert_eq!(s, full_copy);
let bytes = cursor.as_bytes();
let full_copy = unsafe { <T>::deserialize_eps(bytes).unwrap() };
assert_eq!(full_copy, s);
let _ = schema.to_csv();
let _ = schema.debug(bytes);
}
{
let mut cursor = <AlignedCursor<Aligned16>>::new();
unsafe { s.serialize(&mut cursor).unwrap() };
cursor.set_position(0);
let full_copy = unsafe { <T>::deserialize_full(&mut cursor).unwrap() };
assert_eq!(s, full_copy);
let full_copy = unsafe { <T>::deserialize_eps(cursor.as_bytes()).unwrap() };
assert_eq!(full_copy, s);
}
}
#[test]
fn test_range() {
test_generic::<core::ops::Range<i32>>(0..10);
#[derive(Epserde, PartialEq, Debug)]
struct Data(core::ops::Range<i32>);
test_generic(Data(0..10));
}
#[test]
fn test_ser_rc_ref() {
let v = vec![0, 1, 2, 3];
let mut cursor = <AlignedCursor<Aligned16>>::new();
unsafe { Serialize::serialize(&Rc::new(v.as_slice()), &mut cursor).unwrap() };
cursor.set_position(0);
let s = unsafe { <Rc<Box<[i32]>>>::deserialize_eps(cursor.as_bytes()).unwrap() };
assert_eq!(&*s, &v);
}
#[test]
fn test_ref_field() {
let v = vec![0, 1, 2, 3];
let mut cursor = <AlignedCursor<Aligned16>>::new();
#[derive(Epserde, Debug)]
struct Data<A>(A);
unsafe { Serialize::serialize(&Rc::new(Data(v.as_slice())), &mut cursor).unwrap() };
cursor.set_position(0);
let s = unsafe { <Rc<Data<Box<[i32]>>>>::deserialize_eps(cursor.as_bytes()).unwrap() };
assert_eq!(s.0, &v);
}
#[cfg(feature = "std")]
#[test]
fn test_range_bound_deep_copy_idx() {
let r = RangeInclusive::new("a".to_string(), "b".to_string());
let mut cursor = <AlignedCursor<Aligned16>>::new();
unsafe { r.serialize(&mut cursor).unwrap() };
cursor.set_position(0);
let full = unsafe { RangeInclusive::<String>::deserialize_full(&mut cursor).unwrap() };
assert_eq!(full, r);
let eps = unsafe { RangeInclusive::<String>::deserialize_eps(cursor.as_bytes()).unwrap() };
assert_eq!(eps.start_bound(), Bound::Included(&"a"));
assert_eq!(eps.end_bound(), Bound::Included(&"b"));
}
#[test]
fn test_control_flow() {
test_generic::<ControlFlow<i32, f64>>(ControlFlow::Break(42));
test_generic::<ControlFlow<i32, f64>>(ControlFlow::Continue(1.618));
}
#[test]
fn test_bound() {
test_generic::<core::ops::Bound<i32>>(core::ops::Bound::Unbounded);
test_generic::<core::ops::Bound<i32>>(core::ops::Bound::Included(42));
test_generic::<core::ops::Bound<i32>>(core::ops::Bound::Excluded(42));
}
#[cfg(feature = "std")]
#[test]
fn test_builder_hasher_default() {
let bhd = BuildHasherDefault::<DefaultHasher>::default();
let mut cursor = <AlignedCursor<Aligned16>>::new();
unsafe { bhd.serialize(&mut cursor).unwrap() };
cursor.set_position(0);
let full =
unsafe { BuildHasherDefault::<DefaultHasher>::deserialize_full(&mut cursor).unwrap() };
assert_eq!(&full, &bhd);
let eps =
unsafe { BuildHasherDefault::<DefaultHasher>::deserialize_eps(cursor.as_bytes()).unwrap() };
assert_eq!(&eps, &bhd);
}