#![allow(clippy::derive_partial_eq_without_eq, clippy::iter_nth_zero)]
use super::*;
use std::{
cmp::{Ord, Ordering, PartialEq, PartialOrd},
collections::hash_map::DefaultHasher,
fmt::{self, Display},
hash::{Hash, Hasher},
};
use serde::Serialize;
use serde_json;
#[allow(unused_imports)]
use crate::{
erased_types::{DynTrait, InterfaceType, IteratorItem},
std_types::{RArc, RBox, RBoxError, RCow, RNone, ROption, RSome, RStr, RString},
test_utils::{GetImpls, GetImplsHelper},
traits::IntoReprC,
type_level::bools::{False, True},
StableAbi,
};
#[allow(unused_imports)]
use core_extensions::SelfOps;
type DynTraitBox<I> = DynTrait<'static, RBox<()>, I>;
#[derive(Default, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
struct Foo<T> {
l: u32,
r: u32,
name: T,
}
#[repr(C)]
#[derive(StableAbi)]
#[sabi(impl_InterfaceType(Clone, Default, Display, Debug, Serialize, Deserialize, Ord, Hash))]
struct FooInterface;
#[test]
fn foo_interface_test() {
type GI = GetImpls<DynTraitBox<FooInterface>>;
assert!(!GI::IMPLS_SEND);
assert!(!GI::IMPLS_SYNC);
assert!(!GI::IMPLS_UNPIN);
assert!(GI::IMPLS_CLONE);
assert!(GI::IMPLS_DISPLAY);
assert!(GI::IMPLS_DEBUG);
assert!(GI::IMPLS_SERIALIZE);
assert!(GI::IMPLS_EQ);
assert!(GI::IMPLS_PARTIAL_EQ);
assert!(GI::IMPLS_ORD);
assert!(GI::IMPLS_PARTIAL_ORD);
assert!(GI::IMPLS_HASH);
assert!(GI::IMPLS_DESERIALIZE);
assert!(!GI::IMPLS_ITERATOR);
assert!(!GI::IMPLS_DOUBLE_ENDED_ITERATOR);
assert!(!GI::IMPLS_FMT_WRITE);
assert!(!GI::IMPLS_IO_WRITE);
assert!(!GI::IMPLS_IO_SEEK);
assert!(!GI::IMPLS_IO_READ);
assert!(!GI::IMPLS_IO_BUF_READ);
assert!(!GI::IMPLS_ERROR);
}
impl<S> Display for Foo<S>
where
S: Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "l:{} r:{} name:'{}'", self.l, self.r, self.name,)
}
}
impl<'s, T> SerializeType<'s> for Foo<T>
where
T: Serialize,
{
type Interface = FooInterface;
fn serialize_impl(&'s self) -> Result<RString, RBoxError> {
match serde_json::to_string(self) {
Ok(v) => Ok(v.into_c()),
Err(e) => Err(RBoxError::new(e)),
}
}
}
impl<'s> SerializeProxyType<'s> for FooInterface {
type Proxy = RString;
}
impl<'a> DeserializeDyn<'a, VirtualFoo<'static>> for FooInterface {
type Proxy = RString;
fn deserialize_dyn(s: RString) -> Result<VirtualFoo<'static>, RBoxError> {
match ::serde_json::from_str::<Foo<String>>(&*s) {
Ok(x) => Ok(DynTrait::from_value(x)),
Err(e) => Err(RBoxError::new(e)),
}
}
}
type VirtualFoo<'a> = DynTrait<'a, RBox<()>, FooInterface>;
#[repr(C)]
#[derive(StableAbi)]
#[sabi(impl_InterfaceType(Send, Sync, Debug))]
struct DebugInterface;
#[test]
fn debug_interface_test() {
type GI = GetImpls<DynTraitBox<DebugInterface>>;
assert!(GI::IMPLS_SEND);
assert!(GI::IMPLS_SYNC);
assert!(!GI::IMPLS_UNPIN);
assert!(!GI::IMPLS_CLONE);
assert!(!GI::IMPLS_DISPLAY);
assert!(GI::IMPLS_DEBUG);
assert!(!GI::IMPLS_SERIALIZE);
assert!(!GI::IMPLS_EQ);
assert!(!GI::IMPLS_PARTIAL_EQ);
assert!(!GI::IMPLS_ORD);
assert!(!GI::IMPLS_PARTIAL_ORD);
assert!(!GI::IMPLS_HASH);
assert!(!GI::IMPLS_DESERIALIZE);
assert!(!GI::IMPLS_ITERATOR);
assert!(!GI::IMPLS_DOUBLE_ENDED_ITERATOR);
assert!(!GI::IMPLS_FMT_WRITE);
assert!(!GI::IMPLS_IO_WRITE);
assert!(!GI::IMPLS_IO_SEEK);
assert!(!GI::IMPLS_IO_READ);
assert!(!GI::IMPLS_IO_BUF_READ);
assert!(!GI::IMPLS_ERROR);
}
fn new_foo() -> Foo<String> {
Foo {
l: 1000,
r: 100,
name: "hello_world".into(),
}
}
fn new_wrapped() -> VirtualFoo<'static> {
DynTrait::from_value(new_foo())
}
#[test]
fn clone_test() {
let wrapped_expected = Foo::<String>::default().piped(DynTrait::<_, FooInterface>::from_value);
let wrapped = new_wrapped();
{
let cloned = wrapped.clone();
assert_eq!(wrapped, cloned);
assert_ne!(wrapped, wrapped_expected);
}
{
let reborrow = wrapped.reborrow();
let cloned = reborrow.clone();
assert_eq!(reborrow, cloned);
assert_ne!(wrapped, wrapped_expected);
}
}
#[test]
fn default_test() {
let concrete = Foo::<String>::default();
let wrapped = new_wrapped().default();
let wrapped_expected = Foo::<String>::default().piped(DynTrait::<_, FooInterface>::from_value);
{
assert_eq!(wrapped, wrapped_expected);
assert_eq!(wrapped.downcast_as::<Foo<String>>().unwrap(), &concrete);
assert_ne!(wrapped, new_wrapped());
}
{
let reborrow = wrapped.reborrow();
assert_eq!(reborrow, wrapped_expected);
assert_eq!(reborrow.downcast_as::<Foo<String>>().unwrap(), &concrete);
assert_ne!(reborrow, new_wrapped());
}
}
#[test]
fn fmt_test() {
let concrete = new_foo();
let mut wrapped = new_wrapped();
macro_rules! debug_test {
( $wrapped:ident ) => {{
assert_eq!(format!("{:?}", concrete), format!("{:?}", $wrapped),);
assert_eq!(format!("{:#?}", concrete), format!("{:#?}", $wrapped),);
assert_eq!(format!("{}", concrete), format!("{}", $wrapped),);
assert_eq!(format!("{:#}", concrete), format!("{:#}", $wrapped),);
}};
}
debug_test!(wrapped);
{
let reborrow = wrapped.reborrow();
debug_test!(reborrow);
}
{
let reborrow = wrapped.reborrow_mut();
debug_test!(reborrow);
}
}
pub const JSON_0: &str = r#"
{
"l":1000,
"r":10,
"name":"what the hell"
}
"#;
#[test]
fn deserialize_test() {
let json = JSON_0;
let json_ss = serde_json::to_string(json).unwrap();
let concrete = serde_json::from_str::<Foo<String>>(json).unwrap();
let wrapped = VirtualFoo::deserialize_from_proxy(json.into()).unwrap();
let wrapped = wrapped.reborrow();
let wrapped2 = serde_json::from_str::<VirtualFoo<'static>>(&json_ss).unwrap();
assert_eq!(
serde_json::from_str::<VirtualFoo<'static>>(json).map_err(drop),
Err(()),
);
assert_eq!(wrapped.downcast_as::<Foo<String>>().unwrap(), &concrete);
assert_eq!(wrapped2.downcast_as::<Foo<String>>().unwrap(), &concrete);
}
#[test]
fn serialize_test() {
let concrete = new_foo();
let mut wrapped = new_wrapped();
macro_rules! serialize_test {
( $wrapped:ident ) => {{
assert_eq!(
&*concrete.piped_ref(serde_json::to_string).unwrap(),
&*$wrapped.serialize_into_proxy().unwrap()
);
assert_eq!(
concrete
.piped_ref(serde_json::to_string)
.unwrap()
.piped_ref(serde_json::to_string)
.unwrap(),
$wrapped.piped_ref(serde_json::to_string).unwrap()
);
assert_eq!(
$wrapped
.serialize_into_proxy()
.unwrap()
.piped_ref(serde_json::to_string)
.unwrap(),
$wrapped.piped_ref(serde_json::to_string).unwrap()
);
}};
}
serialize_test!(wrapped);
{
let reborrow = wrapped.reborrow();
serialize_test!(reborrow);
}
{
let reborrow = wrapped.reborrow_mut();
serialize_test!(reborrow);
}
}
#[test]
fn cmp_test() {
macro_rules! cmp_test {
(
wrapped_0=$wrapped_0:ident,
wrapped_1=$wrapped_1:ident,
wrapped_2=$wrapped_2:ident,
) => {{
assert_eq!($wrapped_1 == $wrapped_0, false);
assert_eq!($wrapped_1 <= $wrapped_0, false);
assert_eq!($wrapped_1 >= $wrapped_0, true);
assert_eq!($wrapped_1 < $wrapped_0, false);
assert_eq!($wrapped_1 > $wrapped_0, true);
assert_eq!($wrapped_1 != $wrapped_0, true);
assert_eq!($wrapped_1.partial_cmp(&$wrapped_0), Some(Ordering::Greater));
assert_eq!($wrapped_1.cmp(&$wrapped_0), Ordering::Greater);
assert_eq!($wrapped_1.eq(&$wrapped_0), false);
assert_eq!($wrapped_1.ne(&$wrapped_0), true);
assert_eq!($wrapped_1 == $wrapped_1, true);
assert_eq!($wrapped_1 <= $wrapped_1, true);
assert_eq!($wrapped_1 >= $wrapped_1, true);
assert_eq!($wrapped_1 < $wrapped_1, false);
assert_eq!($wrapped_1 > $wrapped_1, false);
assert_eq!($wrapped_1 != $wrapped_1, false);
assert_eq!($wrapped_1.partial_cmp(&$wrapped_1), Some(Ordering::Equal));
assert_eq!($wrapped_1.cmp(&$wrapped_1), Ordering::Equal);
assert_eq!($wrapped_1.eq(&$wrapped_1), true);
assert_eq!($wrapped_1.ne(&$wrapped_1), false);
assert_eq!($wrapped_1 == $wrapped_2, false);
assert_eq!($wrapped_1 <= $wrapped_2, true);
assert_eq!($wrapped_1 >= $wrapped_2, false);
assert_eq!($wrapped_1 < $wrapped_2, true);
assert_eq!($wrapped_1 > $wrapped_2, false);
assert_eq!($wrapped_1 != $wrapped_2, true);
assert_eq!($wrapped_1.partial_cmp(&$wrapped_2), Some(Ordering::Less));
assert_eq!($wrapped_1.cmp(&$wrapped_2), Ordering::Less);
assert_eq!($wrapped_1.eq(&$wrapped_2), false);
assert_eq!($wrapped_1.ne(&$wrapped_2), true);
}};
}
let mut wrapped_0 = new_foo()
.mutated(|x| x.l -= 100)
.piped(DynTrait::<_, FooInterface>::from_value);
let mut wrapped_1 = new_wrapped();
let mut wrapped_2 = new_foo()
.mutated(|x| x.l += 100)
.piped(DynTrait::<_, FooInterface>::from_value);
cmp_test! {
wrapped_0=wrapped_0,
wrapped_1=wrapped_1,
wrapped_2=wrapped_2,
}
{
let reborrow_0 = wrapped_0.reborrow();
let reborrow_1 = wrapped_1.reborrow();
let reborrow_2 = wrapped_2.reborrow();
cmp_test! {
wrapped_0=reborrow_0,
wrapped_1=reborrow_1,
wrapped_2=reborrow_2,
}
}
{
let reborrow_0 = wrapped_0.reborrow_mut();
let reborrow_1 = wrapped_1.reborrow_mut();
let reborrow_2 = wrapped_2.reborrow_mut();
cmp_test! {
wrapped_0=reborrow_0,
wrapped_1=reborrow_1,
wrapped_2=reborrow_2,
}
}
}
#[test]
fn hash_test() {
fn hash_value<H: Hash>(v: &H) -> u64 {
let mut hasher = DefaultHasher::new();
v.hash(&mut hasher);
hasher.finish()
}
{
let mut wrapped = new_wrapped();
assert_eq!(hash_value(&new_foo()), hash_value(&wrapped));
{
let reborrow = wrapped.reborrow();
assert_eq!(hash_value(&new_foo()), hash_value(&reborrow));
}
{
let reborrow_mut = wrapped.reborrow_mut();
assert_eq!(hash_value(&new_foo()), hash_value(&reborrow_mut));
}
}
{
let concrete = Foo::<String>::default();
let hash_concrete = hash_value(&concrete);
let hash_wrapped = hash_value(&DynTrait::from_value(concrete).interface(FooInterface));
assert_eq!(hash_concrete, hash_wrapped);
}
}
#[test]
fn to_any_test() {
let mut wrapped = DynTrait::from_value(new_foo()).interface(FooInterface);
macro_rules! to_unerased {
( $wrapped:expr ; $method:ident ; $expected:expr ) => {
assert_eq!($wrapped.$method::<Foo<RString>>().map_err(drop), Err(()));
assert_eq!($wrapped.$method::<Foo<String>>().unwrap(), $expected);
};
}
to_unerased!( wrapped.clone() ; downcast_into ; RBox::new(new_foo()) );
to_unerased!( wrapped ; downcast_as ; &new_foo() );
to_unerased!( wrapped ; downcast_as_mut ; &mut new_foo() );
{
to_unerased!(wrapped.reborrow_mut() ; downcast_into ; RMut::new(&mut new_foo()));
to_unerased!( wrapped.reborrow_mut() ; downcast_as ; &new_foo() );
to_unerased!( wrapped.reborrow_mut() ; downcast_as_mut ; &mut new_foo() );
}
{
to_unerased!( wrapped.reborrow() ; downcast_into ; RRef::new(&new_foo()) );
to_unerased!( wrapped.reborrow() ; downcast_as ; &new_foo() );
}
}
mod borrowing {
use super::*;
#[derive(
Default, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize,
)]
struct Foo<'a> {
l: u32,
r: u32,
name: &'a str,
}
impl<'a> Foo<'a> {
pub fn new(name: &'a str) -> Self {
Self { l: 0, r: 0, name }
}
}
#[repr(C)]
#[derive(StableAbi)]
#[sabi(impl_InterfaceType(
Send,
Sync,
Unpin,
Clone,
Default,
Display,
Debug,
Serialize,
Deserialize,
Hash
))]
struct FooInterface;
#[test]
fn foo_interface_test() {
type GI = GetImpls<DynTraitBox<FooInterface>>;
assert!(GI::IMPLS_SEND);
assert!(GI::IMPLS_SYNC);
assert!(GI::IMPLS_UNPIN);
assert!(GI::IMPLS_CLONE);
assert!(GI::IMPLS_DISPLAY);
assert!(GI::IMPLS_DEBUG);
assert!(GI::IMPLS_SERIALIZE);
assert!(!GI::IMPLS_EQ);
assert!(!GI::IMPLS_PARTIAL_EQ);
assert!(!GI::IMPLS_ORD);
assert!(!GI::IMPLS_PARTIAL_ORD);
assert!(GI::IMPLS_HASH);
assert!(GI::IMPLS_DESERIALIZE);
assert!(!GI::IMPLS_ITERATOR);
assert!(!GI::IMPLS_DOUBLE_ENDED_ITERATOR);
assert!(!GI::IMPLS_FMT_WRITE);
assert!(!GI::IMPLS_IO_WRITE);
assert!(!GI::IMPLS_IO_SEEK);
assert!(!GI::IMPLS_IO_READ);
assert!(!GI::IMPLS_IO_BUF_READ);
assert!(!GI::IMPLS_ERROR);
}
impl<'s> SerializeProxyType<'s> for FooInterface {
type Proxy = RString;
}
impl<'a> Display for Foo<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "l:{} r:{} name:'", self.l, self.r)?;
Display::fmt(&self.name, f)?;
writeln!(f, "'")?;
Ok(())
}
}
impl<'a, 's> SerializeType<'s> for Foo<'a> {
type Interface = FooInterface;
fn serialize_impl(&self) -> Result<RString, RBoxError> {
match serde_json::to_string(self) {
Ok(v) => Ok(v.into_c()),
Err(e) => Err(RBoxError::new(e)),
}
}
}
impl<'borr> DeserializeDyn<'borr, VirtualFoo<'borr>> for FooInterface {
type Proxy = RStr<'borr>;
fn deserialize_dyn(s: RStr<'borr>) -> Result<VirtualFoo<'borr>, RBoxError> {
match ::serde_json::from_str::<Foo<'borr>>(s.as_str()) {
Ok(x) => Ok(DynTrait::from_borrowing_value(x).interface(FooInterface)),
Err(e) => Err(RBoxError::new(e)),
}
}
}
type VirtualFoo<'a> = DynTrait<'a, RBox<()>, FooInterface>;
fn check_fmt<'a>(foo: &Foo<'a>, wrapped: &VirtualFoo<'a>) {
assert_eq!(format!("{:?}", wrapped), format!("{:?}", foo));
assert_eq!(format!("{:#?}", wrapped), format!("{:#?}", foo));
assert_eq!(format!("{}", wrapped), format!("{}", foo));
assert_eq!(format!("{:#}", wrapped), format!("{:#}", foo));
}
#[test]
fn cloning() {
let name = "hello".to_string();
let foo: Foo<'_> = Foo::new(&name);
let wrapped = DynTrait::from_borrowing_value(foo.clone()).interface(FooInterface);
let cloned = wrapped.clone();
check_fmt(&foo, &cloned);
}
#[test]
fn default() {
let name = "hello".to_string();
let foo: Foo<'_> = Foo::new(&name);
let default_name = "".to_string();
let default_foo = Foo::new(&default_name);
assert_eq!(default_foo, Default::default());
let wrapped = DynTrait::from_borrowing_value(foo.clone()).interface(FooInterface);
let default_wrapped = wrapped.default();
check_fmt(&default_foo, &default_wrapped);
}
#[test]
fn formatting() {
let name = "hello".to_string();
let foo: Foo<'_> = Foo::new(&name);
let wrapped = DynTrait::from_borrowing_value(foo.clone()).interface(FooInterface);
check_fmt(&foo, &wrapped);
}
#[test]
fn serialize() {
let name = "hello".to_string();
let foo: Foo<'_> = Foo::new(&name);
let wrapped = DynTrait::from_borrowing_value(foo.clone()).interface(FooInterface);
assert_eq!(
&*serde_json::to_string(&foo).unwrap(),
&*wrapped.serialize_into_proxy().unwrap(),
);
}
#[test]
fn deserialize() {
let list: Vec<String> = vec![JSON_0.to_string()];
for str_ in list.iter().map(|s| s.as_str()) {
let foo: Foo<'_> = serde_json::from_str(str_).unwrap();
let wrapped = VirtualFoo::deserialize_from_proxy(str_.into()).unwrap();
check_fmt(&foo, &wrapped);
}
}
#[test]
fn hash() {
let name = "hello".to_string();
let foo: Foo<'_> = Foo::new(&name);
let wrapped = DynTrait::from_borrowing_value(foo.clone()).interface(FooInterface);
assert_eq!(HashedBytes::new(&foo), HashedBytes::new(&wrapped),);
}
#[derive(Debug, Default, PartialEq)]
pub struct HashedBytes {
bytes: Vec<u8>,
}
impl HashedBytes {
pub fn new<T>(value: &T) -> Self
where
T: Hash,
{
let mut this = Self { bytes: Vec::new() };
value.hash(&mut this);
this
}
}
impl Hasher for HashedBytes {
fn write(&mut self, bytes: &[u8]) {
self.bytes.extend_from_slice(bytes);
}
fn finish(&self) -> u64 {
0
}
}
#[repr(C)]
#[derive(StableAbi)]
#[sabi(impl_InterfaceType(Send, Sync, DoubleEndedIterator))]
struct IterInterface;
impl<'a> IteratorItem<'a> for IterInterface {
type Item = &'a str;
}
fn iterator_from_lines(s: &str) -> DynTrait<'_, RBox<()>, IterInterface> {
let lines = s.lines().collect::<Vec<&str>>();
DynTrait::from_borrowing_value(lines.into_iter())
}
fn exact_size_hint(n: usize) -> (usize, Option<usize>) {
(n, Some(n))
}
#[test]
fn iter_interface_test() {
type GI = GetImpls<DynTraitBox<IterInterface>>;
assert!(GI::IMPLS_SEND);
assert!(GI::IMPLS_SYNC);
assert!(!GI::IMPLS_UNPIN);
assert!(!GI::IMPLS_CLONE);
assert!(!GI::IMPLS_DISPLAY);
assert!(!GI::IMPLS_DEBUG);
assert!(!GI::IMPLS_SERIALIZE);
assert!(!GI::IMPLS_EQ);
assert!(!GI::IMPLS_PARTIAL_EQ);
assert!(!GI::IMPLS_ORD);
assert!(!GI::IMPLS_PARTIAL_ORD);
assert!(!GI::IMPLS_HASH);
assert!(!GI::IMPLS_DESERIALIZE);
assert!(GI::IMPLS_ITERATOR);
assert!(GI::IMPLS_DOUBLE_ENDED_ITERATOR);
assert!(!GI::IMPLS_FMT_WRITE);
assert!(!GI::IMPLS_IO_WRITE);
assert!(!GI::IMPLS_IO_SEEK);
assert!(!GI::IMPLS_IO_READ);
assert!(!GI::IMPLS_IO_BUF_READ);
assert!(!GI::IMPLS_ERROR);
}
#[test]
fn iterator_collect() {
let s = "line0\nline1\nline2".to_string();
let actual = iterator_from_lines(&s).collect::<Vec<&str>>();
let expected = vec!["line0", "line1", "line2"];
assert_eq!(actual, expected);
}
#[test]
fn iterator_next() {
let s = "line0\nline1\nline2".to_string();
let mut iter = iterator_from_lines(&s);
assert_eq!(iter.size_hint(), exact_size_hint(3));
assert_eq!(iter.next(), Some("line0"));
assert_eq!(iter.size_hint(), exact_size_hint(2));
assert_eq!(iter.next(), Some("line1"));
assert_eq!(iter.size_hint(), exact_size_hint(1));
assert_eq!(iter.next(), Some("line2"));
assert_eq!(iter.size_hint(), exact_size_hint(0));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), exact_size_hint(0));
}
#[test]
fn iterator_nth() {
let s = "line0\nline1\nline2".to_string();
assert_eq!(iterator_from_lines(&s).nth(0), Some("line0"));
assert_eq!(iterator_from_lines(&s).nth(1), Some("line1"));
assert_eq!(iterator_from_lines(&s).nth(2), Some("line2"));
assert_eq!(iterator_from_lines(&s).nth(3), None);
}
#[test]
fn iterator_count() {
let s = "line0\nline1\nline2".to_string();
assert_eq!(iterator_from_lines(&s).count(), 3);
assert_eq!(iterator_from_lines(&s).skip(0).count(), 3);
assert_eq!(iterator_from_lines(&s).skip(1).count(), 2);
assert_eq!(iterator_from_lines(&s).skip(2).count(), 1);
assert_eq!(iterator_from_lines(&s).skip(3).count(), 0);
assert_eq!(iterator_from_lines(&s).skip(4).count(), 0);
}
#[test]
fn iterator_last() {
let s0 = "line0".to_string();
let s1 = "line0\nline1".to_string();
let s2 = "line0\nline1\nline2".to_string();
assert_eq!(iterator_from_lines(&s0).last(), Some("line0"));
assert_eq!(iterator_from_lines(&s1).last(), Some("line1"));
assert_eq!(iterator_from_lines(&s2).last(), Some("line2"));
}
#[test]
fn iterator_skip_eager() {
let s = "line0\nline1\nline2".to_string();
let skipping = |how_many: usize| {
let mut iter = iterator_from_lines(&s);
iter.skip_eager(how_many);
iter
};
assert_eq!(skipping(0).next(), Some("line0"));
assert_eq!(skipping(0).count(), 3);
assert_eq!(skipping(1).next(), Some("line1"));
assert_eq!(skipping(1).count(), 2);
assert_eq!(skipping(2).next(), Some("line2"));
assert_eq!(skipping(2).count(), 1);
assert_eq!(skipping(3).next(), None);
assert_eq!(skipping(3).count(), 0);
}
#[test]
fn iterator_extending_rvec() {
let s = "line0\nline1\nline2".to_string();
let collected =
|how_many: Option<usize>| s.lines().take(how_many.unwrap_or(!0)).collect::<RVec<_>>();
let extending = |how_many: ROption<usize>| {
let mut iter = iterator_from_lines(&s);
let mut buffer = RVec::new();
iter.extending_rvec(&mut buffer, how_many);
buffer
};
assert_eq!(extending(RNone), collected(None));
assert_eq!(extending(RSome(0)), collected(Some(0)));
assert_eq!(extending(RSome(1)), collected(Some(1)));
assert_eq!(extending(RSome(2)), collected(Some(2)));
assert_eq!(extending(RSome(3)), collected(Some(3)));
}
#[test]
fn iterator_next_back() {
let s = "line0\nline1\nline2".to_string();
let mut iter = iterator_from_lines(&s);
assert_eq!(iter.size_hint(), exact_size_hint(3));
assert_eq!(iter.next_back(), Some("line2"));
assert_eq!(iter.size_hint(), exact_size_hint(2));
assert_eq!(iter.next_back(), Some("line1"));
assert_eq!(iter.size_hint(), exact_size_hint(1));
assert_eq!(iter.next_back(), Some("line0"));
assert_eq!(iter.size_hint(), exact_size_hint(0));
assert_eq!(iter.next_back(), None);
assert_eq!(iter.size_hint(), exact_size_hint(0));
}
#[test]
fn iterator_nth_back() {
let s = "line0\nline1\nline2".to_string();
assert_eq!(iterator_from_lines(&s).nth_back_(0), Some("line2"));
assert_eq!(iterator_from_lines(&s).nth_back_(1), Some("line1"));
assert_eq!(iterator_from_lines(&s).nth_back_(2), Some("line0"));
assert_eq!(iterator_from_lines(&s).nth_back_(3), None);
}
#[test]
fn iterator_extending_rvec_back() {
let s = "line0\nline1\nline2".to_string();
let collected = |how_many: Option<usize>| {
s.lines()
.rev()
.take(how_many.unwrap_or(!0))
.collect::<RVec<_>>()
};
let extending = |how_many: ROption<usize>| {
let mut iter = iterator_from_lines(&s);
let mut buffer = RVec::new();
iter.extending_rvec_back(&mut buffer, how_many);
buffer
};
assert_eq!(extending(RNone), collected(None));
assert_eq!(extending(RSome(0)), collected(Some(0)));
assert_eq!(extending(RSome(1)), collected(Some(1)));
assert_eq!(extending(RSome(2)), collected(Some(2)));
assert_eq!(extending(RSome(3)), collected(Some(3)));
}
#[test]
fn is_same_type() {
let value: String = "hello".to_string();
let wrapped = DynTrait::from_borrowing_value(value.clone()).interface(());
let wrapped = wrapped.reborrow();
let dbg_wrapped = DynTrait::from_borrowing_value(value).interface(DebugInterface);
assert!(!wrapped.sabi_is_same_type(&dbg_wrapped));
}
#[test]
fn unerase_should_not_work() {
let value: &str = "hello";
macro_rules! to_unerased {
( $wrapped:expr ; $( $method:ident ),* $(,)* ) => (
$(
assert_eq!(
$wrapped.$method ::<String>().map_err(drop),
Err(())
);
)*
)
}
to_unerased!(
DynTrait::from_borrowing_value(value.to_string()).interface(());
downcast_into,
);
to_unerased!(
DynTrait::from_borrowing_value(value.to_string()).interface(());
downcast_as,
downcast_as_mut,
);
}
#[repr(C)]
#[derive(StableAbi)]
#[sabi(impl_InterfaceType(Send, Sync, FmtWrite))]
struct FmtInterface;
#[test]
fn fmt_interface_test() {
type GI = GetImpls<DynTraitBox<FmtInterface>>;
assert!(GI::IMPLS_SEND);
assert!(GI::IMPLS_SYNC);
assert!(!GI::IMPLS_UNPIN);
assert!(!GI::IMPLS_CLONE);
assert!(!GI::IMPLS_DISPLAY);
assert!(!GI::IMPLS_DEBUG);
assert!(!GI::IMPLS_SERIALIZE);
assert!(!GI::IMPLS_EQ);
assert!(!GI::IMPLS_PARTIAL_EQ);
assert!(!GI::IMPLS_ORD);
assert!(!GI::IMPLS_PARTIAL_ORD);
assert!(!GI::IMPLS_HASH);
assert!(!GI::IMPLS_DESERIALIZE);
assert!(!GI::IMPLS_ITERATOR);
assert!(!GI::IMPLS_DOUBLE_ENDED_ITERATOR);
assert!(GI::IMPLS_FMT_WRITE);
assert!(!GI::IMPLS_IO_WRITE);
assert!(!GI::IMPLS_IO_SEEK);
assert!(!GI::IMPLS_IO_READ);
assert!(!GI::IMPLS_IO_BUF_READ);
assert!(!GI::IMPLS_ERROR);
}
#[test]
fn fmt_write() {
use std::fmt::Write;
let mut s = String::new();
{
let mut wrapped = DynTrait::from_ptr(&mut s).interface(FmtInterface);
let mut wrapped = wrapped.reborrow_mut();
wrapped.write_char('¿').unwrap();
wrapped.write_str("Hello").unwrap();
wrapped.write_char('?').unwrap();
}
assert_eq!(&*s, "¿Hello?");
}
#[repr(C)]
#[derive(StableAbi)]
#[sabi(impl_InterfaceType(Send, Sync, IoWrite, IoSeek, IoRead, IoBufRead))]
struct IoInterface;
#[test]
fn io_write() {
use std::io::{Cursor, Write};
const FILLER: u8 = 255;
let mut buff = vec![FILLER; 9];
let mut buff = buff[..].piped_mut(Cursor::new);
{
let mut wrapped = DynTrait::from_borrowing_ptr(&mut buff).interface(IoInterface);
assert_eq!(wrapped.write(&[0, 1]).map_err(drop), Ok(2));
wrapped.write_all(&[2, 3, 4, 5]).unwrap();
}
assert_eq!(
&**buff.get_ref(),
&[0, 1, 2, 3, 4, 5, FILLER, FILLER, FILLER][..]
);
{
let mut wrapped = DynTrait::from_borrowing_ptr(&mut buff).interface(IoInterface);
wrapped
.write_all(&[2, 3, 4, 5, 6, 7, 8, 9, 10])
.unwrap_err();
wrapped.flush().unwrap();
}
}
#[test]
fn io_read() {
use std::io::{Cursor, Read};
let mut buff = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].piped(Cursor::new);
let mut out = vec![0; 400];
let mut wrapped = DynTrait::from_ptr(&mut buff).interface(IoInterface);
assert_eq!(wrapped.read(&mut out[..3]).map_err(drop), Ok(3));
assert_eq!(&out[..3], &[1, 2, 3][..]);
assert_eq!(wrapped.read_exact(&mut out[4..8]).map_err(drop), Ok(()));
assert_eq!(&out[4..8], &[4, 5, 6, 7][..]);
assert_eq!(wrapped.read_exact(&mut out[8..]).map_err(drop), Err(()));
}
#[repr(C)]
#[derive(StableAbi)]
#[sabi(impl_InterfaceType(Send, Sync, IoRead, IoBufRead))]
struct IoBufReadInterface;
#[test]
fn io_buf_read_interface_test() {
type GI = GetImpls<DynTraitBox<IoBufReadInterface>>;
assert!(GI::IMPLS_SEND);
assert!(GI::IMPLS_SYNC);
assert!(!GI::IMPLS_UNPIN);
assert!(!GI::IMPLS_CLONE);
assert!(!GI::IMPLS_DISPLAY);
assert!(!GI::IMPLS_DEBUG);
assert!(!GI::IMPLS_SERIALIZE);
assert!(!GI::IMPLS_EQ);
assert!(!GI::IMPLS_PARTIAL_EQ);
assert!(!GI::IMPLS_ORD);
assert!(!GI::IMPLS_PARTIAL_ORD);
assert!(!GI::IMPLS_HASH);
assert!(!GI::IMPLS_DESERIALIZE);
assert!(!GI::IMPLS_ITERATOR);
assert!(!GI::IMPLS_DOUBLE_ENDED_ITERATOR);
assert!(!GI::IMPLS_FMT_WRITE);
assert!(!GI::IMPLS_IO_WRITE);
assert!(!GI::IMPLS_IO_SEEK);
assert!(GI::IMPLS_IO_READ);
assert!(GI::IMPLS_IO_BUF_READ);
assert!(!GI::IMPLS_ERROR);
}
#[test]
fn io_bufread() {
use std::io::{BufRead, Cursor};
let s = "line0\nline1\nline2".as_bytes().piped(Cursor::new);
let wrapped = DynTrait::<_, IoBufReadInterface>::from_borrowing_value(s);
assert_eq!(
wrapped.lines().collect::<Result<Vec<String>, _>>().unwrap(),
vec![
"line0".to_string(),
"line1".to_string(),
"line2".to_string(),
]
);
}
#[test]
fn io_seek() {
use std::io::{Cursor, Read, Seek, SeekFrom};
let mut buff = vec![255, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].piped(Cursor::new);
let mut out = vec![0; 400];
let mut wrapped = DynTrait::from_ptr(&mut buff).interface(IoInterface);
{
wrapped.seek(SeekFrom::Start(1)).unwrap();
assert_eq!(wrapped.read_exact(&mut out[..4]).map_err(drop), Ok(()));
assert_eq!(&out[..4], &[1, 2, 3, 4][..]);
}
{
wrapped.seek(SeekFrom::End(-3)).unwrap();
assert_eq!(wrapped.read_exact(&mut out[4..7]).map_err(drop), Ok(()));
assert_eq!(&out[..7], &[1, 2, 3, 4, 8, 9, 10][..]);
}
{
wrapped.seek(SeekFrom::Current(-4)).unwrap();
assert_eq!(wrapped.read_exact(&mut out[7..8]).map_err(drop), Ok(()));
assert_eq!(&out[..8], &[1, 2, 3, 4, 8, 9, 10, 7][..]);
}
}
}