near_gas/trait_impls/
from_str.rs1use crate::{NearGas, NearGasError, ONE_GIGA_GAS, ONE_PETA_GAS, ONE_TERA_GAS};
2
3impl std::str::FromStr for NearGas {
4 type Err = NearGasError;
5 fn from_str(s: &str) -> Result<Self, Self::Err> {
6 let uppercase_s = s.trim().to_ascii_uppercase();
7 let (value, unit) = uppercase_s.split_at(
8 s.find(|c: char| c.is_ascii_alphabetic())
9 .ok_or_else(|| NearGasError::IncorrectUnit(s.to_owned()))?,
10 );
11 let unit_precision = match unit {
12 "PGAS" | "PETAGAS" => ONE_PETA_GAS,
13 "TGAS" | "TERAGAS" => ONE_TERA_GAS,
14 "GIGAGAS" | "GGAS" => ONE_GIGA_GAS,
15 _ => return Err(NearGasError::IncorrectUnit(s.to_owned())),
16 };
17 Ok(NearGas::from_gas(
18 crate::utils::parse_decimal_number(value.trim(), unit_precision)
19 .map_err(NearGasError::IncorrectNumber)?,
20 ))
21 }
22}
23
24#[cfg(test)]
25mod test {
26 use std::str::FromStr;
27
28 use crate::{DecimalNumberParsingError, NearGas, NearGasError};
29
30 #[test]
31 fn doubledot() {
32 let data = "1.1.1 TeraGas";
33 let gas: Result<NearGas, NearGasError> = FromStr::from_str(data);
34 assert_eq!(
35 gas,
36 Err(NearGasError::IncorrectNumber(
37 DecimalNumberParsingError::InvalidNumber("1.1.1".to_owned())
38 ))
39 )
40 }
41
42 #[test]
43 fn space_after_dot() {
44 let data = "1. 0 TeraGas";
45 let gas: Result<NearGas, NearGasError> = FromStr::from_str(data);
46 assert_eq!(
47 gas,
48 Err(NearGasError::IncorrectNumber(
49 DecimalNumberParsingError::InvalidNumber("1. 0".to_owned())
50 ))
51 )
52 }
53
54 #[test]
55 fn decimal_tgas() {
56 let data = "0.5 TGas";
57 let gas: Result<NearGas, NearGasError> = FromStr::from_str(data);
58 assert_eq!(gas, Ok(NearGas::from_ggas(500)))
59 }
60
61 #[test]
62 fn incorect_currency() {
63 let data = "0 pas";
64 let gas: Result<NearGas, NearGasError> = FromStr::from_str(data);
65 assert_eq!(gas, Err(NearGasError::IncorrectUnit(data.to_owned())))
66 }
67
68 #[test]
69 fn without_currency() {
70 let data = "0";
71 let gas: Result<NearGas, NearGasError> = FromStr::from_str(data);
72 assert_eq!(gas, Err(NearGasError::IncorrectUnit("0".to_owned())))
73 }
74
75 #[test]
76 fn invalid_whole() {
77 let data = "-1 TeraGas";
78 let gas: Result<NearGas, NearGasError> = FromStr::from_str(data);
79 assert_eq!(
80 gas,
81 Err(NearGasError::IncorrectNumber(
82 DecimalNumberParsingError::InvalidNumber("-1".to_owned())
83 ))
84 )
85 }
86
87 #[test]
88 fn test_from_str_f64_gas_without_int() {
89 let near_gas = NearGas::from_str(".055ggas").unwrap_err();
90 assert_eq!(
91 near_gas,
92 NearGasError::IncorrectNumber(DecimalNumberParsingError::InvalidNumber(
93 ".055".to_string()
94 ))
95 );
96 }
97
98 #[test]
99 fn test_from_str_without_unit() {
100 let near_gas = NearGas::from_str("100").unwrap_err();
101 assert_eq!(near_gas, NearGasError::IncorrectUnit("100".to_string()));
102 }
103
104 #[test]
105 fn test_from_str_incorrect_unit() {
106 let near_gas = NearGas::from_str("100 UAH").unwrap_err();
107 assert_eq!(near_gas, NearGasError::IncorrectUnit("100 UAH".to_string()));
108 }
109
110 #[test]
111 fn test_from_str_invalid_double_dot() {
112 let near_gas = NearGas::from_str("100.55.").unwrap_err();
113 assert_eq!(near_gas, NearGasError::IncorrectUnit("100.55.".to_string()));
114 }
115
116 #[test]
117 fn test_from_str_large_fractional_part() {
118 let near_gas = NearGas::from_str("100.1111122222333 ggas").unwrap_err(); assert_eq!(
120 near_gas,
121 NearGasError::IncorrectNumber(DecimalNumberParsingError::LongFractional(
122 "1111122222333".to_string()
123 ))
124 );
125 }
126
127 #[test]
128 fn test_from_str_large_int_part() {
129 let near_gas = NearGas::from_str("200123456789123.0 tgas").unwrap_err();
130 assert_eq!(
131 near_gas,
132 NearGasError::IncorrectNumber(DecimalNumberParsingError::LongWhole(
133 "200123456789123".to_string()
134 ))
135 );
136 }
137
138 #[test]
139 fn test_from_str_negative_value() {
140 let near_gas = NearGas::from_str("-100 ggas").unwrap_err();
141 assert_eq!(
142 near_gas,
143 NearGasError::IncorrectNumber(DecimalNumberParsingError::InvalidNumber(
144 "-100".to_string()
145 ))
146 );
147 }
148
149 #[test]
150 fn near_gas_from_str_currency_pgas() {
151 assert_eq!(
152 NearGas::from_str("10 pgas").unwrap(),
153 NearGas::from_gas(10_000_000_000_000_000) );
155 assert_eq!(
156 NearGas::from_str("10.055PETAGAS").unwrap(),
157 NearGas::from_gas(10_055_000_000_000_000) )
159 }
160 #[test]
161 fn near_gas_from_str_currency_tgas() {
162 assert_eq!(
163 NearGas::from_str("10 tgas").unwrap(),
164 NearGas::from_gas(10_000_000_000_000) );
166 assert_eq!(
167 NearGas::from_str("10.055TERAGAS").unwrap(),
168 NearGas::from_gas(10_055_000_000_000) );
170 }
171
172 #[test]
173 fn near_gas_from_str_currency_gigagas() {
174 assert_eq!(
175 NearGas::from_str("10 gigagas").unwrap(),
176 NearGas::from_gas(10_000_000_000) );
178 assert_eq!(
179 NearGas::from_str("10GGAS ").unwrap(),
180 NearGas::from_gas(10_000_000_000) );
182 }
183
184 #[test]
185 fn near_gas_from_str_f64_pgas() {
186 assert_eq!(
187 NearGas::from_str("0.000001 pgas").unwrap(),
188 NearGas::from_gas(1_000_000_000) )
190 }
191 #[test]
192 fn near_gas_from_str_f64_tgas() {
193 assert_eq!(
194 NearGas::from_str("0.000001 tgas").unwrap(),
195 NearGas::from_gas(1_000_000) );
197 }
198}