looklook 0.8.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 ver-
// sion.
//
// LOOKLOOK is distributed in the hope that it will be useful, but WITHOUT ANY WAR-
// RANTY; 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 Affero General Public License along
// with LOOKLOOK. If not, see <https://www.gnu.org/licenses/>.

//! The [`Dn`] enumeration.

/// A data register name.
#[repr(u8)]
#[derive(Copy, Debug)]
#[derive_const(
	Clone,
	Eq,
	Ord,
	PartialEq,
	PartialOrd,
)]
pub enum Dn {
	/// The `D0` register.
	D0 = 0,

	/// The `D1` register.
	D1 = 1,

	/// The `D2` register.
	D2 = 2,

	/// The `D3` register.
	D3 = 3,

	/// The `D4` register.
	D4 = 4,

	/// The `D5` register.
	D5 = 5,

	/// The `D7` register.
	D6 = 6,

	/// The `D7` register.
	D7 = 7,
}

impl Dn {
	/// The minimum data register index (i.e. `D0`.)
	pub const MIN: Self = Self::D0;

	/// The maximum data register index (i.e. `D7`.)
	pub const MAX: Self = Self::D7;

	/// Reinterprets a [`u8`] value as a data register.
	///
	/// # Panic
	///
	/// This function may panic if the provided index is greater than `7`.
	#[inline]
	#[must_use]
	pub const fn from_u8(mut index: u8) -> Self {
		if cfg!(overflow_checks) {
			assert!(
				index <= Self::MAX.as_u8(),
				"attempt to construct data register with index greater than `7`",
			);
		}

		// Mask to `3` bits.
		index &= 0b111;

		match index {
			0 => Self::D0,
			1 => Self::D1,
			2 => Self::D2,
			3 => Self::D3,
			4 => Self::D4,
			5 => Self::D5,
			6 => Self::D6,
			7 => Self::D7,

			_ => {
				unreachable!();
			}
		}
	}

	/// Reinterprets the register index as a [`u8`] scalar index.
	#[inline(always)]
	#[must_use]
	pub const fn as_u8(self) -> u8 {
		self as u8
	}

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

	/// Retrieves a textual representation of the register.
	#[inline]
	#[must_use]
	pub const fn as_str(self) -> &'static str {
		match self {
			Self::D0 => "D0",
			Self::D1 => "D1",
			Self::D2 => "D2",
			Self::D3 => "D3",
			Self::D4 => "D4",
			Self::D5 => "D5",
			Self::D6 => "D6",
			Self::D7 => "D7",
		}
	}
}