/// 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. 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. 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. 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. 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. 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. 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 serde_json::Number; /// # /// assert!(Number::from_f64(256.0).is_some()); /// /// assert!(Number::from_f64(f64::NAN).is_none()); /// ``` 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")]
{
zmij::Buffer::new().format_finite(f).to_owned()
}
};
Some(Number { n })
} else {
None
}
}
/// If the `Number` is an integer, represent it as i128 if possible. Returns /// None otherwise. pubfn as_i128(&self) -> Option<i128> { #[cfg(not(feature = "arbitrary_precision"))] matchself.n {
N::PosInt(n) => Some(n as i128),
N::NegInt(n) => Some(n as i128),
N::Float(_) => None,
} #[cfg(feature = "arbitrary_precision")] self.n.parse().ok()
}
/// If the `Number` is an integer, represent it as u128 if possible. Returns /// None otherwise. pubfn as_u128(&self) -> Option<u128> { #[cfg(not(feature = "arbitrary_precision"))] matchself.n {
N::PosInt(n) => Some(n as u128),
N::NegInt(_) | N::Float(_) => None,
} #[cfg(feature = "arbitrary_precision")] self.n.parse().ok()
}
/// Converts an `i128` to a `Number`. Numbers smaller than i64::MIN or /// larger than u64::MAX can only be represented in `Number` if serde_json's /// "arbitrary_precision" feature is enabled. /// /// ``` /// # use serde_json::Number; /// # /// assert!(Number::from_i128(256).is_some()); /// ``` pubfn from_i128(i: i128) -> Option<Number> { let n = { #[cfg(not(feature = "arbitrary_precision"))]
{ iflet Ok(u) = u64::try_from(i) {
N::PosInt(u)
} elseiflet Ok(i) = i64::try_from(i) {
N::NegInt(i)
} else { return None;
}
} #[cfg(feature = "arbitrary_precision")]
{
i.to_string()
}
};
Some(Number { n })
}
/// Converts a `u128` to a `Number`. Numbers greater than u64::MAX can only /// be represented in `Number` if serde_json's "arbitrary_precision" feature /// is enabled. /// /// ``` /// # use serde_json::Number; /// # /// assert!(Number::from_u128(256).is_some()); /// ``` pubfn from_u128(i: u128) -> Option<Number> { let n = { #[cfg(not(feature = "arbitrary_precision"))]
{ iflet Ok(u) = u64::try_from(i) {
N::PosInt(u)
} else { return None;
}
} #[cfg(feature = "arbitrary_precision")]
{
i.to_string()
}
};
Some(Number { n })
}
/// Returns the JSON representation that this Number was parsed from. /// /// When parsing with serde_json's `arbitrary_precision` feature enabled, /// positive exponents are normalized to include an explicit `+` sign so /// that `1e140` becomes `1e+140`. /// /// 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")]
{
zmij::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 }
}
}
fn visit_i128<E>(self, value: i128) -> Result<Number, E> where
E: de::Error,
{
Number::from_i128(value)
.ok_or_else(|| de::Error::custom("JSON number out of range"))
}
fn visit_u128<E>(self, value: u128) -> Result<Number, E> where
E: de::Error,
{
Number::from_u128(value)
.ok_or_else(|| de::Error::custom("JSON number out of range"))
}
fn visit_f64<E>(self, value: f64) -> Result<Number, E> where
E: de::Error,
{
Number::from_f64(value).ok_or_else(|| de::Error::custom("not a JSON number"))
}
#[cfg(feature = "arbitrary_precision")] fn visit_map<V>(self, mut visitor: V) -> Result<Number, V::Error> where
V: de::MapAccess<'de>,
{ let value = tri!(visitor.next_key::<NumberKey>()); if value.is_none() { return Err(de::Error::invalid_type(Unexpected::Map, &self));
} let v: NumberFromString = tri!(visitor.next_value());
Ok(v.value)
}
}
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.