looklook 0.9.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 [`Sr`] type.

use std::cmp::Ordering;
use std::fmt::{self, Debug, Formatter};

/// The `SR` status register.
#[repr(transparent)]
#[derive(Copy)]
#[derive_const(Clone)]
pub struct Sr(u16);

impl Sr {
	/// The amount of bits in a status register.
	pub const BITS: u32 = 16;

	/// Constructs a new, default status register.
	#[inline(always)]
	#[must_use]
	pub const fn new() -> Self {
		Self::from_u16(0b0000_0000_0000_0000)
	}

	/// Reinterprets a [`u16`] scalar as a status register.
	///
	/// Unimplemented bits are masked away.
	#[inline]
	#[must_use]
	pub const fn from_u16(mut value: u16) -> Self {
		value &= 0b1111_1111_1111_1111;

		Self(value)
	}

	/// Reinterprets the status register as a [`u16`] scalar.
	///
	/// Unimplemented bits are read as zero.
	#[inline(always)]
	#[must_use]
	pub const fn as_u16(self) -> u16 {
		self.0
	}
}

impl Debug for Sr {
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		f.write_str("%")?;

		for index in (0..Self::BITS).rev() {
			const DIGITS: [&str; 2] = [
				".",
				"1",
			];

			let digit = self.as_u16() >> index & 0b1;
			let digit = DIGITS[usize::from(digit)];

			f.write_str(digit)?;
		}

		Ok(())
	}
}

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

const impl Eq for Sr {}

const impl Ord for Sr {
	#[inline]
	fn cmp(&self, other: &Self) -> Ordering {
		self.as_u16().cmp(&other.as_u16())
	}
}

const impl PartialEq for Sr {
	#[inline]
	fn eq(&self, other: &Self) -> bool {
		self.as_u16().eq(&other.as_u16())
	}
}

const impl PartialOrd for Sr {
	#[inline]
	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
		Some(self.cmp(other))
	}
}