1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use core::fmt::{Debug, Formatter, Result};
/// Represents a JSON number.
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Number(pub(crate) Kind);
#[derive(Clone, Copy, PartialEq)]
pub enum Kind {
Unsigned(u64),
Signed(i64),
Float(f64),
}
impl Number {
/// Creates JSON number from `u64`.
#[inline(always)]
pub fn from_u64(val: u64) -> Self {
Self(Kind::Unsigned(val))
}
/// Creates JSON number from `i64`.
#[inline(always)]
pub fn from_i64(val: i64) -> Self {
Self(Kind::Signed(val))
}
/// Creates JSON number from `f64`.
///
/// Returns `None` if the number is infinite or NaN.
#[inline]
pub fn from_f64(val: f64) -> Option<Self> {
match val.is_finite() {
true => Some(Self(Kind::Float(val))),
_ => None,
}
}
/// Returns the number as `u64`, or `None` if it is not a positive integer.
pub fn as_u64(&self) -> Option<u64> {
match self.0 {
Kind::Unsigned(v) => Some(v),
_ => None,
}
}
/// Returns the number as `i64`, or `None` if it is not a negative integer.
pub fn as_i64(&self) -> Option<i64> {
match self.0 {
Kind::Signed(v) => Some(v),
_ => None,
}
}
/// Returns the number as `f64`, or `None` if it is not a float.
pub fn as_f64(&self) -> Option<f64> {
match self.0 {
Kind::Float(v) => Some(v),
_ => None,
}
}
/// Returns `true` if the number is an unsigned integer or a positive integer.
pub fn is_u64(&self) -> bool {
self.as_u64().is_some()
}
/// Returns `true` if the number is a signed integer or a negative integer.
pub fn is_i64(&self) -> bool {
self.as_i64().is_some()
}
/// Returns `true` if the number is a float.
pub fn is_f64(&self) -> bool {
self.as_f64().is_some()
}
}
impl Eq for Kind {}
impl Debug for Number {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match self.0 {
Kind::Unsigned(v) => v.fmt(f),
Kind::Signed(v) => v.fmt(f),
Kind::Float(v) => v.fmt(f),
}
}
}