decancer/bidi/
level.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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)
  }
}