tower_sesh/value/
number.rs1use std::{fmt, hash::Hash};
4
5use serde::{
6 de::{self, Unexpected, Visitor},
7 forward_to_deserialize_any, Deserialize, Serialize,
8};
9
10use super::error::Error;
11
12#[derive(Clone, PartialEq, Eq, Hash)]
19pub struct Number {
20 n: NumberImpl,
21}
22
23#[derive(Copy, Clone)]
24enum NumberImpl {
25 PosInt(u64),
26 NegInt(i64),
28 Float(f64),
30}
31
32impl PartialEq for NumberImpl {
33 fn eq(&self, other: &Self) -> bool {
34 use NumberImpl::*;
35 match (self, other) {
36 (PosInt(a), PosInt(b)) => a.eq(b),
37 (NegInt(a), NegInt(b)) => a.eq(b),
38 (Float(a), Float(b)) => a.eq(b),
39 _ => false,
40 }
41 }
42}
43
44impl Eq for NumberImpl {}
46
47impl Hash for NumberImpl {
48 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
49 use NumberImpl::*;
50 match *self {
51 PosInt(i) => i.hash(state),
52 NegInt(i) => i.hash(state),
53 Float(f) => {
54 if f == 0.0f64 {
55 0.0f64.to_bits().hash(state)
56 } else {
57 f.to_bits().hash(state)
58 }
59 }
60 }
61 }
62}
63
64impl Number {
65 pub fn is_i64(&self) -> bool {
73 use NumberImpl::*;
74 match self.n {
75 PosInt(v) => v <= i64::MAX as u64,
76 NegInt(_) => true,
77 Float(_) => false,
78 }
79 }
80
81 pub fn is_u64(&self) -> bool {
89 use NumberImpl::*;
90 match self.n {
91 PosInt(_) => true,
92 NegInt(_) | Float(_) => false,
93 }
94 }
95
96 pub fn is_f64(&self) -> bool {
108 use NumberImpl::*;
109 match self.n {
110 Float(_) => true,
111 PosInt(_) | NegInt(_) => false,
112 }
113 }
114
115 pub fn as_i64(&self) -> Option<i64> {
118 use NumberImpl::*;
119 match self.n {
120 PosInt(n) => {
121 if n <= i64::MAX as u64 {
122 Some(n as i64)
123 } else {
124 None
125 }
126 }
127 NegInt(n) => Some(n),
128 Float(_) => None,
129 }
130 }
131
132 pub fn as_u64(&self) -> Option<u64> {
135 use NumberImpl::*;
136 match self.n {
137 PosInt(n) => Some(n),
138 NegInt(_) | Float(_) => None,
139 }
140 }
141
142 pub fn as_f64(&self) -> Option<f64> {
144 use NumberImpl::*;
145 match self.n {
146 PosInt(n) => Some(n as f64),
147 NegInt(n) => Some(n as f64),
148 Float(n) => Some(n),
149 }
150 }
151
152 pub fn from_f64(f: f64) -> Option<Number> {
165 if f.is_finite() {
166 let n = NumberImpl::Float(f);
167 Some(Number { n })
168 } else {
169 None
170 }
171 }
172
173 pub fn from_i128(i: i128) -> Option<Number> {
182 let n = if let Ok(u) = u64::try_from(i) {
183 NumberImpl::PosInt(u)
184 } else if let Ok(i) = i64::try_from(i) {
185 NumberImpl::NegInt(i)
186 } else {
187 return None;
188 };
189 Some(Number { n })
190 }
191
192 pub fn from_u128(u: u128) -> Option<Number> {
201 let n = if let Ok(u) = u64::try_from(u) {
202 NumberImpl::PosInt(u)
203 } else {
204 return None;
205 };
206 Some(Number { n })
207 }
208
209 pub(super) fn as_f32(&self) -> Option<f32> {
210 use NumberImpl::*;
211 match self.n {
212 PosInt(n) => Some(n as f32),
213 NegInt(n) => Some(n as f32),
214 Float(n) => Some(n as f32),
215 }
216 }
217
218 pub(super) fn from_f32(f: f32) -> Option<Number> {
219 if f.is_finite() {
220 let n = NumberImpl::Float(f as f64);
221 Some(Number { n })
222 } else {
223 None
224 }
225 }
226}
227
228impl fmt::Display for Number {
229 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
230 use NumberImpl::*;
231 match self.n {
232 PosInt(u) => formatter.write_str(itoa::Buffer::new().format(u)),
233 NegInt(i) => formatter.write_str(itoa::Buffer::new().format(i)),
234 Float(f) => formatter.write_str(ryu::Buffer::new().format_finite(f)),
235 }
236 }
237}
238
239impl fmt::Debug for Number {
240 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241 write!(f, "Number({})", self)
242 }
243}
244
245impl Serialize for Number {
246 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
247 where
248 S: serde::Serializer,
249 {
250 use NumberImpl::*;
251 match self.n {
252 PosInt(u) => serializer.serialize_u64(u),
253 NegInt(i) => serializer.serialize_i64(i),
254 Float(f) => serializer.serialize_f64(f),
255 }
256 }
257}
258
259impl<'de> Deserialize<'de> for Number {
260 #[inline]
261 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
262 where
263 D: serde::Deserializer<'de>,
264 {
265 struct NumberVisitor;
266
267 impl Visitor<'_> for NumberVisitor {
268 type Value = Number;
269
270 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
271 formatter.write_str("a number")
272 }
273
274 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E> {
275 Ok(v.into())
276 }
277
278 fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
279 where
280 E: serde::de::Error,
281 {
282 Number::from_i128(v).ok_or_else(|| de::Error::custom("number out of range"))
283 }
284
285 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> {
286 Ok(v.into())
287 }
288
289 fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
290 where
291 E: de::Error,
292 {
293 Number::from_u128(v).ok_or_else(|| de::Error::custom("number out of range"))
294 }
295
296 fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
297 where
298 E: de::Error,
299 {
300 Number::from_f32(v).ok_or_else(|| de::Error::custom("not a valid number"))
301 }
302
303 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
304 where
305 E: de::Error,
306 {
307 Number::from_f64(v).ok_or_else(|| de::Error::custom("not a valid number"))
308 }
309 }
310
311 deserializer.deserialize_any(NumberVisitor)
312 }
313}
314
315macro_rules! deserialize_any {
316 () => {
317 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
318 where
319 V: Visitor<'de>,
320 {
321 match self.n {
322 NumberImpl::PosInt(u) => visitor.visit_u64(u),
323 NumberImpl::NegInt(i) => visitor.visit_i64(i),
324 NumberImpl::Float(f) => visitor.visit_f64(f),
325 }
326 }
327 };
328}
329
330impl<'de> serde::Deserializer<'de> for Number {
331 type Error = Error;
332
333 deserialize_any!();
334
335 forward_to_deserialize_any! {
336 i8 i16 i32 i64 i128
337 u8 u16 u32 u64 u128 f32 f64
338 bool char str string bytes byte_buf option unit unit_struct
339 newtype_struct seq tuple tuple_struct map struct enum identifier
340 ignored_any
341 }
342}
343
344impl<'de> serde::Deserializer<'de> for &Number {
345 type Error = Error;
346
347 deserialize_any!();
348
349 forward_to_deserialize_any! {
350 i8 i16 i32 i64 i128
351 u8 u16 u32 u64 u128 f32 f64
352 bool char str string bytes byte_buf option unit unit_struct
353 newtype_struct seq tuple tuple_struct map struct enum identifier
354 ignored_any
355 }
356}
357
358macro_rules! from_unsigned {
359 ($($ty:ty)*) => {
360 $(
361 impl From<$ty> for Number {
362 fn from(u: $ty) -> Self {
363 let n = NumberImpl::PosInt(u as u64);
364 Number { n }
365 }
366 }
367 )*
368 };
369}
370
371macro_rules! from_signed {
372 ($($ty:ty)*) => {
373 $(
374 impl From<$ty> for Number {
375 fn from(i: $ty) -> Self {
376 let n = if i < 0 {
377 NumberImpl::NegInt(i as i64)
378 } else {
379 NumberImpl::PosInt(i as u64)
380 };
381 Number { n }
382 }
383 }
384 )*
385 };
386}
387
388from_unsigned! {
389 u8 u16 u32 u64 usize
390}
391from_signed! {
392 i8 i16 i32 i64 isize
393}
394
395impl Number {
396 #[cold]
397 pub(crate) fn unexpected(&self) -> Unexpected {
398 use NumberImpl::*;
399 match self.n {
400 PosInt(u) => Unexpected::Unsigned(u),
401 NegInt(i) => Unexpected::Signed(i),
402 Float(f) => Unexpected::Float(f),
403 }
404 }
405}