Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: serde-rs/json
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0.129
Choose a base ref
...
head repository: serde-rs/json
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.0.130
Choose a head ref

Commits on Jun 17, 2024

  1. Add i128 deserialization

    Implemented serde::de::Visitor::visit_i128.
    This fixes compatability with Ipld::Integer when using DagJsonCodec.
    druide committed Jun 17, 2024
    Copy the full SHA
    168ef4b View commit details
  2. Fix tests

    druide committed Jun 17, 2024
    Copy the full SHA
    4f12af0 View commit details

Commits on Oct 18, 2024

  1. Copy the full SHA
    8ceb824 View commit details
  2. Merge pull request #1141 from druide/master

    Add i128 deserialization
    dtolnay authored Oct 18, 2024
    Copy the full SHA
    29f4a47 View commit details
  3. Format PR 1141 with rustfmt

    dtolnay committed Oct 18, 2024
    Copy the full SHA
    5fab5fc View commit details
  4. Copy the full SHA
    eb9ce29 View commit details
  5. Merge pull request #1200 from dtolnay/from128

    Delete unreachable branch from Number::from_i128
    dtolnay authored Oct 18, 2024
    Copy the full SHA
    22973d2 View commit details
  6. Copy the full SHA
    c3149ef View commit details
  7. Copy the full SHA
    f699506 View commit details
  8. Merge pull request #1201 from dtolnay/from128

    Allow arbitrarily large i128 in arbitrary_precision mode
    dtolnay authored Oct 18, 2024
    Copy the full SHA
    be67b7e View commit details
  9. Copy the full SHA
    e64c368 View commit details
  10. Copy the full SHA
    f3e2c48 View commit details
  11. Merge pull request #1202 from dtolnay/useprimitive

    Delete unneeded imports in doc code
    dtolnay authored Oct 18, 2024
    Copy the full SHA
    b4df0f8 View commit details
  12. Copy the full SHA
    fb12a9d View commit details
  13. Delete Value::as_i128

    This is adequately supported by `value.as_number().and_then(Number::as_i128)`
    dtolnay committed Oct 18, 2024
    Copy the full SHA
    1a944f4 View commit details
  14. Delete Number conversion example code

    All of these are actually calling methods on Value, not Number. The
    example code on Value methods is adequate without duplicating them to
    Number.
    dtolnay committed Oct 18, 2024
    Copy the full SHA
    95f55f3 View commit details
  15. Copy the full SHA
    be68eab View commit details
  16. Merge pull request #1203 from dtolnay/i128err

    Return error instead of Null if i128 deserialized to Value is out of range
    dtolnay authored Oct 18, 2024
    Copy the full SHA
    7e45e3d View commit details
  17. Add Number u128 conversions

    dtolnay committed Oct 18, 2024
    Copy the full SHA
    d86703f View commit details
  18. Merge pull request #1204 from dtolnay/u128

    Add Number u128 conversions
    dtolnay authored Oct 18, 2024
    Copy the full SHA
    2a2adb1 View commit details
  19. Release 1.0.130

    dtolnay committed Oct 18, 2024
    Copy the full SHA
    2825e15 View commit details
