mod common;
use common::*;
#[cfg(feature = "alloc")]
#[test]
fn vecm_empty() {
use xdrs::*;
let val: VecM<u32> = VecM::default();
CXS::check_codec(&val, &hex!("00"));
TXS::check_codec(&val, &hex!("00000000"));
}
#[cfg(feature = "alloc")]
#[test]
fn vecm_full() {
use xdrs::*;
let val: VecM<u32> = VecM(vec![1]);
CXS::check_codec(&val, &hex!("0101"));
TXS::check_codec(&val, &hex!("0000000100000001"));
}
#[cfg(feature = "alloc")]
#[test]
fn stringm_full() {
use xdrs::*;
let val: StringM<10> = StringM("hello".as_bytes().into());
CXS::check_codec(&val, &hex!("0568656c6c6f"));
TXS::check_codec(&val, &hex!("0000000568656c6c6f000000"));
}
#[cfg(feature = "alloc")]
#[test]
fn vec_in_struct() {
use xdrs::*;
#[derive(Debug, PartialEq, Eq, xdrs::ReadXDR, xdrs::WriteXDR)]
#[repr(C)]
struct Two {
pub a: Vec<u8>,
pub b: bool,
}
let val = Two {
a: Vec::default(),
b: true,
};
CXS::check_decode(&val, &hex!("0001"));
TXS::check_codec(&val, &hex!("0000000000000001"));
}
#[test]
fn slice_in_struct() {
let arr: [u8; 0] = [];
let buf = &arr[..];
#[derive(Debug, PartialEq, Eq, xdrs::WriteXDR, xdrs::ReadXDR)]
#[repr(C)]
struct Two<'a> {
pub a: &'a [u8],
pub b: bool,
}
let val = Two { a: buf, b: true };
CXS::check_codec(&val, &hex!("0001"));
TXS::check_codec(&val, &hex!("0000000000000001"));
}
#[cfg(feature = "alloc")]
#[test]
fn vec_in_tuple() {
use xdrs::*;
let val = (Vec::<u32>::default(), true);
CXS::check_encode(&val, &hex!("0001"));
CXS::check_decode(&val, &hex!("0001"));
}
#[cfg(feature = "alloc")]
#[test]
fn recursive_struct() {
use xdrs::*;
#[derive(Debug, PartialEq, Eq, xdrs::WriteXDR, xdrs::ReadXDR)]
#[repr(C)]
struct Recursive {
pub elem: BytesM,
pub nextvec: VecM<Recursive>,
}
let val = Recursive {
elem: BytesM("hello".as_bytes().into()),
nextvec: VecM::default(),
};
CXS::check_codec(&val, &hex!("0568656c6c6f00"));
TXS::check_codec(&val, &hex!("0000000568656c6c6f00000000000000"));
}
#[cfg(feature = "alloc")]
#[test]
fn recursive_struct_box() {
use xdrs::*;
#[derive(Debug, PartialEq, Eq, xdrs::WriteXDR, xdrs::ReadXDR)]
#[repr(C)]
struct Recursive {
pub elem: BytesM,
pub next: Option<Box<Recursive>>,
}
let val = Recursive {
elem: BytesM("hello".as_bytes().into()),
next: None,
};
CXS::check_codec(&val, &hex!("0568656c6c6f00"));
TXS::check_codec(&val, &hex!("0000000568656c6c6f00000000000000"));
}
#[test]
fn option_test() {
let x: Option<i32> = None;
let y: Option<i32> = Some(1);
CXS::check_codec(&x, &hex!("00"));
TXS::check_codec(&x, &hex!("00000000"));
CXS::check_codec(&y, &hex!("0101"));
TXS::check_codec(&y, &hex!("0000000100000001"));
}
#[cfg(feature = "alloc")]
#[test]
fn option_box_test() {
let x: Option<Box<i32>> = None;
let y: Option<Box<i32>> = Some(Box::new(1));
CXS::check_codec(&x, &hex!("00"));
TXS::check_codec(&x, &hex!("00000000"));
CXS::check_codec(&y, &hex!("0101"));
TXS::check_codec(&y, &hex!("0000000100000001"));
}
#[cfg(feature = "alloc")]
#[test]
fn bytesm_rejects_overlength() {
use xdrs::*;
let buf = hex!("000000040102030400000000");
let err = xdrs::txs::decode::<BytesM<3>>(&buf).unwrap_err();
assert!(matches!(err, ReadError::MaxLengthExceeded));
}
#[cfg(feature = "alloc")]
#[test]
fn bytesm_accepts_at_max() {
use xdrs::*;
let buf = hex!("0000000301020300");
let val: BytesM<3> = xdrs::txs::decode(&buf).unwrap();
assert_eq!(&*val.0, &[1, 2, 3]);
}
#[cfg(feature = "alloc")]
#[test]
fn stringm_rejects_overlength() {
use xdrs::*;
let buf = hex!("0000000568656c6c6f000000");
let err = xdrs::txs::decode::<StringM<4>>(&buf).unwrap_err();
assert!(matches!(err, ReadError::MaxLengthExceeded));
}
#[cfg(feature = "alloc")]
#[test]
fn stringm_accepts_at_max() {
use xdrs::*;
let buf = hex!("0000000568656c6c6f000000");
let val: StringM<5> = xdrs::txs::decode(&buf).unwrap();
assert_eq!(&*val.0, b"hello");
}
#[cfg(feature = "alloc")]
#[test]
fn vecm_u8_rejects_overlength() {
use xdrs::*;
let buf = hex!("0000000301020300");
let err = xdrs::txs::decode::<VecM<u8, 2>>(&buf).unwrap_err();
assert!(matches!(err, ReadError::MaxLengthExceeded));
}
#[cfg(feature = "alloc")]
#[test]
fn vecm_u8_accepts_at_max() {
use xdrs::*;
let buf = hex!("0000000301020300");
let val: VecM<u8, 3> = xdrs::txs::decode(&buf).unwrap();
assert_eq!(&*val.0, &[1, 2, 3]);
}
#[cfg(feature = "alloc")]
#[test]
fn vecm_generic_rejects_overlength() {
use xdrs::*;
let buf = hex!("00000003000000010000000200000003");
let err = xdrs::txs::decode::<VecM<u32, 2>>(&buf).unwrap_err();
assert!(matches!(err, ReadError::MaxLengthExceeded));
}
#[cfg(feature = "alloc")]
#[test]
fn vecm_generic_rejects_huge_length_without_allocating() {
use xdrs::*;
let buf = hex!("7FFFFFFF");
let err = xdrs::txs::decode::<VecM<u32, 2>>(&buf).unwrap_err();
assert!(matches!(err, ReadError::MaxLengthExceeded));
}
#[cfg(feature = "alloc")]
#[test]
fn vecm_generic_accepts_at_max() {
use xdrs::*;
let buf = hex!("00000003000000010000000200000003");
let val: VecM<u32, 3> = xdrs::txs::decode(&buf).unwrap();
assert_eq!(&*val.0, &[1u32, 2, 3]);
}
#[cfg(feature = "alloc")]
#[test]
fn bare_vec_rejects_huge_length_without_oom() {
use xdrs::*;
let buf = hex!("7FFFFFFF");
let err = xdrs::txs::decode::<Vec<u32>>(&buf).unwrap_err();
assert!(matches!(err, ReadError::SourceEmpty { .. }));
}
#[cfg(feature = "alloc")]
#[test]
fn vec_does_not_overconsume_from_wire() {
use xdrs::*;
let input: (Vec<u32>, u32) = (vec![1, 2, 3], 99);
let encoded = xdrs::txs::encode(&input).unwrap();
let decoded: (VecM<u32, 4>, u32) = xdrs::txs::decode(&encoded).unwrap();
let expected = VecM(vec![1u32, 2, 3]);
assert_eq!(decoded.0, expected);
assert_eq!(decoded.1, 99);
}
#[cfg(feature = "alloc")]
#[test]
fn arc_codec() {
use std::sync::Arc;
let val: Arc<u32> = Arc::new(7);
CXS::check_codec(&val, &hex!("07"));
TXS::check_codec(&val, &hex!("00000007"));
let val: Arc<Option<u32>> = Arc::new(Some(7));
TXS::check_codec(&val, &hex!("0000000100000007"));
}
#[cfg(feature = "alloc")]
#[test]
fn rc_decode() {
use std::rc::Rc;
let val: Rc<u32> = Rc::new(7);
CXS::check_decode(&val, &hex!("07"));
TXS::check_decode(&val, &hex!("00000007"));
let val: Rc<Vec<u32>> = Rc::new(vec![1, 2]);
TXS::check_decode(&val, &hex!("000000020000000100000002"));
}
#[cfg(feature = "alloc")]
#[test]
fn shared_pointers_borrow_from_input() {
use std::{rc::Rc, sync::Arc};
let buf = hex!("00000002abcd0000");
let a: Arc<&[u8]> = xdrs::txs::decode(&buf).unwrap();
let r: Rc<&[u8]> = xdrs::txs::decode(&buf).unwrap();
assert_eq!(*a, &[0xab, 0xcd][..]);
assert_eq!(*r, &[0xab, 0xcd][..]);
assert_eq!(a.as_ptr(), buf[4..6].as_ptr());
assert_eq!(r.as_ptr(), buf[4..6].as_ptr());
}
#[cfg(feature = "alloc")]
#[test]
fn shared_pointers_are_read_xdr_owned() {
use std::{rc::Rc, sync::Arc};
fn assert_owned<T: xdrs::ReadXDROwned>() {}
assert_owned::<Arc<u32>>();
assert_owned::<Rc<u32>>();
assert_owned::<Arc<Vec<Rc<u64>>>>();
}
#[cfg(feature = "alloc")]
#[test]
fn shared_pointers_in_struct() {
use std::{rc::Rc, sync::Arc};
#[derive(Debug, PartialEq, Eq, xdrs::ReadXDR, xdrs::WriteXDR)]
struct WithArc {
pub a: Arc<u32>,
pub b: Arc<Vec<u8>>,
}
let val = WithArc {
a: Arc::new(1),
b: Arc::new(vec![0xff]),
};
TXS::check_codec(&val, &hex!("0000000100000001ff000000"));
#[derive(Debug, PartialEq, Eq, xdrs::ReadXDR)]
struct WithRc {
pub a: Rc<u32>,
pub b: Rc<bool>,
}
let val = WithRc {
a: Rc::new(1),
b: Rc::new(true),
};
TXS::check_decode(&val, &hex!("0000000100000001"));
}