Skip to main content

fluidattacks_blends_domain/stack/resolve/
variables.rs

1use core::num::NonZeroU32;
2
3/// Stands for the unknown rest of a partial symbol stack.
4#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
5#[non_exhaustive]
6pub struct SymbolStackVariable(NonZeroU32);
7
8impl SymbolStackVariable {
9    /// The first variable of a path.
10    pub const INITIAL: Self = Self(NonZeroU32::MIN);
11
12    /// The variable numbered `id`; `None` for 0, which numbers no variable.
13    #[must_use]
14    pub fn new(id: u32) -> Option<Self> {
15        NonZeroU32::new(id).map(Self)
16    }
17
18    /// This variable's number.
19    #[must_use]
20    pub const fn get(self) -> u32 {
21        self.0.get()
22    }
23
24    /// This variable renumbered `offset` places up; `None` past the last number.
25    #[must_use]
26    pub fn with_offset(self, offset: u32) -> Option<Self> {
27        self.0.checked_add(offset).map(Self)
28    }
29}
30
31#[cfg(test)]
32mod tests {
33    use super::SymbolStackVariable;
34
35    #[test]
36    fn zero_numbers_no_variable() {
37        assert_eq!(SymbolStackVariable::new(0), None);
38    }
39
40    #[test]
41    fn the_initial_variable_is_number_one() {
42        assert_eq!(SymbolStackVariable::INITIAL.get(), 1);
43    }
44
45    #[test]
46    fn an_offset_renumbers_a_variable_up() {
47        assert_eq!(
48            SymbolStackVariable::INITIAL.with_offset(2),
49            SymbolStackVariable::new(3)
50        );
51    }
52
53    #[test]
54    fn an_offset_past_the_last_number_gives_no_variable() {
55        let last = SymbolStackVariable::new(u32::MAX).unwrap();
56
57        assert_eq!(last.with_offset(1), None);
58        assert_eq!(last.with_offset(0), Some(last));
59    }
60}