/rust/registry/src/index.crates.io-1949cf8c6b5b557f/lexpr-0.2.7/src/number.rs
Line | Count | Source |
1 | | //! Dynamically typed number type. |
2 | | |
3 | | use std::fmt::{self, Debug, Display}; |
4 | | |
5 | | /// Represents an S-expression number, whether integer or floating point. |
6 | | #[derive(PartialEq, Clone)] |
7 | | pub struct Number { |
8 | | n: N, |
9 | | } |
10 | | |
11 | | #[derive(Debug, PartialEq, Clone)] |
12 | | enum N { |
13 | | PosInt(u64), |
14 | | NegInt(i64), |
15 | | Float(f64), |
16 | | } |
17 | | |
18 | | impl Number { |
19 | | /// Returns true if the `Number` is an integer between `i64::MIN` and |
20 | | /// `i64::MAX`. |
21 | | /// |
22 | | /// For any `Number` on which `is_i64` returns true, `as_i64` is |
23 | | /// guaranteed to return the integer value. |
24 | | /// |
25 | | /// ``` |
26 | | /// # use lexpr::sexp; |
27 | | /// # |
28 | | /// let big = i64::max_value() as u64 + 10; |
29 | | /// let v = sexp!(((a . 64) (b . ,big) (c . 256.0))); |
30 | | /// |
31 | | /// assert!(v["a"].is_i64()); |
32 | | /// |
33 | | /// // Greater than i64::MAX. |
34 | | /// assert!(!v["b"].is_i64()); |
35 | | /// |
36 | | /// // Numbers with a decimal point are not considered integers. |
37 | | /// assert!(!v["c"].is_i64()); |
38 | | /// ``` |
39 | | #[inline] |
40 | 0 | pub fn is_i64(&self) -> bool { |
41 | 0 | match self.n { |
42 | 0 | N::PosInt(v) => v <= i64::max_value() as u64, |
43 | 0 | N::NegInt(_) => true, |
44 | 0 | N::Float(_) => false, |
45 | | } |
46 | 0 | } |
47 | | |
48 | | /// Returns true if the `Number` is an integer between zero and `u64::MAX`. |
49 | | /// |
50 | | /// For any Number on which `is_u64` returns true, `as_u64` is guaranteed to |
51 | | /// return the integer value. |
52 | | /// |
53 | | /// ``` |
54 | | /// # use lexpr::sexp; |
55 | | /// # |
56 | | /// let v = sexp!(((a . 64) (b . -64) (c . 256.0))); |
57 | | /// |
58 | | /// assert!(v["a"].is_u64()); |
59 | | /// |
60 | | /// // Negative integer. |
61 | | /// assert!(!v["b"].is_u64()); |
62 | | /// |
63 | | /// // Numbers with a decimal point are not considered integers. |
64 | | /// assert!(!v["c"].is_u64()); |
65 | | /// ``` |
66 | | #[inline] |
67 | 0 | pub fn is_u64(&self) -> bool { |
68 | 0 | match self.n { |
69 | 0 | N::PosInt(_) => true, |
70 | 0 | N::NegInt(_) | N::Float(_) => false, |
71 | | } |
72 | 0 | } |
73 | | |
74 | | /// Returns true if the `Number` can be represented by f64. |
75 | | /// |
76 | | /// For any Number on which `is_f64` returns true, `as_f64` is guaranteed to |
77 | | /// return the floating point value. |
78 | | /// |
79 | | /// Currently this function returns true if and only if both `is_i64` and |
80 | | /// `is_u64` return false but this is not a guarantee in the future. |
81 | | /// |
82 | | /// ``` |
83 | | /// # use lexpr::sexp; |
84 | | /// # |
85 | | /// let v = sexp!(((a . 256.0) (b . 64) (c . -64))); |
86 | | /// assert!(v["a"].is_f64()); |
87 | | /// |
88 | | /// // Integers. |
89 | | /// assert!(!v["b"].is_f64()); |
90 | | /// assert!(!v["c"].is_f64()); |
91 | | /// ``` |
92 | | #[inline] |
93 | 0 | pub fn is_f64(&self) -> bool { |
94 | 0 | match self.n { |
95 | 0 | N::Float(_) => true, |
96 | 0 | N::PosInt(_) | N::NegInt(_) => false, |
97 | | } |
98 | 0 | } |
99 | | |
100 | | /// If the `Number` is an integer, represent it as i64 if possible. Returns |
101 | | /// None otherwise. |
102 | | /// |
103 | | /// ``` |
104 | | /// # use lexpr::sexp; |
105 | | /// # |
106 | | /// let big = i64::max_value() as u64 + 10; |
107 | | /// let v = sexp!(((a . 64) (b . ,big) (c . 256.0))); |
108 | | /// |
109 | | /// assert_eq!(v["a"].as_i64(), Some(64)); |
110 | | /// assert_eq!(v["b"].as_i64(), None); |
111 | | /// assert_eq!(v["c"].as_i64(), None); |
112 | | /// ``` |
113 | | #[inline] |
114 | 0 | pub fn as_i64(&self) -> Option<i64> { |
115 | 0 | match self.n { |
116 | 0 | N::PosInt(n) => { |
117 | 0 | if n <= i64::max_value() as u64 { |
118 | 0 | Some(n as i64) |
119 | | } else { |
120 | 0 | None |
121 | | } |
122 | | } |
123 | 0 | N::NegInt(n) => Some(n), |
124 | 0 | N::Float(_) => None, |
125 | | } |
126 | 0 | } |
127 | | |
128 | | /// If the `Number` is an integer, represent it as u64 if possible. Returns |
129 | | /// None otherwise. |
130 | | /// |
131 | | /// ``` |
132 | | /// # use lexpr::sexp; |
133 | | /// # |
134 | | /// let v = sexp!(((a . 64) (b . -64) (c . 256.0))); |
135 | | /// |
136 | | /// assert_eq!(v["a"].as_u64(), Some(64)); |
137 | | /// assert_eq!(v["b"].as_u64(), None); |
138 | | /// assert_eq!(v["c"].as_u64(), None); |
139 | | /// ``` |
140 | | #[inline] |
141 | 0 | pub fn as_u64(&self) -> Option<u64> { |
142 | 0 | match self.n { |
143 | 0 | N::PosInt(n) => Some(n), |
144 | 0 | N::NegInt(_) | N::Float(_) => None, |
145 | | } |
146 | 0 | } |
147 | | |
148 | | /// Represents the number as f64 if possible. Returns None otherwise. |
149 | | /// |
150 | | /// ``` |
151 | | /// # use lexpr::sexp; |
152 | | /// # |
153 | | /// let v = sexp!(((a . 256.0) (b . 64) (c . -64))); |
154 | | /// |
155 | | /// assert_eq!(v["a"].as_f64(), Some(256.0)); |
156 | | /// assert_eq!(v["b"].as_f64(), Some(64.0)); |
157 | | /// assert_eq!(v["c"].as_f64(), Some(-64.0)); |
158 | | /// ``` |
159 | | #[inline] |
160 | 0 | pub fn as_f64(&self) -> Option<f64> { |
161 | 0 | match self.n { |
162 | 0 | N::PosInt(n) => Some(n as f64), |
163 | 0 | N::NegInt(n) => Some(n as f64), |
164 | 0 | N::Float(n) => Some(n), |
165 | | } |
166 | 0 | } |
167 | | |
168 | | /// Converts a finite `f64` to a `Number`. Infinite or NaN values |
169 | | /// are not S-expression numbers. |
170 | | /// |
171 | | /// ``` |
172 | | /// # use std::f64; |
173 | | /// # |
174 | | /// # use lexpr::Number; |
175 | | /// # |
176 | | /// assert!(Number::from_f64(256.0).is_some()); |
177 | | /// |
178 | | /// assert!(Number::from_f64(f64::NAN).is_none()); |
179 | | /// ``` |
180 | | #[inline] |
181 | 0 | pub fn from_f64(f: f64) -> Option<Number> { |
182 | 0 | if f.is_finite() { |
183 | 0 | Some(Number { n: N::Float(f) }) |
184 | | } else { |
185 | 0 | None |
186 | | } |
187 | 0 | } |
188 | | |
189 | | /// Dispatch based on the type of the contained value. |
190 | | /// |
191 | | /// Depending on the stored value, one of the functions of the |
192 | | /// supplied visitor will be called. |
193 | 0 | pub fn visit<V>(&self, visitor: V) -> Result<V::Value, V::Error> |
194 | 0 | where |
195 | 0 | V: Visitor, |
196 | | { |
197 | 0 | match self.n { |
198 | 0 | N::PosInt(n) => visitor.visit_u64(n), |
199 | 0 | N::NegInt(n) => visitor.visit_i64(n), |
200 | 0 | N::Float(n) => visitor.visit_f64(n), |
201 | | } |
202 | 0 | } Unexecuted instantiation: <lexpr::number::Number>::visit::<serde_lexpr::value::de::visit_number::Proxy<<f64 as serde_core::de::Deserialize>::deserialize::PrimitiveVisitor>> Unexecuted instantiation: <lexpr::number::Number>::visit::<serde_lexpr::value::de::visit_number::Proxy<<i32 as serde_core::de::Deserialize>::deserialize::PrimitiveVisitor>> Unexecuted instantiation: <lexpr::number::Number>::visit::<lexpr::print::Formatter::write_number::Write<&mut lexpr::value::WriterFormatter>> |
203 | | } |
204 | | |
205 | | /// Trait to access the value stored in `Number`. |
206 | | /// |
207 | | /// The `Number` type does not directly expose its internal |
208 | | /// structure to allow future changes without breaking the API. |
209 | | /// |
210 | | /// Instead, you can implement this trait and pass your implementation |
211 | | /// to `Number::visit`. |
212 | | /// |
213 | | /// [`Number::visit`]: struct.Number.html#method.visit |
214 | | pub trait Visitor { |
215 | | /// The return type of the visitor methods. |
216 | | type Value; |
217 | | /// The error type of the visitor methods. |
218 | | type Error; |
219 | | |
220 | | /// Construct an error given a message. |
221 | | /// |
222 | | /// This method is used by trait default implementations. |
223 | | fn error<T: Into<String>>(msg: T) -> Self::Error; |
224 | | |
225 | | /// The stored value is a `u64`. |
226 | | fn visit_u64(self, n: u64) -> Result<Self::Value, Self::Error>; |
227 | | /// The stored value is an `i64`. |
228 | | fn visit_i64(self, n: i64) -> Result<Self::Value, Self::Error>; |
229 | | /// The stored value is `f64`. |
230 | | fn visit_f64(self, n: f64) -> Result<Self::Value, Self::Error>; |
231 | | } |
232 | | |
233 | | macro_rules! impl_from_unsigned { |
234 | | ( |
235 | | $($ty:ty),* |
236 | | ) => { |
237 | | $( |
238 | | impl From<$ty> for Number { |
239 | | #[inline] |
240 | 0 | fn from(u: $ty) -> Self { |
241 | 0 | Number { n: N::PosInt(u64::from(u)) } |
242 | 0 | } Unexecuted instantiation: <lexpr::number::Number as core::convert::From<u64>>::from Unexecuted instantiation: <lexpr::number::Number as core::convert::From<u64>>::from Unexecuted instantiation: <lexpr::number::Number as core::convert::From<u8>>::from Unexecuted instantiation: <lexpr::number::Number as core::convert::From<u16>>::from Unexecuted instantiation: <lexpr::number::Number as core::convert::From<u32>>::from |
243 | | } |
244 | | )* |
245 | | }; |
246 | | } |
247 | | |
248 | | macro_rules! impl_from_signed { |
249 | | ( |
250 | | $($ty:ty),* |
251 | | ) => { |
252 | | $( |
253 | | impl From<$ty> for Number { |
254 | | #[inline] |
255 | 0 | fn from(n: $ty) -> Self { |
256 | 0 | let n = if n >= 0 { |
257 | 0 | N::PosInt(n as u64) |
258 | | } else { |
259 | 0 | N::NegInt(i64::from(n)) |
260 | | }; |
261 | 0 | Number { n } |
262 | 0 | } Unexecuted instantiation: <lexpr::number::Number as core::convert::From<i64>>::from Unexecuted instantiation: <lexpr::number::Number as core::convert::From<i64>>::from Unexecuted instantiation: <lexpr::number::Number as core::convert::From<i8>>::from Unexecuted instantiation: <lexpr::number::Number as core::convert::From<i16>>::from Unexecuted instantiation: <lexpr::number::Number as core::convert::From<i32>>::from |
263 | | } |
264 | | )* |
265 | | }; |
266 | | } |
267 | | |
268 | | impl_from_unsigned!(u8, u16, u32, u64); |
269 | | impl_from_signed!(i8, i16, i32, i64); |
270 | | |
271 | | impl From<f32> for Number { |
272 | | #[inline] |
273 | 0 | fn from(n: f32) -> Self { |
274 | 0 | Number { |
275 | 0 | n: N::Float(f64::from(n)), |
276 | 0 | } |
277 | 0 | } |
278 | | } |
279 | | |
280 | | impl From<f64> for Number { |
281 | | #[inline] |
282 | 0 | fn from(n: f64) -> Self { |
283 | 0 | Number { n: N::Float(n) } |
284 | 0 | } Unexecuted instantiation: <lexpr::number::Number as core::convert::From<f64>>::from Unexecuted instantiation: <lexpr::number::Number as core::convert::From<f64>>::from |
285 | | } |
286 | | |
287 | | impl Display for Number { |
288 | 0 | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { |
289 | 0 | match self.n { |
290 | 0 | N::PosInt(i) => Display::fmt(&i, formatter), |
291 | 0 | N::NegInt(i) => Display::fmt(&i, formatter), |
292 | 0 | N::Float(f) => Display::fmt(&f, formatter), |
293 | | } |
294 | 0 | } |
295 | | } |
296 | | |
297 | | impl Debug for Number { |
298 | 0 | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { |
299 | 0 | Debug::fmt(&self.n, formatter) |
300 | 0 | } |
301 | | } |