oct 0.36.2

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

//! Tests for [`MaxSerialisedSize`].

#![allow(clippy::missing_docs_in_private_items)]
#![allow(clippy::missing_errors_doc)]

#![cfg(test)]

use oct::serdes::{MaxSerialisedSize, Serialise};

#[cfg(feature = "proc_macro")]
use core::mem::ManuallyDrop;

#[cfg(feature = "simd")]
use core::simd::{self, Simd};

#[cfg(feature = "proc_macro")]
#[test]
fn test_derive_max_serialised_size() {
	#[derive(MaxSerialisedSize)]
	struct StructUnit;

	#[derive(MaxSerialisedSize)]
	struct StructNamed {
		_raw_name: [u8; 16],

		_birthday: u64,
	}

	#[derive(MaxSerialisedSize)]
	struct StructUnnamed(
		#[expect(unused)]
		[f64; 6],
	);

	#[expect(unused)]
	#[derive(MaxSerialisedSize)]
	enum Enum {
		Unit,

		Named {
			named: StructNamed,
		},

		Unnamed(StructUnnamed),
	}

	#[derive(MaxSerialisedSize)]
	union Union<T: MaxSerialisedSize> {
		_null: ManuallyDrop<[T; 0]>,

		_single: ManuallyDrop<[T; 1]>,

		_double: ManuallyDrop<[T; 2]>,
	}

	assert_eq!(StructUnit::MAX_SERIALISED_SIZE,    0);
	assert_eq!(StructNamed::MAX_SERIALISED_SIZE,   24);
	assert_eq!(StructUnnamed::MAX_SERIALISED_SIZE, 48);
	assert_eq!(Enum::MAX_SERIALISED_SIZE,          49);
	assert_eq!(Union::<u128>::MAX_SERIALISED_SIZE, 32);
}

#[test]
fn test_max_serialised_size() {
	struct Test<const N: usize> {
		buf: [u8; N],
	}

	impl<const N: usize> Test<N> {
		#[must_use]
		pub fn new() -> Self {
			Self { buf: [0; N] }
		}

		#[must_use]
		fn serialised_size<T: Serialise>(&mut self, value: T) -> usize {
			let mut w = self.buf.as_mut_slice();

			value.serialise(&mut w).unwrap();

			let remaining = w.len();
			self.buf.len() - remaining
		}

		#[track_caller]
		fn assert_eq_serialised_size<T: Serialise + MaxSerialisedSize>(&mut self, value: T) {
			assert!(self.serialised_size(value) == T::MAX_SERIALISED_SIZE);
		}

		#[track_caller]
		fn assert_le_serialised_size<T: Serialise + MaxSerialisedSize>(&mut self, value: T) {
			assert!(self.serialised_size(value) <= T::MAX_SERIALISED_SIZE);
		}
	}

	let mut test = Test::<512>::new();

	test.assert_eq_serialised_size([u128::MAX; 32]);
	test.assert_eq_serialised_size([u16::MAX; 256]);
	test.assert_eq_serialised_size([u32::MAX; 128]);
	test.assert_eq_serialised_size([u64::MAX; 64]);
	test.assert_eq_serialised_size([u8::MAX; 0]);
	test.assert_eq_serialised_size([u8::MAX; 512]);
	test.assert_eq_serialised_size(true);
	test.assert_eq_serialised_size(char::MAX);
	test.assert_eq_serialised_size(f32::INFINITY);
	test.assert_eq_serialised_size(f64::INFINITY);
	test.assert_eq_serialised_size(i128::MAX);
	test.assert_eq_serialised_size(i16::MAX);
	test.assert_eq_serialised_size(i32::MAX);
	test.assert_eq_serialised_size(i64::MAX);
	test.assert_eq_serialised_size(i8::MAX);
	test.assert_le_serialised_size(Option::<i128>::None);
	test.assert_eq_serialised_size(Option::<i128>::Some(0));
	test.assert_eq_serialised_size(Option::<()>::None);
	test.assert_eq_serialised_size(Option::<()>::Some(()));
	test.assert_le_serialised_size(Result::<u8, u16>::Ok(0));
	test.assert_eq_serialised_size(Result::<u8, u16>::Err(0));
	test.assert_eq_serialised_size(Result::<(), ()>::Ok(()));
	test.assert_eq_serialised_size(Result::<(), ()>::Err(()));
	test.assert_eq_serialised_size(u128::MAX);
	test.assert_eq_serialised_size(u16::MAX);
	test.assert_eq_serialised_size(u32::MAX);
	test.assert_eq_serialised_size(u64::MAX);
	test.assert_eq_serialised_size(u8::MAX);

	#[cfg(feature = "f16")]
	test.assert_eq_serialised_size(f16::INFINITY);

	#[cfg(feature = "f128")]
	test.assert_eq_serialised_size(f128::INFINITY);

	#[cfg(feature = "simd")]
	test.assert_eq_serialised_size(simd::Mask::<i64, 64>::from_array([true; 64]));

	#[cfg(feature = "simd")]
	test.assert_eq_serialised_size(Simd::from_array([u64::MAX; 64]));
}