use crossmist::{lambda, Deserializer, FnOnceObject, Object, Serializer}; use std::fmt::Debug; fn serde(x: &T) -> T { let mut s = Serializer::new(); s.serialize(x); let handles = s.drain_handles(); let data = s.into_vec(); let mut d = unsafe { Deserializer::new( data, handles .into_iter() .map(|fd| { #[cfg(unix)] let borrowed = std::os::fd::BorrowedFd::borrow_raw(fd); #[cfg(windows)] let borrowed = std::os::windows::io::BorrowedHandle::borrow_raw(fd.0 as _); borrowed.try_clone_to_owned().unwrap() }) .collect(), ) }; unsafe { d.deserialize() }.expect("Deserialization failed") } fn test_idempotency(x: T) { assert_eq!(serde(&x), x); } #[derive(Debug, PartialEq, Object)] struct SimplePair { x: i32, y: i32, } #[test] fn simple() { test_idempotency(0x123456789abcdefi64); } #[test] fn string() { test_idempotency("hello".to_string()); } #[test] fn complex_argument() { test_idempotency(SimplePair { x: 5, y: 7 }) } #[test] fn hole() { test_idempotency((1i32, 2u8, 3i32)) } #[test] fn boxed() { test_idempotency(Box::new(7)) } #[test] fn vec_and_box() { test_idempotency((vec![1, 2, 3], Box::new([4, 5, 6]))) } trait Trait: Object { fn say(&self) -> String; } #[derive(Object)] struct ImplA(String); #[derive(Object)] struct ImplB(i32); impl Trait for ImplA { fn say(&self) -> String { format!("ImplA says: {}", self.0) } } impl Trait for ImplB { fn say(&self) -> String { format!("ImplB says: {}", self.0) } } impl Trait for bool { fn say(&self) -> String { format!("bool says: {}", self) } } #[test] fn box_trait() { assert_eq!( serde(&(Box::new(ImplA("hello".to_string())) as Box)).say(), "ImplA says: hello" ); assert_eq!( serde(&(Box::new(ImplB(5)) as Box)).say(), "ImplB says: 5" ); assert_eq!( serde(&(Box::new(true) as Box)).say(), "bool says: true" ); } #[test] fn function() { let func: Box> = lambda! { |a: i32, b: i32| -> i32 { a + b } }; assert_eq!(serde(&func).call_object_box((5, 7)), 12); } #[test] fn bound_function() { let a = 5; let func: Box> = lambda! { move(a: i32) |b: i32| -> i32 { a + b } }; assert_eq!(serde(&func).call_object_box((7,)), 12); } #[test] fn double_bound_function() { let a = 5; let b = 7; let func: Box> = lambda! { move(a: i32, b: i32) || -> i32 { a + b } }; assert_eq!(serde(&func).call_object_box(()), 12); } #[test] #[cfg(not(miri))] fn test_rx() { let (mut tx, rx) = crossmist::channel::().unwrap(); let mut rx = serde(&rx); tx.send(&5).unwrap(); tx.send(&7).unwrap(); assert_eq!(rx.recv().unwrap().unwrap(), 5); assert_eq!(rx.recv().unwrap().unwrap(), 7); } #[test] #[cfg(not(miri))] fn test_tx() { let (tx, mut rx) = crossmist::channel::().unwrap(); let mut tx = serde(&tx); tx.send(&5).unwrap(); tx.send(&7).unwrap(); assert_eq!(rx.recv().unwrap().unwrap(), 5); assert_eq!(rx.recv().unwrap().unwrap(), 7); } #[test] #[cfg(not(miri))] fn test_duplex() { let (mut local, downstream) = crossmist::duplex::<(i32, i32), i32>().unwrap(); let mut downstream = serde(&downstream); for (x, y) in [(5, 7), (100, -1), (53, 2354)] { local.send(&(x, y)).unwrap(); let (x1, y1) = downstream.recv().unwrap().unwrap(); downstream.send(&(x1 - y1)).unwrap(); assert_eq!(local.recv().unwrap().unwrap(), x1 - y1); } drop(local); assert!(downstream.recv().unwrap().is_none()); }