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