/// Represents a JSON number, whether integer or floating point. #[derive(Clone, PartialEq, Eq, Hash)] pubstruct Number {
n: N,
}
#[cfg(not(feature = "arbitrary_precision"))] #[derive(Copy, Clone)] enum N {
PosInt(u64), /// Always less than zero.
NegInt(i64), /// Always finite.
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;
impl Number { /// Returns true if the `Number` is an integer between `i64::MIN` and /// `i64::MAX`. /// /// For any Number on which `is_i64` returns true, `as_i64` is guaranteed to /// return the integer value. /// /// ``` /// # use serde_json::json; /// # /// let big = i64::MAX as u64 + 10; /// let v = json!({ "a": 64, "b": big, "c": 256.0 }); /// /// assert!(v["a"].is_i64()); /// /// // Greater than i64::MAX. /// assert!(!v["b"].is_i64()); /// /// // Numbers with a decimal point are not considered integers. /// assert!(!v["c"].is_i64()); /// ``` #[inline] pubfn is_i64(&self) -> bool { #[cfg(not(feature = "arbitrary_precision"))] matchself.n {
N::PosInt(v) => v <= i64::MAX as u64,
N::NegInt(_) => true,
N::Float(_) => false,
} #[cfg(feature = "arbitrary_precision")] self.as_i64().is_some()
}
/// Returns true if the `Number` is an integer between zero and `u64::MAX`. /// /// For any Number on which `is_u64` returns true, `as_u64` is guaranteed to /// return the integer value. /// /// ``` /// # use serde_json::json; /// # /// let v = json!({ "a": 64, "b": -64, "c": 256.0 }); /// /// assert!(v["a"].is_u64()); /// /// // Negative integer. /// assert!(!v["b"].is_u64()); /// /// // Numbers with a decimal point are not considered integers. /// assert!(!v["c"].is_u64()); /// ``` #[inline] pubfn is_u64(&self) -> bool { #[cfg(not(feature = "arbitrary_precision"))] matchself.n {
N::PosInt(_) => true,
N::NegInt(_) | N::Float(_) => false,
} #[cfg(feature = "arbitrary_precision")] self.as_u64().is_some()
}
/// Returns true if the `Number` can be represented by f64. /// /// For any Number on which `is_f64` returns true, `as_f64` is guaranteed to /// return the floating point value. /// /// Currently this function returns true if and only if both `is_i64` and /// `is_u64` return false but this is not a guarantee in the future. /// /// ``` /// # use serde_json::json; /// # /// let v = json!({ "a": 256.0, "b": 64, "c": -64 }); /// /// assert!(v["a"].is_f64()); /// /// // Integers. /// assert!(!v["b"].is_f64()); /// assert!(!v["c"].is_f64()); /// ``` #[inline] pubfn is_f64(&self) -> bool { #[cfg(not(feature = "arbitrary_precision"))] matchself.n {
N::Float(_) => true,
N::PosInt(_) | N::NegInt(_) => false,
} #[cfg(feature = "arbitrary_precision")]
{ for c inself.n.chars() { if c == '.' || c == 'e' || c == 'E' { returnself.n.parse::<f64>().ok().map_or(false, f64::is_finite);
}
} false
}
}
/// If the `Number` is an integer, represent it as i64 if possible. Returns /// None otherwise. /// /// ``` /// # use serde_json::json; /// # /// let big = i64::MAX as u64 + 10; /// let v = json!({ "a": 64, "b": big, "c": 256.0 }); /// /// assert_eq!(v["a"].as_i64(), Some(64)); /// assert_eq!(v["b"].as_i64(), None); /// assert_eq!(v["c"].as_i64(), None); /// ``` #[inline] pubfn as_i64(&self) -> Option<i64> { #[cfg(not(feature = "arbitrary_precision"))] matchself.n {
N::PosInt(n) => { if n <= i64::MAX as u64 {
Some(n as i64)
} else {
None
}
}
N::NegInt(n) => Some(n),
N::Float(_) => None,
} #[cfg(feature = "arbitrary_precision")] self.n.parse().ok()
}
/// If the `Number` is an integer, represent it as u64 if possible. Returns /// None otherwise. /// /// ``` /// # use serde_json::json; /// # /// let v = json!({ "a": 64, "b": -64, "c": 256.0 }); /// /// assert_eq!(v["a"].as_u64(), Some(64)); /// assert_eq!(v["b"].as_u64(), None); /// assert_eq!(v["c"].as_u64(), None); /// ``` #[inline] pubfn as_u64(&self) -> Option<u64> { #[cfg(not(feature = "arbitrary_precision"))] matchself.n {
N::PosInt(n) => Some(n),
N::NegInt(_) | N::Float(_) => None,
} #[cfg(feature = "arbitrary_precision")] self.n.parse().ok()
}
/// Represents the number as f64 if possible. Returns None otherwise. /// /// ``` /// # use serde_json::json; /// # /// let v = json!({ "a": 256.0, "b": 64, "c": -64 }); /// /// assert_eq!(v["a"].as_f64(), Some(256.0)); /// assert_eq!(v["b"].as_f64(), Some(64.0)); /// assert_eq!(v["c"].as_f64(), Some(-64.0)); /// ``` #[inline] pubfn as_f64(&self) -> Option<f64> { #[cfg(not(feature = "arbitrary_precision"))] matchself.n {
N::PosInt(n) => Some(n as f64),
N::NegInt(n) => Some(n as f64),
N::Float(n) => Some(n),
} #[cfg(feature = "arbitrary_precision")] self.n.parse::<f64>().ok().filter(|float| float.is_finite())
}
/// Converts a finite `f64` to a `Number`. Infinite or NaN values are not JSON /// numbers. /// /// ``` /// # use std::f64; /// # /// # use serde_json::Number; /// # /// assert!(Number::from_f64(256.0).is_some()); /// /// assert!(Number::from_f64(f64::NAN).is_none()); /// ``` #[inline] pubfn from_f64(f: f64) -> Option<Number> { if f.is_finite() { let n = { #[cfg(not(feature = "arbitrary_precision"))]
{
N::Float(f)
} #[cfg(feature = "arbitrary_precision")]
{
ryu::Buffer::new().format_finite(f).to_owned()
}
};
Some(Number { n })
} else {
None
}
}
/// Returns the exact original JSON representation that this Number was /// parsed from. /// /// For numbers constructed not via parsing, such as by `From<i32>`, returns /// the JSON representation that serde\_json would serialize for this /// number. /// /// ``` /// # use serde_json::Number; /// for value in [ /// "7", /// "12.34", /// "34e-56789", /// "0.0123456789000000012345678900000001234567890000123456789", /// "343412345678910111213141516171819202122232425262728293034", /// "-343412345678910111213141516171819202122232425262728293031", /// ] { /// let number: Number = serde_json::from_str(value).unwrap(); /// assert_eq!(number.as_str(), value); /// } /// ``` #[cfg(feature = "arbitrary_precision")] #[cfg_attr(docsrs, doc(cfg(feature = "arbitrary_precision")))] pubfn as_str(&self) -> &str {
&self.n
}
pub(crate) fn from_f32(f: f32) -> Option<Number> { if f.is_finite() { let n = { #[cfg(not(feature = "arbitrary_precision"))]
{
N::Float(f as f64)
} #[cfg(feature = "arbitrary_precision")]
{
ryu::Buffer::new().format_finite(f).to_owned()
}
};
Some(Number { n })
} else {
None
}
}
#[cfg(feature = "arbitrary_precision")] /// Not public API. Only tests use this. #[doc(hidden)] #[inline] pubfn from_string_unchecked(n: String) -> Self {
Number { n }
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.