use crate::interner::MAX_ALLOWED_DEPTH;
use super::Lod;
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct MaxDepth(u8);
impl From<MaxDepth> for u8 {
#[inline]
fn from(id: MaxDepth) -> u8 {
id.0
}
}
impl TryFrom<u8> for MaxDepth {
type Error = &'static str;
#[inline]
fn try_from(value: u8) -> Result<Self, Self::Error> {
if value < MAX_ALLOWED_DEPTH as u8 {
Ok(Self(value))
} else {
Err("Max depth exceeds allowed limit")
}
}
}
impl MaxDepth {
#[must_use]
#[inline(always)]
pub const fn new(max: u8) -> Self {
assert!(
max < MAX_ALLOWED_DEPTH as u8,
"Max depth exceeds allowed limit"
);
Self(max)
}
#[must_use]
#[inline(always)]
pub const fn max(&self) -> u8 {
self.0
}
#[must_use]
pub const fn as_usize(&self) -> usize {
self.0 as usize
}
#[must_use]
pub fn for_lod(&self, lod: Lod) -> Self {
let max = self.0.saturating_sub(lod.lod());
Self(max)
}
}
impl std::fmt::Display for MaxDepth {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.max())
}
}
impl std::fmt::Debug for MaxDepth {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.max())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new() {
let depth = MaxDepth::new(6);
assert_eq!(depth.max(), 6);
}
#[test]
#[cfg(debug_assertions)]
#[should_panic(expected = "Max depth exceeds allowed limit")]
fn test_max_allowed_depth() {
let _ = MaxDepth::new(MAX_ALLOWED_DEPTH as u8);
}
#[test]
fn test_display_and_debug() {
let depth = MaxDepth::new(6);
assert_eq!(format!("{depth}"), "6");
assert_eq!(format!("{depth:?}"), "6");
}
#[test]
#[should_panic(expected = "Max depth exceeds allowed limit")]
fn test_new_current_eq_max() {
let _ = MaxDepth::new(MAX_ALLOWED_DEPTH as u8);
}
#[test]
fn test_zero_zero_depth() {
let depth = MaxDepth::new(0);
assert_eq!(depth.max(), 0);
}
#[test]
fn test_maximum_valid_depth() {
let max = MAX_ALLOWED_DEPTH as u8 - 1;
let depth = MaxDepth::new(max);
assert_eq!(depth.max(), max);
}
#[test]
fn test_try_from_ok() {
let val: u8 = 5;
let depth = MaxDepth::try_from(val);
assert!(depth.is_ok());
assert_eq!(depth.unwrap().max(), 5);
}
#[test]
fn test_try_from_err() {
let val: u8 = MAX_ALLOWED_DEPTH as u8;
let depth = MaxDepth::try_from(val);
assert!(depth.is_err());
}
#[test]
fn test_for_lod() {
let max_depth = MaxDepth::new(6);
let lod = Lod::new(2);
let reduced = max_depth.for_lod(lod);
assert_eq!(reduced.max(), 4);
}
#[test]
fn test_for_lod_saturate() {
let max_depth = MaxDepth::new(2);
let lod = Lod::new(5);
let reduced = max_depth.for_lod(lod);
assert_eq!(reduced.max(), 0);
}
}