]> git.proxmox.com Git - cargo.git/blobdiff - vendor/serde_json/src/number.rs
New upstream version 0.63.1
[cargo.git] / vendor / serde_json / src / number.rs
index c1476189b0734530cea7f62916f735a93e87006e..3c8f6f1bf2316d643f3a9882c8a332b7b64163ff 100644 (file)
@@ -1,28 +1,33 @@
 use crate::de::ParserNumber;
 use crate::error::Error;
-use crate::lib::*;
+#[cfg(feature = "arbitrary_precision")]
+use crate::error::ErrorCode;
+#[cfg(feature = "arbitrary_precision")]
+use alloc::borrow::ToOwned;
+#[cfg(feature = "arbitrary_precision")]
+use alloc::string::{String, ToString};
+use core::fmt::{self, Debug, Display};
+#[cfg(not(feature = "arbitrary_precision"))]
+use core::hash::{Hash, Hasher};
 use serde::de::{self, Unexpected, Visitor};
+#[cfg(feature = "arbitrary_precision")]
+use serde::de::{IntoDeserializer, MapAccess};
 use serde::{
     forward_to_deserialize_any, serde_if_integer128, Deserialize, Deserializer, Serialize,
     Serializer,
 };
 
-#[cfg(feature = "arbitrary_precision")]
-use crate::error::ErrorCode;
-#[cfg(feature = "arbitrary_precision")]
-use serde::de::{IntoDeserializer, MapAccess};
-
 #[cfg(feature = "arbitrary_precision")]
 pub(crate) const TOKEN: &str = "$serde_json::private::Number";
 
 /// Represents a JSON number, whether integer or floating point.
-#[derive(Clone, Eq, PartialEq)]
+#[derive(Clone, PartialEq, Eq, Hash)]
 pub struct Number {
     n: N,
 }
 
 #[cfg(not(feature = "arbitrary_precision"))]
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone)]
 enum N {
     PosInt(u64),
     /// Always less than zero.
@@ -31,10 +36,42 @@ enum N {
     Float(f64),
 }
 
+#[cfg(not(feature = "arbitrary_precision"))]
+impl PartialEq for N {
+    fn eq(&self, other: &Self) -> bool {
+        match (self, other) {
+            (N::PosInt(a), N::PosInt(b)) => a == b,
+            (N::NegInt(a), N::NegInt(b)) => a == b,
+            (N::Float(a), N::Float(b)) => a == b,
+            _ => false,
+        }
+    }
+}
+
 // Implementing Eq is fine since any float values are always finite.
 #[cfg(not(feature = "arbitrary_precision"))]
 impl Eq for N {}
 
+#[cfg(not(feature = "arbitrary_precision"))]
+impl Hash for N {
+    fn hash<H: Hasher>(&self, h: &mut H) {
+        match *self {
+            N::PosInt(i) => i.hash(h),
+            N::NegInt(i) => i.hash(h),
+            N::Float(f) => {
+                if f == 0.0f64 {
+                    // There are 2 zero representations, +0 and -0, which
+                    // compare equal but have different bits. We use the +0 hash
+                    // for both so that hash(+0) == hash(-0).
+                    0.0f64.to_bits().hash(h);
+                } else {
+                    f.to_bits().hash(h);
+                }
+            }
+        }
+    }
+}
+
 #[cfg(feature = "arbitrary_precision")]
 type N = String;
 
@@ -130,7 +167,7 @@ impl Number {
         {
             for c in self.n.chars() {
                 if c == '.' || c == 'e' || c == 'E' {
-                    return self.n.parse::<f64>().ok().map_or(false, |f| f.is_finite());
+                    return self.n.parse::<f64>().ok().map_or(false, f64::is_finite);
                 }
             }
             false
@@ -254,13 +291,13 @@ impl Number {
     }
 }
 
-impl fmt::Display for Number {
+impl Display for Number {
     #[cfg(not(feature = "arbitrary_precision"))]
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         match self.n {
-            N::PosInt(u) => Display::fmt(&u, formatter),
-            N::NegInt(i) => Display::fmt(&i, formatter),
-            N::Float(f) => Display::fmt(&f, formatter),
+            N::PosInt(u) => formatter.write_str(itoa::Buffer::new().format(u)),
+            N::NegInt(i) => formatter.write_str(itoa::Buffer::new().format(i)),
+            N::Float(f) => formatter.write_str(ryu::Buffer::new().format_finite(f)),
         }
     }
 
@@ -271,29 +308,8 @@ impl fmt::Display for Number {
 }
 
 impl Debug for Number {
-    #[cfg(not(feature = "arbitrary_precision"))]
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        let mut debug = formatter.debug_tuple("Number");
-        match self.n {
-            N::PosInt(i) => {
-                debug.field(&i);
-            }
-            N::NegInt(i) => {
-                debug.field(&i);
-            }
-            N::Float(f) => {
-                debug.field(&f);
-            }
-        }
-        debug.finish()
-    }
-
-    #[cfg(feature = "arbitrary_precision")]
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        formatter
-            .debug_tuple("Number")
-            .field(&format_args!("{}", self.n))
-            .finish()
+        write!(formatter, "Number({})", self)
     }
 }
 
@@ -718,13 +734,15 @@ impl_from_signed!(i8, i16, i32, i64, isize);
 serde_if_integer128! {
     impl From<i128> for Number {
         fn from(i: i128) -> Self {
-            Number { n: i.to_string() }
+            let n = itoa::Buffer::new().format(i).to_owned();
+            Number { n }
         }
     }
 
     impl From<u128> for Number {
         fn from(u: u128) -> Self {
-            Number { n: u.to_string() }
+            let n = itoa::Buffer::new().format(u).to_owned();
+            Number { n }
         }
     }
 }