]> git.proxmox.com Git - cargo.git/blob - vendor/serde_json-1.0.3/src/number.rs
New upstream version 0.23.0
[cargo.git] / vendor / serde_json-1.0.3 / src / number.rs
1 // Copyright 2017 Serde Developers
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8
9 use error::Error;
10 use num_traits::NumCast;
11 use serde::de::{self, Visitor, Unexpected};
12 use serde::{Serialize, Serializer, Deserialize, Deserializer};
13 use std::fmt::{self, Debug, Display};
14 use std::i64;
15
16 /// Represents a JSON number, whether integer or floating point.
17 #[derive(Clone, PartialEq)]
18 pub struct Number {
19 n: N,
20 }
21
22 // "N" is a prefix of "NegInt"... this is a false positive.
23 // https://github.com/Manishearth/rust-clippy/issues/1241
24 #[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
25 #[derive(Copy, Clone, Debug, PartialEq)]
26 enum N {
27 PosInt(u64),
28 /// Always less than zero.
29 NegInt(i64),
30 /// Always finite.
31 Float(f64),
32 }
33
34 impl Number {
35 /// Returns true if the `Number` is an integer between `i64::MIN` and
36 /// `i64::MAX`.
37 ///
38 /// For any Number on which `is_i64` returns true, `as_i64` is guaranteed to
39 /// return the integer value.
40 ///
41 /// ```rust
42 /// # #[macro_use]
43 /// # extern crate serde_json;
44 /// #
45 /// # use std::i64;
46 /// #
47 /// # fn main() {
48 /// let big = i64::MAX as u64 + 10;
49 /// let v = json!({ "a": 64, "b": big, "c": 256.0 });
50 ///
51 /// assert!(v["a"].is_i64());
52 ///
53 /// // Greater than i64::MAX.
54 /// assert!(!v["b"].is_i64());
55 ///
56 /// // Numbers with a decimal point are not considered integers.
57 /// assert!(!v["c"].is_i64());
58 /// # }
59 /// ```
60 #[inline]
61 pub fn is_i64(&self) -> bool {
62 match self.n {
63 N::PosInt(v) => v <= i64::MAX as u64,
64 N::NegInt(_) => true,
65 N::Float(_) => false,
66 }
67 }
68
69 /// Returns true if the `Number` is an integer between zero and `u64::MAX`.
70 ///
71 /// For any Number on which `is_u64` returns true, `as_u64` is guaranteed to
72 /// return the integer value.
73 ///
74 /// ```rust
75 /// # #[macro_use]
76 /// # extern crate serde_json;
77 /// #
78 /// # fn main() {
79 /// let v = json!({ "a": 64, "b": -64, "c": 256.0 });
80 ///
81 /// assert!(v["a"].is_u64());
82 ///
83 /// // Negative integer.
84 /// assert!(!v["b"].is_u64());
85 ///
86 /// // Numbers with a decimal point are not considered integers.
87 /// assert!(!v["c"].is_u64());
88 /// # }
89 /// ```
90 #[inline]
91 pub fn is_u64(&self) -> bool {
92 match self.n {
93 N::PosInt(_) => true,
94 N::NegInt(_) | N::Float(_) => false,
95 }
96 }
97
98 /// Returns true if the `Number` can be represented by f64.
99 ///
100 /// For any Number on which `is_f64` returns true, `as_f64` is guaranteed to
101 /// return the floating point value.
102 ///
103 /// Currently this function returns true if and only if both `is_i64` and
104 /// `is_u64` return false but this is not a guarantee in the future.
105 ///
106 /// ```rust
107 /// # #[macro_use]
108 /// # extern crate serde_json;
109 /// #
110 /// # fn main() {
111 /// let v = json!({ "a": 256.0, "b": 64, "c": -64 });
112 ///
113 /// assert!(v["a"].is_f64());
114 ///
115 /// // Integers.
116 /// assert!(!v["b"].is_f64());
117 /// assert!(!v["c"].is_f64());
118 /// # }
119 /// ```
120 #[inline]
121 pub fn is_f64(&self) -> bool {
122 match self.n {
123 N::Float(_) => true,
124 N::PosInt(_) | N::NegInt(_) => false,
125 }
126 }
127
128 /// If the `Number` is an integer, represent it as i64 if possible. Returns
129 /// None otherwise.
130 ///
131 /// ```rust
132 /// # #[macro_use]
133 /// # extern crate serde_json;
134 /// #
135 /// # use std::i64;
136 /// #
137 /// # fn main() {
138 /// let big = i64::MAX as u64 + 10;
139 /// let v = json!({ "a": 64, "b": big, "c": 256.0 });
140 ///
141 /// assert_eq!(v["a"].as_i64(), Some(64));
142 /// assert_eq!(v["b"].as_i64(), None);
143 /// assert_eq!(v["c"].as_i64(), None);
144 /// # }
145 /// ```
146 #[inline]
147 pub fn as_i64(&self) -> Option<i64> {
148 match self.n {
149 N::PosInt(n) => NumCast::from(n),
150 N::NegInt(n) => Some(n),
151 N::Float(_) => None,
152 }
153 }
154
155 /// If the `Number` is an integer, represent it as u64 if possible. Returns
156 /// None otherwise.
157 ///
158 /// ```rust
159 /// # #[macro_use]
160 /// # extern crate serde_json;
161 /// #
162 /// # fn main() {
163 /// let v = json!({ "a": 64, "b": -64, "c": 256.0 });
164 ///
165 /// assert_eq!(v["a"].as_u64(), Some(64));
166 /// assert_eq!(v["b"].as_u64(), None);
167 /// assert_eq!(v["c"].as_u64(), None);
168 /// # }
169 /// ```
170 #[inline]
171 pub fn as_u64(&self) -> Option<u64> {
172 match self.n {
173 N::PosInt(n) => Some(n),
174 N::NegInt(n) => NumCast::from(n),
175 N::Float(_) => None,
176 }
177 }
178
179 /// Represents the number as f64 if possible. Returns None otherwise.
180 ///
181 /// ```rust
182 /// # #[macro_use]
183 /// # extern crate serde_json;
184 /// #
185 /// # fn main() {
186 /// let v = json!({ "a": 256.0, "b": 64, "c": -64 });
187 ///
188 /// assert_eq!(v["a"].as_f64(), Some(256.0));
189 /// assert_eq!(v["b"].as_f64(), Some(64.0));
190 /// assert_eq!(v["c"].as_f64(), Some(-64.0));
191 /// # }
192 /// ```
193 #[inline]
194 pub fn as_f64(&self) -> Option<f64> {
195 match self.n {
196 N::PosInt(n) => NumCast::from(n),
197 N::NegInt(n) => NumCast::from(n),
198 N::Float(n) => Some(n),
199 }
200 }
201
202 /// Converts a finite `f64` to a `Number`. Infinite or NaN values are not JSON
203 /// numbers.
204 ///
205 /// ```rust
206 /// # use std::f64;
207 /// #
208 /// # use serde_json::Number;
209 /// #
210 /// assert!(Number::from_f64(256.0).is_some());
211 ///
212 /// assert!(Number::from_f64(f64::NAN).is_none());
213 /// ```
214 #[inline]
215 pub fn from_f64(f: f64) -> Option<Number> {
216 if f.is_finite() {
217 Some(Number { n: N::Float(f) })
218 } else {
219 None
220 }
221 }
222 }
223
224 impl fmt::Display for Number {
225 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
226 match self.n {
227 N::PosInt(i) => Display::fmt(&i, formatter),
228 N::NegInt(i) => Display::fmt(&i, formatter),
229 N::Float(f) => Display::fmt(&f, formatter),
230 }
231 }
232 }
233
234 impl Debug for Number {
235 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
236 Debug::fmt(&self.n, formatter)
237 }
238 }
239
240 impl Serialize for Number {
241 #[inline]
242 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
243 where
244 S: Serializer,
245 {
246 match self.n {
247 N::PosInt(i) => serializer.serialize_u64(i),
248 N::NegInt(i) => serializer.serialize_i64(i),
249 N::Float(f) => serializer.serialize_f64(f),
250 }
251 }
252 }
253
254 impl<'de> Deserialize<'de> for Number {
255 #[inline]
256 fn deserialize<D>(deserializer: D) -> Result<Number, D::Error>
257 where
258 D: Deserializer<'de>,
259 {
260 struct NumberVisitor;
261
262 impl<'de> Visitor<'de> for NumberVisitor {
263 type Value = Number;
264
265 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
266 formatter.write_str("a number")
267 }
268
269 #[inline]
270 fn visit_i64<E>(self, value: i64) -> Result<Number, E> {
271 Ok(value.into())
272 }
273
274 #[inline]
275 fn visit_u64<E>(self, value: u64) -> Result<Number, E> {
276 Ok(value.into())
277 }
278
279 #[inline]
280 fn visit_f64<E>(self, value: f64) -> Result<Number, E>
281 where
282 E: de::Error,
283 {
284 Number::from_f64(value).ok_or_else(|| de::Error::custom("not a JSON number"))
285 }
286 }
287
288 deserializer.deserialize_any(NumberVisitor)
289 }
290 }
291
292 impl<'de> Deserializer<'de> for Number {
293 type Error = Error;
294
295 #[inline]
296 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
297 where
298 V: Visitor<'de>,
299 {
300 match self.n {
301 N::PosInt(i) => visitor.visit_u64(i),
302 N::NegInt(i) => visitor.visit_i64(i),
303 N::Float(f) => visitor.visit_f64(f),
304 }
305 }
306
307 forward_to_deserialize_any! {
308 bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
309 byte_buf option unit unit_struct newtype_struct seq tuple
310 tuple_struct map struct enum identifier ignored_any
311 }
312 }
313
314 impl<'de, 'a> Deserializer<'de> for &'a Number {
315 type Error = Error;
316
317 #[inline]
318 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
319 where
320 V: Visitor<'de>,
321 {
322 match self.n {
323 N::PosInt(i) => visitor.visit_u64(i),
324 N::NegInt(i) => visitor.visit_i64(i),
325 N::Float(f) => visitor.visit_f64(f),
326 }
327 }
328
329 forward_to_deserialize_any! {
330 bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
331 byte_buf option unit unit_struct newtype_struct seq tuple
332 tuple_struct map struct enum identifier ignored_any
333 }
334 }
335
336 macro_rules! from_signed {
337 ($($signed_ty:ident)*) => {
338 $(
339 impl From<$signed_ty> for Number {
340 #[inline]
341 fn from(i: $signed_ty) -> Self {
342 if i < 0 {
343 Number { n: N::NegInt(i as i64) }
344 } else {
345 Number { n: N::PosInt(i as u64) }
346 }
347 }
348 }
349 )*
350 };
351 }
352
353 macro_rules! from_unsigned {
354 ($($unsigned_ty:ident)*) => {
355 $(
356 impl From<$unsigned_ty> for Number {
357 #[inline]
358 fn from(u: $unsigned_ty) -> Self {
359 Number { n: N::PosInt(u as u64) }
360 }
361 }
362 )*
363 };
364 }
365
366 from_signed!(i8 i16 i32 i64 isize);
367 from_unsigned!(u8 u16 u32 u64 usize);
368
369 impl Number {
370 // Not public API. Should be pub(crate).
371 #[doc(hidden)]
372 pub fn unexpected(&self) -> Unexpected {
373 match self.n {
374 N::PosInt(u) => Unexpected::Unsigned(u),
375 N::NegInt(i) => Unexpected::Signed(i),
376 N::Float(f) => Unexpected::Float(f),
377 }
378 }
379 }