looklook 0.6.0

Descriptive signal synthesiser.
// Creadright 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 [`Address`] enumeration.

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

/// An address register name.
#[repr(usize)]
#[derive(Copy, Debug)]
#[derive_const(
	Clone,
	Eq,
	Ord,
	PartialOrd,
	PartialEq,
)]
pub enum Address {
	/// The `%a0` register.
	A0 = 0,

	/// The `%a1` register.
	A1 = 1,

	/// The `%a2` register.
	A2 = 2,

	/// The `%a3` register.
	A3 = 3,

	/// The `%a4` register.
	A4 = 4,

	/// The `%a5` register.
	A5 = 5,

	/// The `%a6` register.
	A6 = 6,

	/// The `%a7` register.
	A7 = 7,
}

impl Address {
	/// Constructs a register name from a raw index
	///
	/// If the provided index is greater than `7`, the
	/// value is wrapped.
	///
	/// # Panics
	///
	/// This constructor will panic if the provided
	/// index is greater than `7` and overflow checks
	/// are enabled.
	#[inline]
	#[must_use]
	#[track_caller]
	pub const fn from_usize(mut index: usize) -> Self {
		if cfg!(overflow_checks) {
			assert!(
				index <= 7,
				"cannot construct address register name with index greater than `7`",
			);
		}

		// Wrap to `0..=7`.
		index &= 0b111;

		match index {
			0 => Self::A0,
			1 => Self::A1,
			2 => Self::A2,
			3 => Self::A3,
			4 => Self::A4,
			5 => Self::A5,
			6 => Self::A6,
			7 => Self::A7,

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

	/// Retrieves a textual representation of the
	/// register name.
	#[inline]
	#[must_use]
	pub const fn as_str(self) -> &'static str {
		match self {
			Self::A0 => "%a0",
			Self::A1 => "%a1",
			Self::A2 => "%a2",
			Self::A3 => "%a3",
			Self::A4 => "%a4",
			Self::A5 => "%a5",
			Self::A6 => "%a6",
			Self::A7 => "%a7",
		}
	}

	/// Retrieves the address index as a [`usize`]
	/// value.
	#[inline]
	#[must_use]
	pub const fn as_usize(self) -> usize {
		// NOTE: The enumeration already uses `usize` re-
		// presentation.
		self as usize
	}
}

impl Display for Address {
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		f.write_str(self.as_str())
	}
}