oct 0.34.0

Octonary transcodings.
Documentation
// Copyright 2024-2026 Gabriel Bjørnager Jensen.
//
// SPDX: MIT OR Apache-2.0

//! Tests for [`Deserialise`].

#![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(..),
		}
	}
}