Showing with 122 additions and 95 deletions.
  1. +1 −1 Cargo.toml
  2. +1 −1 src/lib.rs
  3. +3 −2 src/map.rs
  4. +101 −91 src/number.rs
  5. +16 −0 src/value/de.rs
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "serde_json"
version = "1.0.129"
version = "1.0.130"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
categories = ["encoding", "parser-implementations", "no-std"]
description = "A JSON serialization file format"
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -299,7 +299,7 @@
//! [macro]: crate::json
//! [`serde-json-core`]: https://github.com/rust-embedded-community/serde-json-core
#![doc(html_root_url = "https://docs.rs/serde_json/1.0.129")]
#![doc(html_root_url = "https://docs.rs/serde_json/1.0.130")]
// Ignored clippy lints
#![allow(
clippy::collapsible_else_if,
5 changes: 3 additions & 2 deletions src/map.rs
Original file line number Diff line number Diff line change
@@ -362,9 +362,10 @@ impl Map<String, Value> {
///
/// Other maps nested within the values of this map are not sorted. If you
/// need the entire data structure to be sorted at all levels, you must also
/// call `map.`[`values_mut`]`().for_each(`[`Value::sort_all_objects`]`)`.
/// call
/// <code>map.[values_mut]\().for_each([Value::sort_all_objects])</code>.
///
/// [`values_mut`]: Map::values_mut
/// [values_mut]: Map::values_mut
#[inline]
pub fn sort_keys(&mut self) {
#[cfg(feature = "preserve_order")]
192 changes: 101 additions & 91 deletions src/number.rs
Original file line number Diff line number Diff line change
@@ -78,22 +78,6 @@ impl Number {
///
/// 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]
pub fn is_i64(&self) -> bool {
#[cfg(not(feature = "arbitrary_precision"))]
match self.n {
@@ -109,21 +93,6 @@ impl Number {
///
/// 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]
pub fn is_u64(&self) -> bool {
#[cfg(not(feature = "arbitrary_precision"))]
match self.n {
@@ -141,19 +110,6 @@ impl Number {
///
/// 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]
pub fn is_f64(&self) -> bool {
#[cfg(not(feature = "arbitrary_precision"))]
match self.n {
@@ -173,18 +129,6 @@ impl Number {

/// 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]
pub fn as_i64(&self) -> Option<i64> {
#[cfg(not(feature = "arbitrary_precision"))]
match self.n {
@@ -204,17 +148,6 @@ impl Number {

/// 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]
pub fn as_u64(&self) -> Option<u64> {
#[cfg(not(feature = "arbitrary_precision"))]
match self.n {
@@ -226,17 +159,6 @@ impl Number {
}

/// 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]
pub fn as_f64(&self) -> Option<f64> {
#[cfg(not(feature = "arbitrary_precision"))]
match self.n {
@@ -252,15 +174,12 @@ impl Number {
/// 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]
pub fn from_f64(f: f64) -> Option<Number> {
if f.is_finite() {
let n = {
@@ -279,6 +198,87 @@ impl Number {
}
}

/// If the `Number` is an integer, represent it as i128 if possible. Returns
/// None otherwise.
pub fn as_i128(&self) -> Option<i128> {
#[cfg(not(feature = "arbitrary_precision"))]
match self.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.
pub fn as_u128(&self) -> Option<u128> {
#[cfg(not(feature = "arbitrary_precision"))]
match self.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());
/// ```
pub fn from_i128(i: i128) -> Option<Number> {
let n = {
#[cfg(not(feature = "arbitrary_precision"))]
{
if let Ok(u) = u64::try_from(i) {
N::PosInt(u)
} else if let 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());
/// ```
pub fn from_u128(i: u128) -> Option<Number> {
let n = {
#[cfg(not(feature = "arbitrary_precision"))]
{
if let Ok(u) = u64::try_from(i) {
N::PosInt(u)
} else {
return None;
}
}
#[cfg(feature = "arbitrary_precision")]
{
i.to_string()
}
};
Some(Number { n })
}

/// Returns the exact original JSON representation that this Number was
/// parsed from.
///
@@ -368,7 +368,6 @@ impl Debug for Number {

impl Serialize for Number {
#[cfg(not(feature = "arbitrary_precision"))]
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
@@ -381,7 +380,6 @@ impl Serialize for Number {
}

#[cfg(feature = "arbitrary_precision")]
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
@@ -409,17 +407,30 @@ impl<'de> Deserialize<'de> for Number {
formatter.write_str("a JSON number")
}

#[inline]
fn visit_i64<E>(self, value: i64) -> Result<Number, E> {
Ok(value.into())
}

#[inline]
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_u64<E>(self, value: u64) -> Result<Number, E> {
Ok(value.into())
}

#[inline]
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,
@@ -428,7 +439,6 @@ impl<'de> Deserialize<'de> for Number {
}

#[cfg(feature = "arbitrary_precision")]
#[inline]
fn visit_map<V>(self, mut visitor: V) -> Result<Number, V::Error>
where
V: de::MapAccess<'de>,
@@ -522,7 +532,6 @@ fn invalid_number() -> Error {
macro_rules! deserialize_any {
(@expand [$($num_string:tt)*]) => {
#[cfg(not(feature = "arbitrary_precision"))]
#[inline]
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
@@ -535,14 +544,17 @@ macro_rules! deserialize_any {
}

#[cfg(feature = "arbitrary_precision")]
#[inline]
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
where V: Visitor<'de>
{
if let Some(u) = self.as_u64() {
return visitor.visit_u64(u);
} else if let Some(i) = self.as_i64() {
return visitor.visit_i64(i);
} else if let Some(u) = self.as_u128() {
return visitor.visit_u128(u);
} else if let Some(i) = self.as_i128() {
return visitor.visit_i128(i);
} else if let Some(f) = self.as_f64() {
if ryu::Buffer::new().format_finite(f) == self.n || f.to_string() == self.n {
return visitor.visit_f64(f);
@@ -728,7 +740,6 @@ macro_rules! impl_from_unsigned {
) => {
$(
impl From<$ty> for Number {
#[inline]
fn from(u: $ty) -> Self {
let n = {
#[cfg(not(feature = "arbitrary_precision"))]
@@ -751,7 +762,6 @@ macro_rules! impl_from_signed {
) => {
$(
impl From<$ty> for Number {
#[inline]
fn from(i: $ty) -> Self {
let n = {
#[cfg(not(feature = "arbitrary_precision"))]
16 changes: 16 additions & 0 deletions src/value/de.rs
Original file line number Diff line number Diff line change
@@ -44,11 +44,27 @@ impl<'de> Deserialize<'de> for Value {
Ok(Value::Number(value.into()))
}

fn visit_i128<E>(self, value: i128) -> Result<Value, E>
where
E: serde::de::Error,
{
let de = serde::de::value::I128Deserializer::new(value);
Number::deserialize(de).map(Value::Number)
}

#[inline]
fn visit_u64<E>(self, value: u64) -> Result<Value, E> {
Ok(Value::Number(value.into()))
}

fn visit_u128<E>(self, value: u128) -> Result<Value, E>
where
E: serde::de::Error,
{
let de = serde::de::value::U128Deserializer::new(value);
Number::deserialize(de).map(Value::Number)
}

#[inline]
fn visit_f64<E>(self, value: f64) -> Result<Value, E> {
Ok(Number::from_f64(value).map_or(Value::Null, Value::Number))