decancer 2.0.1

A tiny package that removes common unicode confusables/homoglyphs from strings.
Documentation
use super::Class;
use crate::Error;

#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub(crate) struct Level(pub(crate) u8);

pub(crate) const MAX_EXPLICIT_DEPTH: u8 = 125;
pub(crate) const MAX_IMPLICIT_DEPTH: u8 = MAX_EXPLICIT_DEPTH + 1;

impl Level {
  pub(crate) const fn ltr() -> Self {
    Self(0)
  }

  pub(crate) const fn rtl() -> Self {
    Self(1)
  }

  pub(crate) const fn new_explicit(number: u8) -> Result<Self, Error> {
    if number <= MAX_EXPLICIT_DEPTH {
      Ok(Self(number))
    } else {
      Err(Error::LevelExplicitOverflow)
    }
  }

  pub(crate) const fn new_implicit(number: u8) -> Result<Self, Error> {
    if number <= MAX_IMPLICIT_DEPTH {
      Ok(Self(number))
    } else {
      Err(Error::LevelImplicitOverflow)
    }
  }

  pub(crate) fn lower(&mut self, amount: u8) -> Result<(), Error> {
    self.0 = self
      .0
      .checked_sub(amount)
      .ok_or(Error::LevelModificationUnderflow)?;

    Ok(())
  }

  pub(crate) fn raise(&mut self, amount: u8) -> Result<(), Error> {
    let number = self
      .0
      .checked_add(amount)
      .ok_or(Error::LevelModificationOverflow)?;

    if number <= MAX_IMPLICIT_DEPTH {
      self.0 = number;

      Ok(())
    } else {
      Err(Error::LevelModificationOverflow)
    }
  }

  pub(crate) const fn is_ltr(&self) -> bool {
    self.0 % 2 == 0
  }

  pub(crate) const fn is_rtl(&self) -> bool {
    self.0 % 2 == 1
  }

  pub(crate) const fn class(&self) -> Class {
    if self.is_ltr() {
      Class::L
    } else {
      Class::R
    }
  }

  pub(crate) const fn new_explicit_next_ltr(&self) -> Result<Self, Error> {
    Self::new_explicit((self.0 + 2) & !1)
  }

  pub(crate) const fn new_explicit_next_rtl(&self) -> Result<Self, Error> {
    Self::new_explicit((self.0 + 1) | 1)
  }

  pub(crate) const fn new_lowest_ge_rtl(&self) -> Result<Self, Error> {
    Self::new_implicit(self.0 | 1)
  }
}