1 // Copyright 2017 Serde Developers
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.
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}
;
16 /// Represents a JSON number, whether integer or floating point.
17 #[derive(Clone, PartialEq)]
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)]
28 /// Always less than zero.
35 /// Returns true if the `Number` is an integer between `i64::MIN` and
38 /// For any Number on which `is_i64` returns true, `as_i64` is guaranteed to
39 /// return the integer value.
43 /// # extern crate serde_json;
48 /// let big = i64::MAX as u64 + 10;
49 /// let v = json!({ "a": 64, "b": big, "c": 256.0 });
51 /// assert!(v["a"].is_i64());
53 /// // Greater than i64::MAX.
54 /// assert!(!v["b"].is_i64());
56 /// // Numbers with a decimal point are not considered integers.
57 /// assert!(!v["c"].is_i64());
61 pub fn is_i64(&self) -> bool
{
63 N
::PosInt(v
) => v
<= i64::MAX
as u64,
69 /// Returns true if the `Number` is an integer between zero and `u64::MAX`.
71 /// For any Number on which `is_u64` returns true, `as_u64` is guaranteed to
72 /// return the integer value.
76 /// # extern crate serde_json;
79 /// let v = json!({ "a": 64, "b": -64, "c": 256.0 });
81 /// assert!(v["a"].is_u64());
83 /// // Negative integer.
84 /// assert!(!v["b"].is_u64());
86 /// // Numbers with a decimal point are not considered integers.
87 /// assert!(!v["c"].is_u64());
91 pub fn is_u64(&self) -> bool
{
94 N
::NegInt(_
) | N
::Float(_
) => false,
98 /// Returns true if the `Number` can be represented by f64.
100 /// For any Number on which `is_f64` returns true, `as_f64` is guaranteed to
101 /// return the floating point value.
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.
108 /// # extern crate serde_json;
111 /// let v = json!({ "a": 256.0, "b": 64, "c": -64 });
113 /// assert!(v["a"].is_f64());
116 /// assert!(!v["b"].is_f64());
117 /// assert!(!v["c"].is_f64());
121 pub fn is_f64(&self) -> bool
{
124 N
::PosInt(_
) | N
::NegInt(_
) => false,
128 /// If the `Number` is an integer, represent it as i64 if possible. Returns
133 /// # extern crate serde_json;
138 /// let big = i64::MAX as u64 + 10;
139 /// let v = json!({ "a": 64, "b": big, "c": 256.0 });
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);
147 pub fn as_i64(&self) -> Option
<i64> {
149 N
::PosInt(n
) => NumCast
::from(n
),
150 N
::NegInt(n
) => Some(n
),
155 /// If the `Number` is an integer, represent it as u64 if possible. Returns
160 /// # extern crate serde_json;
163 /// let v = json!({ "a": 64, "b": -64, "c": 256.0 });
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);
171 pub fn as_u64(&self) -> Option
<u64> {
173 N
::PosInt(n
) => Some(n
),
174 N
::NegInt(n
) => NumCast
::from(n
),
179 /// Represents the number as f64 if possible. Returns None otherwise.
183 /// # extern crate serde_json;
186 /// let v = json!({ "a": 256.0, "b": 64, "c": -64 });
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));
194 pub fn as_f64(&self) -> Option
<f64> {
196 N
::PosInt(n
) => NumCast
::from(n
),
197 N
::NegInt(n
) => NumCast
::from(n
),
198 N
::Float(n
) => Some(n
),
202 /// Converts a finite `f64` to a `Number`. Infinite or NaN values are not JSON
208 /// # use serde_json::Number;
210 /// assert!(Number::from_f64(256.0).is_some());
212 /// assert!(Number::from_f64(f64::NAN).is_none());
215 pub fn from_f64(f
: f64) -> Option
<Number
> {
217 Some(Number { n: N::Float(f) }
)
224 impl fmt
::Display
for Number
{
225 fn fmt(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
227 N
::PosInt(i
) => Display
::fmt(&i
, formatter
),
228 N
::NegInt(i
) => Display
::fmt(&i
, formatter
),
229 N
::Float(f
) => Display
::fmt(&f
, formatter
),
234 impl Debug
for Number
{
235 fn fmt(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
236 Debug
::fmt(&self.n
, formatter
)
240 impl Serialize
for Number
{
242 fn serialize
<S
>(&self, serializer
: S
) -> Result
<S
::Ok
, S
::Error
>
247 N
::PosInt(i
) => serializer
.serialize_u64(i
),
248 N
::NegInt(i
) => serializer
.serialize_i64(i
),
249 N
::Float(f
) => serializer
.serialize_f64(f
),
254 impl<'de
> Deserialize
<'de
> for Number
{
256 fn deserialize
<D
>(deserializer
: D
) -> Result
<Number
, D
::Error
>
258 D
: Deserializer
<'de
>,
260 struct NumberVisitor
;
262 impl<'de
> Visitor
<'de
> for NumberVisitor
{
265 fn expecting(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
266 formatter
.write_str("a number")
270 fn visit_i64
<E
>(self, value
: i64) -> Result
<Number
, E
> {
275 fn visit_u64
<E
>(self, value
: u64) -> Result
<Number
, E
> {
280 fn visit_f64
<E
>(self, value
: f64) -> Result
<Number
, E
>
284 Number
::from_f64(value
).ok_or_else(|| de
::Error
::custom("not a JSON number"))
288 deserializer
.deserialize_any(NumberVisitor
)
292 impl<'de
> Deserializer
<'de
> for Number
{
296 fn deserialize_any
<V
>(self, visitor
: V
) -> Result
<V
::Value
, Error
>
301 N
::PosInt(i
) => visitor
.visit_u64(i
),
302 N
::NegInt(i
) => visitor
.visit_i64(i
),
303 N
::Float(f
) => visitor
.visit_f64(f
),
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
314 impl<'de
, 'a
> Deserializer
<'de
> for &'a Number
{
318 fn deserialize_any
<V
>(self, visitor
: V
) -> Result
<V
::Value
, Error
>
323 N
::PosInt(i
) => visitor
.visit_u64(i
),
324 N
::NegInt(i
) => visitor
.visit_i64(i
),
325 N
::Float(f
) => visitor
.visit_f64(f
),
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
336 macro_rules
! from_signed
{
337 ($
($signed_ty
:ident
)*) => {
339 impl From
<$signed_ty
> for Number
{
341 fn from(i
: $signed_ty
) -> Self {
343 Number { n: N::NegInt(i as i64) }
345 Number { n: N::PosInt(i as u64) }
353 macro_rules
! from_unsigned
{
354 ($
($unsigned_ty
:ident
)*) => {
356 impl From
<$unsigned_ty
> for Number
{
358 fn from(u
: $unsigned_ty
) -> Self {
359 Number { n: N::PosInt(u as u64) }
366 from_signed
!(i8 i16 i32 i64 isize);
367 from_unsigned
!(u8 u16 u32 u64 usize);
370 // Not public API. Should be pub(crate).
372 pub fn unexpected(&self) -> Unexpected
{
374 N
::PosInt(u
) => Unexpected
::Unsigned(u
),
375 N
::NegInt(i
) => Unexpected
::Signed(i
),
376 N
::Float(f
) => Unexpected
::Float(f
),