#![cfg(test)]
use core::char;
#[cfg(feature = "bstr")]
use alloc::boxed::Box;
#[cfg(feature = "bstr")]
use alloc::bstr::ByteString;
#[cfg(feature = "bstr")]
use alloc::rc::Rc;
#[cfg(feature = "bstr")]
use core::bstr::ByteStr;
#[cfg(feature = "bstr")]
use std::io::Cursor;
#[cfg(all(feature = "bstr", target_has_atomic = "ptr"))]
use alloc::sync::Arc;
#[cfg(feature = "proc_macro")]
use oct::serdes::Deserialise;
macro_rules! test {
{$( $Ty:ty { $($lhs:expr => $rhs:pat),+$(,)? }$(,)?)*} => {
$($({
let mut data: &[u8] = &$lhs;
let lhs = <$Ty as ::oct::serdes::Deserialise>::deserialise(&mut data);
#[allow(clippy::redundant_pattern_matching)]
if !matches!(lhs, $rhs) {
::core::panic!(
"deserialisation test failed: `{lhs:?}` does not match `{}`",
::core::stringify!($rhs),
);
}
})*)*
};
}
#[test]
fn test_deserialise() {
test! {
i8 {
[0x00] => Ok(0x00),
[0x7F] => Ok(0x7F),
[0x80] => Ok(-0x80),
[0xFF] => Ok(-0x01),
}
i16 {
[0x00, 0x00] => Ok(0x0000),
[0xFF, 0x7F] => Ok(0x7FFF),
[0x00, 0x80] => Ok(-0x8000),
[0xFF, 0xFF] => Ok(-0x0001),
}
i32 {
[0x00, 0x00, 0x00, 0x00] => Ok(0x00000000),
[0xFF, 0xFF, 0xFF, 0x7F] => Ok(0x7FFFFFFF),
[0x00, 0x00, 0x00, 0x80] => Ok(-0x80000000),
[0xFF, 0xFF, 0xFF, 0xFF] => Ok(-0x00000001),
}
i64 {
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] => Ok(0x0000000000000000),
[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F] => Ok(0x7FFFFFFFFFFFFFFF),
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80] => Ok(-0x8000000000000000),
[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] => Ok(-0x0000000000000001),
}
u128 {
[
0x7F, 0x8F, 0x6F, 0x9F, 0x5F, 0xAF, 0x4F, 0xBF,
0x3F, 0xCF, 0x2F, 0xDF, 0x1F, 0xEF, 0x0F, 0xFF,
] => Ok(0xFF_0F_EF_1F_DF_2F_CF_3F_BF_4F_AF_5F_9F_6F_8F_7F),
}
char {
[0xFD, 0xFF, 0x00, 0x00] => Ok(char::REPLACEMENT_CHARACTER),
}
[char; 0x5] {
[
0xBB, 0x03, 0x00, 0x00, 0x91, 0x03, 0x00, 0x00,
0xBC, 0x03, 0x00, 0x00, 0x94, 0x03, 0x00, 0x00,
0xB1, 0x03, 0x00, 0x00,
] => Ok(['\u{03BB}', '\u{0391}', '\u{03BC}', '\u{0394}', '\u{03B1}']),
}
Option<()> {
[0x00] => Ok(None),
[0x01] => Ok(Some(())),
}
Result<(), i8> {
[0x00, 0x00] => Ok(Ok(())),
[0x01, 0x7F] => Ok(Err(i8::MAX)),
}
}
}
#[cfg(feature = "bstr")]
#[test]
fn test_deserialise_bstr() {
let data = [
0x10, 0x00,
b'I',
b' ',
b'L',
b'O',
b'V',
b'E',
b' ',
b'Y',
b'O',
b'U',
b'!',
b'!',
b'!',
b' ',
b'<',
b'3',
];
let mut r = Cursor::new(&data);
assert_eq!(
ByteString::deserialise(&mut r).unwrap().0,
b"I LOVE YOU!!! <3",
);
r.set_position(0);
assert_eq!(
&Box::<ByteStr>::deserialise(&mut r).unwrap().0,
b"I LOVE YOU!!! <3",
);
r.set_position(0);
assert_eq!(
&Rc::<ByteStr>::deserialise(&mut r).unwrap().0,
b"I LOVE YOU!!! <3",
);
r.set_position(0);
#[cfg(target_has_atomic = "ptr")]
assert_eq!(
&Arc::<ByteStr>::deserialise(&mut r).unwrap().0,
b"I LOVE YOU!!! <3",
);
}
#[cfg(feature = "proc_macro")]
#[test]
fn test_derive_deserialise() {
#[derive(Debug, Deserialise, PartialEq)]
struct ProcExit {
exit_code: i32,
timestmap: u64,
}
#[derive(Debug, Deserialise, PartialEq)]
struct NewByte(u8);
#[derive(Debug, Deserialise, PartialEq)]
struct Unit;
#[derive(Debug, Deserialise, PartialEq)]
enum UnitOrFields {
Unit,
Unnamed(i32),
Named { timestamp: u64 },
}
test! {
ProcExit {
[
0x01, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x0B, 0x5E,
0x00, 0x00, 0x00, 0x00,
] => Ok(ProcExit { exit_code: 0x1, timestmap: 1577836800 }),
}
NewByte {
[0x80] => Ok(NewByte(0x80)),
}
Unit {
[] => Ok(Unit),
}
UnitOrFields {
[
0x00,
] => Ok(UnitOrFields::Unit),
[
0x01, 0xFF, 0xFF, 0xFF, 0xFF,
] => Ok(UnitOrFields::Unnamed(-1)),
[
0x02, 0x4C, 0xC8, 0xC5, 0x66, 0x00, 0x00, 0x00,
0x00,
] => Ok(UnitOrFields::Named { timestamp: 1724237900 }),
[
0x03,
] => Err(..),
}
}
}