]> git.proxmox.com Git - rustc.git/blob - src/vendor/serde_json-0.9.10/src/number.rs
New upstream version 1.19.0+dfsg3
[rustc.git] / src / vendor / serde_json-0.9.10 / src / number.rs
1 use error::Error;
2 use num_traits::NumCast;
3 use serde::de::{self, Visitor};
4 use serde::{Serialize, Serializer, Deserialize, Deserializer};
5 use std::fmt::{self, Debug, Display};
6 use std::i64;
7
8 /// Represents a JSON number, whether integer or floating point.
9 #[derive(Clone, PartialEq)]
10 pub struct Number {
11 n: N,
12 }
13
14 // "N" is a prefix of "NegInt"... this is a false positive.
15 // https://github.com/Manishearth/rust-clippy/issues/1241
16 #[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
17 #[derive(Copy, Clone, Debug, PartialEq)]
18 enum N {
19 PosInt(u64),
20 /// Always less than zero.
21 NegInt(i64),
22 /// Always finite.
23 Float(f64),
24 }
25
26 impl Number {
27 /// Returns `true` if the number can be represented as `i64`.
28 #[inline]
29 pub fn is_i64(&self) -> bool {
30 match self.n {
31 N::PosInt(v) => v <= i64::MAX as u64,
32 N::NegInt(_) => true,
33 N::Float(_) => false,
34 }
35 }
36
37 /// Returns `true` if the number can be represented as `u64`.
38 #[inline]
39 pub fn is_u64(&self) -> bool {
40 match self.n {
41 N::PosInt(_) => true,
42 N::NegInt(_) | N::Float(_) => false,
43 }
44 }
45
46 /// Returns `true` if the number can be represented as `f64`.
47 #[inline]
48 pub fn is_f64(&self) -> bool {
49 match self.n {
50 N::Float(_) => true,
51 N::PosInt(_) | N::NegInt(_) => false,
52 }
53 }
54
55 /// Returns the number represented as `i64` if possible, or else `None`.
56 #[inline]
57 pub fn as_i64(&self) -> Option<i64> {
58 match self.n {
59 N::PosInt(n) => NumCast::from(n),
60 N::NegInt(n) => Some(n),
61 N::Float(_) => None,
62 }
63 }
64
65 /// Returns the number represented as `u64` if possible, or else `None`.
66 #[inline]
67 pub fn as_u64(&self) -> Option<u64> {
68 match self.n {
69 N::PosInt(n) => Some(n),
70 N::NegInt(n) => NumCast::from(n),
71 N::Float(_) => None,
72 }
73 }
74
75 /// Returns the number represented as `f64` if possible, or else `None`.
76 #[inline]
77 pub fn as_f64(&self) -> Option<f64> {
78 match self.n {
79 N::PosInt(n) => NumCast::from(n),
80 N::NegInt(n) => NumCast::from(n),
81 N::Float(n) => Some(n),
82 }
83 }
84
85 /// Converts a finite `f64` to a `Number`. Infinite or NaN values are not JSON
86 /// numbers.
87 #[inline]
88 pub fn from_f64(f: f64) -> Option<Number> {
89 if f.is_finite() {
90 Some(Number { n: N::Float(f) })
91 } else {
92 None
93 }
94 }
95 }
96
97 impl fmt::Display for Number {
98 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
99 match self.n {
100 N::PosInt(i) => Display::fmt(&i, formatter),
101 N::NegInt(i) => Display::fmt(&i, formatter),
102 N::Float(f) => Display::fmt(&f, formatter),
103 }
104 }
105 }
106
107 impl Debug for Number {
108 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
109 Debug::fmt(&self.n, formatter)
110 }
111 }
112
113 impl Serialize for Number {
114 #[inline]
115 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
116 where S: Serializer
117 {
118 match self.n {
119 N::PosInt(i) => serializer.serialize_u64(i),
120 N::NegInt(i) => serializer.serialize_i64(i),
121 N::Float(f) => serializer.serialize_f64(f),
122 }
123 }
124 }
125
126 impl Deserialize for Number {
127 #[inline]
128 fn deserialize<D>(deserializer: D) -> Result<Number, D::Error>
129 where D: Deserializer
130 {
131 struct NumberVisitor;
132
133 impl Visitor for NumberVisitor {
134 type Value = Number;
135
136 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
137 formatter.write_str("a number")
138 }
139
140 #[inline]
141 fn visit_i64<E>(self, value: i64) -> Result<Number, E> {
142 Ok(value.into())
143 }
144
145 #[inline]
146 fn visit_u64<E>(self, value: u64) -> Result<Number, E> {
147 Ok(value.into())
148 }
149
150 #[inline]
151 fn visit_f64<E>(self, value: f64) -> Result<Number, E>
152 where E: de::Error
153 {
154 Number::from_f64(value).ok_or_else(|| de::Error::custom("not a JSON number"))
155 }
156 }
157
158 deserializer.deserialize(NumberVisitor)
159 }
160 }
161
162 impl Deserializer for Number {
163 type Error = Error;
164
165 #[inline]
166 fn deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
167 where V: Visitor
168 {
169 match self.n {
170 N::PosInt(i) => visitor.visit_u64(i),
171 N::NegInt(i) => visitor.visit_i64(i),
172 N::Float(f) => visitor.visit_f64(f),
173 }
174 }
175
176 forward_to_deserialize! {
177 bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
178 seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
179 tuple_struct struct struct_field tuple enum ignored_any
180 }
181 }
182
183 impl<'a> Deserializer for &'a Number {
184 type Error = Error;
185
186 #[inline]
187 fn deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
188 where V: Visitor
189 {
190 match self.n {
191 N::PosInt(i) => visitor.visit_u64(i),
192 N::NegInt(i) => visitor.visit_i64(i),
193 N::Float(f) => visitor.visit_f64(f),
194 }
195 }
196
197 forward_to_deserialize! {
198 bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
199 seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
200 tuple_struct struct struct_field tuple enum ignored_any
201 }
202 }
203
204 macro_rules! from_signed {
205 ($($signed_ty:ident)*) => {
206 $(
207 impl From<$signed_ty> for Number {
208 #[inline]
209 fn from(i: $signed_ty) -> Self {
210 if i < 0 {
211 Number { n: N::NegInt(i as i64) }
212 } else {
213 Number { n: N::PosInt(i as u64) }
214 }
215 }
216 }
217 )*
218 };
219 }
220
221 macro_rules! from_unsigned {
222 ($($unsigned_ty:ident)*) => {
223 $(
224 impl From<$unsigned_ty> for Number {
225 #[inline]
226 fn from(u: $unsigned_ty) -> Self {
227 Number { n: N::PosInt(u as u64) }
228 }
229 }
230 )*
231 };
232 }
233
234 from_signed!(i8 i16 i32 i64 isize);
235 from_unsigned!(u8 u16 u32 u64 usize);