ebds/
denomination.rs

1#[cfg(not(feature = "std"))]
2use alloc::string::String;
3
4use crate::std;
5use std::fmt;
6
7/// Cash denominations
8#[repr(u32)]
9#[derive(Clone, Copy, Debug, Default, PartialEq)]
10pub enum Denomination {
11    #[default]
12    Zero = 0,
13    One = 1,
14    Two = 2,
15    Five = 5,
16    Ten = 10,
17    Twenty = 20,
18    Fifty = 50,
19    Hundred = 100,
20    TwoHundred = 200,
21    FiveHundred = 500,
22    Thousand = 1000,
23    TwoThousand = 2000,
24    FiveThousand = 5000,
25    TenThousand = 10_000,
26    TwentyThousand = 20_000,
27    FiftyThousand = 50_000,
28    HundredThousand = 100_000,
29}
30
31impl From<Denomination> for &'static str {
32    fn from(d: Denomination) -> Self {
33        match d {
34            Denomination::Zero => "Zero",
35            Denomination::One => "One",
36            Denomination::Two => "Two",
37            Denomination::Five => "Five",
38            Denomination::Ten => "Ten",
39            Denomination::Twenty => "Twenty",
40            Denomination::Fifty => "Fifty",
41            Denomination::Hundred => "Hundred",
42            Denomination::TwoHundred => "Two hundred",
43            Denomination::FiveHundred => "Five hundred",
44            Denomination::Thousand => "Thousand",
45            Denomination::TwoThousand => "Two thousand",
46            Denomination::FiveThousand => "Five thousand",
47            Denomination::TenThousand => "Ten thousand",
48            Denomination::TwentyThousand => "Twenty thousand",
49            Denomination::FiftyThousand => "Fifty thousand",
50            Denomination::HundredThousand => "Hundred thousand",
51        }
52    }
53}
54
55impl From<&Denomination> for &'static str {
56    fn from(d: &Denomination) -> Self {
57        (*d).into()
58    }
59}
60
61impl fmt::Display for Denomination {
62    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63        write!(f, r#""{}""#, <&str>::from(self))
64    }
65}
66
67impl From<u32> for Denomination {
68    fn from(digit: u32) -> Self {
69        match digit {
70            0 => Self::Zero,
71            1 => Self::One,
72            2 => Self::Two,
73            5 => Self::Five,
74            10 => Self::Ten,
75            20 => Self::Twenty,
76            50 => Self::Fifty,
77            100 => Self::Hundred,
78            200 => Self::TwoHundred,
79            500 => Self::FiveHundred,
80            1000 => Self::Thousand,
81            2000 => Self::TwoThousand,
82            5000 => Self::FiveThousand,
83            10_000 => Self::TenThousand,
84            20_000 => Self::TwentyThousand,
85            50_000 => Self::FiftyThousand,
86            100_000 => Self::HundredThousand,
87            _ => Self::Zero,
88        }
89    }
90}
91
92impl From<Denomination> for u32 {
93    fn from(d: Denomination) -> Self {
94        d as u32
95    }
96}
97
98bitfield! {
99    /// Enable/disable note denominations while in base note mode
100    #[derive(Clone, Copy, Debug, Default, PartialEq)]
101    pub struct StandardDenomination(u8);
102    u8;
103    pub one, set_one: 0;
104    pub two, set_two: 1;
105    pub three, set_three: 2;
106    pub four, set_four: 3;
107    pub five, set_five: 4;
108    pub six, set_six: 5;
109    pub seven, set_seven: 6;
110}
111
112mod bitmask {
113    pub const DENOMINATION: u8 = 0b111_1111;
114}
115
116impl StandardDenomination {
117    /// Creates a [Denomination] with all denominations set.
118    pub const fn all() -> Self {
119        Self(bitmask::DENOMINATION)
120    }
121
122    /// Creates a [Denomination] with no denominations set.
123    pub const fn none() -> Self {
124        Self(0)
125    }
126
127    /// Converts from the [ExceptionStatus](crate::status::ExceptionStatus) `note_value` field.
128    pub const fn from_note_value(note_value: u8) -> Self {
129        match note_value {
130            0b000 => Self::none(),
131            0b001..=0b111 => Self(1 << (note_value - 1)),
132            _ => Self::none(),
133        }
134    }
135
136    /// Sets all denomintations.
137    pub fn set_all(&mut self) {
138        self.0 |= bitmask::DENOMINATION;
139    }
140
141    /// Inverts all the denomination bits.
142    pub fn set_inverted(&mut self) {
143        self.0 ^= bitmask::DENOMINATION;
144    }
145
146    /// Inverts all the denomination bits.
147    pub fn invert(&self) -> Self {
148        Self(self.0 ^ bitmask::DENOMINATION)
149    }
150}
151
152fn denom_delimiter(has_denom: bool) -> &'static str {
153    if has_denom {
154        ","
155    } else {
156        ""
157    }
158}
159
160impl fmt::Display for StandardDenomination {
161    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162        let mut dis = String::new();
163        let mut has_denom = false;
164
165        if self.one() {
166            dis += "Denom1";
167            has_denom = true;
168        }
169        if self.two() {
170            dis = dis + denom_delimiter(has_denom) + "Denom2";
171            has_denom = true;
172        }
173        if self.three() {
174            dis = dis + denom_delimiter(has_denom) + "Denom3";
175            has_denom = true;
176        }
177        if self.four() {
178            dis = dis + denom_delimiter(has_denom) + "Denom4";
179            has_denom = true;
180        }
181        if self.five() {
182            dis = dis + denom_delimiter(has_denom) + "Denom5";
183            has_denom = true;
184        }
185        if self.six() {
186            dis = dis + denom_delimiter(has_denom) + "Denom6";
187            has_denom = true;
188        }
189        if self.seven() {
190            dis = dis + denom_delimiter(has_denom) + "Denom7";
191            has_denom = true;
192        }
193
194        if has_denom {
195            write!(f, r#""{dis}""#)
196        } else {
197            write!(f, r#""None""#)
198        }
199    }
200}
201
202impl From<StandardDenomination> for u8 {
203    fn from(d: StandardDenomination) -> Self {
204        d.0
205    }
206}
207
208impl From<&StandardDenomination> for u8 {
209    fn from(d: &StandardDenomination) -> Self {
210        d.0
211    }
212}
213
214impl From<u8> for StandardDenomination {
215    fn from(b: u8) -> Self {
216        Self(b & bitmask::DENOMINATION)
217    }
218}
219
220impl From<StandardDenominationFlag> for StandardDenomination {
221    fn from(f: StandardDenominationFlag) -> Self {
222        Self(f as u8)
223    }
224}
225
226/// Bit flags for [StandardDenomination]s.
227#[repr(u8)]
228#[derive(Clone, Copy, Debug, Default, PartialEq)]
229pub enum StandardDenominationFlag {
230    Denom1 = 0b000_0001,
231    Denom2 = 0b000_0010,
232    Denom3 = 0b000_0100,
233    Denom4 = 0b000_1000,
234    Denom5 = 0b001_0000,
235    Denom6 = 0b010_0000,
236    Denom7 = 0b100_0000,
237    #[default]
238    Zero = 0b000_0000,
239}
240
241impl StandardDenominationFlag {
242    /// Creates a new [StandardDenominationFlag].
243    pub const fn new() -> Self {
244        Self::Zero
245    }
246}
247
248impl From<StandardDenomination> for StandardDenominationFlag {
249    fn from(d: StandardDenomination) -> Self {
250        // matches lowest value first
251        if d.one() {
252            Self::Denom1
253        } else if d.two() {
254            Self::Denom2
255        } else if d.three() {
256            Self::Denom3
257        } else if d.four() {
258            Self::Denom4
259        } else if d.five() {
260            Self::Denom5
261        } else if d.six() {
262            Self::Denom6
263        } else if d.seven() {
264            Self::Denom7
265        } else {
266            Self::Zero
267        }
268    }
269}