dup_crypto/dewif/
currency.rs

1//  Copyright (C) 2020 Éloïs SANCHEZ.
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU Affero General Public License as
5// published by the Free Software Foundation, either version 3 of the
6// License, or (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU Affero General Public License for more details.
12//
13// You should have received a copy of the GNU Affero General Public License
14// along with this program.  If not, see <https://www.gnu.org/licenses/>.
15
16//! Define DEWIF currency field
17
18use std::fmt::Display;
19use std::num::NonZeroU32;
20use std::str::FromStr;
21
22/// Ğ1 currency
23pub const G1_CURRENCY: u32 = 1;
24const G1_CURRENCY_STR: &str = "g1";
25
26/// Ğ1-Test currency
27pub const G1_TEST_CURRENCY: u32 = /*268_435_457*/0x1000_0001;
28const G1_TEST_CURRENCY_STR: &str = "g1-test";
29
30#[derive(Copy, Clone, Debug, PartialEq)]
31/// Expected DEWIF currency
32pub enum ExpectedCurrency {
33    /// Expected any currency (no limitation)
34    Any,
35    /// Expected specific currency
36    Specific(Currency),
37}
38
39impl ExpectedCurrency {
40    pub(crate) fn is_valid(self, currency: Currency) -> bool {
41        match self {
42            Self::Any => true,
43            Self::Specific(expected_currency) => expected_currency == currency,
44        }
45    }
46}
47
48impl Display for ExpectedCurrency {
49    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
50        match self {
51            Self::Any => write!(f, "Any"),
52            Self::Specific(expected_currency) => expected_currency.fmt(f),
53        }
54    }
55}
56
57/// DEWIF currency
58#[derive(Copy, Clone, Debug, PartialEq)]
59pub struct Currency(Option<NonZeroU32>);
60
61impl Currency {
62    /// None currency
63    pub fn none() -> Self {
64        Currency(None)
65    }
66}
67
68impl Display for Currency {
69    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
70        if let Some(currency_code) = self.0 {
71            match currency_code.get() {
72                G1_CURRENCY => write!(f, "{}", G1_CURRENCY_STR),
73                G1_TEST_CURRENCY => write!(f, "{}", G1_TEST_CURRENCY_STR),
74                other => write!(f, "{}", other),
75            }
76        } else {
77            write!(f, "None")
78        }
79    }
80}
81
82impl From<u32> for Currency {
83    fn from(source: u32) -> Self {
84        Self(NonZeroU32::new(source))
85    }
86}
87
88impl From<Currency> for u32 {
89    fn from(val: Currency) -> Self {
90        if let Some(currency_code) = val.0 {
91            currency_code.get()
92        } else {
93            0u32
94        }
95    }
96}
97
98/// Unknown currency name
99#[derive(Copy, Clone, Debug, PartialEq)]
100pub struct UnknownCurrencyName;
101
102impl FromStr for Currency {
103    type Err = UnknownCurrencyName;
104
105    fn from_str(source: &str) -> Result<Self, Self::Err> {
106        match source {
107            "" => Ok(Currency(None)),
108            G1_CURRENCY_STR => Ok(Currency(NonZeroU32::new(G1_CURRENCY))),
109            G1_TEST_CURRENCY_STR => Ok(Currency(NonZeroU32::new(G1_TEST_CURRENCY))),
110            _ => Err(UnknownCurrencyName),
111        }
112    }
113}
114
115#[cfg(test)]
116mod tests {
117
118    use super::*;
119    use unwrap::unwrap;
120
121    #[test]
122    fn display_expected_currency() {
123        assert_eq!(
124            "None",
125            &format!("{}", ExpectedCurrency::Specific(Currency::from(0))),
126        );
127        assert_eq!("Any", &format!("{}", ExpectedCurrency::Any));
128    }
129
130    #[test]
131    fn display_currency() {
132        assert_eq!(G1_CURRENCY_STR, &format!("{}", Currency::from(G1_CURRENCY)),);
133        assert_eq!(
134            G1_TEST_CURRENCY_STR,
135            &format!("{}", Currency::from(G1_TEST_CURRENCY)),
136        );
137        assert_eq!("42", &format!("{}", Currency::from(42)),);
138        assert_eq!("None", &format!("{}", Currency::from(0)),);
139    }
140
141    #[test]
142    fn currency_from_str() {
143        assert_eq!(
144            Currency::from(G1_CURRENCY),
145            unwrap!(Currency::from_str(G1_CURRENCY_STR)),
146        );
147        assert_eq!(
148            Currency::from(G1_TEST_CURRENCY),
149            unwrap!(Currency::from_str(G1_TEST_CURRENCY_STR)),
150        );
151        assert_eq!(
152            Err(UnknownCurrencyName),
153            Currency::from_str("unknown currency"),
154        );
155    }
156}