looklook 0.5.0

Descriptive signal synthesiser.
// Copyright 2026 Gabriel Bjørnager Jensen.
//
// This file is part of LOOKLOOK.
//
// LOOKLOOK is free software: you can redistribute
// it and/or modify it under the terms of the GNU
// Affero General Public License as published by
// the Free Software Foundation, either version 3
// of the License, or (at your option) any later
// version.
//
// LOOKLOOK is distributed in the hope that it will
// be useful, but WITHOUT ANY WARRANTY; without
// even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Af-
// fero General Public License along with LOOKLOOK.
// If not, see <https://www.gnu.org/licenses/>.

//! The [`SampleDepth`] type.

mod test;

use std::fmt::{self, Debug, Display, Formatter};

/// A sampling depth.
#[repr(transparent)]
#[derive(Copy)]
#[derive_const(
	Clone,
	Eq,
	Ord,
	PartialEq,
	PartialOrd,
)]
pub struct SampleDepth(Inner);

impl SampleDepth {
	/// The minimum, supported sampling depth.
	pub const MIN: Self = Self(Inner::U8);

	/// The maximum, supported sampling depth.
	pub const MAX: Self = Self(Inner::U64);

	/// Constructs a new sampling depth value, measured
	/// in count of octets (bytes.)
	///
	/// If the provided value is zero or greater than
	/// `4`,  this constructor will return [`None`].
	#[inline]
	#[must_use]
	pub const fn new(value: u32) -> Option<Self> {
		match value {
			1 => Some(Self(Inner::U8)),
			2 => Some(Self(Inner::U16)),
			3 => Some(Self(Inner::U24)),
			4 => Some(Self(Inner::U32)),
			5 => Some(Self(Inner::U40)),
			6 => Some(Self(Inner::U48)),
			7 => Some(Self(Inner::U56)),
			8 => Some(Self(Inner::U64)),
			_ => None,
		}
	}

	/// Retrieves the sampling depth.
	#[inline]
	#[must_use]
	pub const fn get(self) -> u32 {
		self.as_u8().into()
	}

	/// Retrieves the sampling depth as a [`u8`] value.
	#[inline(always)]
	#[must_use]
	pub const fn as_u8(self) -> u8 {
		self.0 as u8
	}

	/// Retrieves the sampling depth as a [`u64`] value.
	#[inline]
	#[must_use]
	pub const fn as_u64(self) -> u64 {
		self.get().into()
	}

	/// Retrieves the sampling depth as a [`usize`]
	/// value.
	#[inline]
	#[must_use]
	pub const fn as_usize(self) -> usize {
		self.as_u8().into()
	}
}

impl Debug for SampleDepth {
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		Debug::fmt(&self.get(), f)
	}
}

const impl Default for SampleDepth {
	#[inline(always)]
	fn default() -> Self {
		const { Self::new(3).unwrap() }
	}
}

impl Display for SampleDepth {
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		write!(f, "{}B", self.get())
	}
}

/// Inner values for [`SampleDepth`].
#[repr(u8)]
#[derive(Copy, Debug)]
#[derive_const(
	Clone,
	Eq,
	Ord,
	PartialEq,
	PartialOrd,
)]
enum Inner {
	/// An (`8-bit`) byte.
	U8  = 1,

	/// A (`16-bit`) half word.
	U16 = 2,

	/// A (`24`-bit) triple-byte.
	U24 = 3,

	/// A (`32`-bit) word.
	U32 = 4,

	/// A (`40`-bit) quintuple-byte.
	U40 = 5,

	/// A (`48`-bit) sextuple-byte.
	U48 = 6,

	/// A (`56`-bit) septuple-byte.
	U56 = 7,

	/// A (`64`-bit) double word.
	U64 = 8,
}