aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Duong <joshuaduong@google.com>2024-02-06 02:43:55 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2024-02-06 02:43:55 +0000
commit274fd5210af7852f1c1612185f0f96027c4b276d (patch)
treeb8d42aea8748d3498c8db89b44c0a8be35e0c447
parentab3436461b12acbbafa7e02f308418ea5ef97bb9 (diff)
parent3d4eded760ff8f9ff11e9118e0c854a83438dc74 (diff)
downloadserde_json-emu-34-2-dev.tar.gz
Revert "Upgrade serde_json to 1.0.113" am: 3d4eded760HEADmastermainemu-34-2-dev
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/serde_json/+/2952088 Change-Id: I623cbf19e26449e69a4f16f2f46c038fafce80ab Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--.github/workflows/ci.yml57
-rw-r--r--Android.bp4
-rw-r--r--Cargo.toml31
-rw-r--r--Cargo.toml.orig35
-rw-r--r--METADATA25
-rw-r--r--README.md2
-rw-r--r--build.rs39
-rw-r--r--src/de.rs287
-rw-r--r--src/error.rs126
-rw-r--r--src/io/core.rs2
-rw-r--r--src/lexical/algorithm.rs5
-rw-r--r--src/lexical/digit.rs5
-rw-r--r--src/lexical/errors.rs3
-rw-r--r--src/lexical/math.rs4
-rw-r--r--src/lexical/num.rs2
-rw-r--r--src/lib.rs22
-rw-r--r--src/macros.rs3
-rw-r--r--src/map.rs121
-rw-r--r--src/number.rs68
-rw-r--r--src/raw.rs268
-rw-r--r--src/read.rs2
-rw-r--r--src/ser.rs122
-rw-r--r--src/value/de.rs90
-rw-r--r--src/value/from.rs37
-rw-r--r--src/value/index.rs2
-rw-r--r--src/value/mod.rs30
-rw-r--r--src/value/partial_eq.rs14
-rw-r--r--src/value/ser.rs39
-rw-r--r--tests/lexical.rs5
-rw-r--r--tests/lexical/parse.rs2
-rw-r--r--tests/map.rs1
-rw-r--r--tests/regression/issue1004.rs12
-rw-r--r--tests/regression/issue845.rs1
-rw-r--r--tests/test.rs224
-rw-r--r--tests/ui/parse_key.stderr2
36 files changed, 478 insertions, 1216 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index fa385b5..d3c2d3e 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
{
"git": {
- "sha1": "09d865b34b9701be52764dc9bf571b1a16e9d3dc"
+ "sha1": "a15bd0968639884ec7b73107360d58fd655e2071"
},
"path_in_vcs": ""
} \ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d997982..bfaffaf 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -3,7 +3,6 @@ name: CI
on:
push:
pull_request:
- workflow_dispatch:
schedule: [cron: "40 1 * * *"]
permissions:
@@ -22,7 +21,7 @@ jobs:
os: [ubuntu, windows]
timeout-minutes: 45
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly
- run: cargo test
- run: cargo test --features preserve_order --tests -- --skip ui --exact
@@ -38,7 +37,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- rust: [beta, 1.64.0, 1.56.1]
+ rust: [beta, 1.56.1, 1.53.0, 1.46.0, 1.40.0, 1.38.0, 1.36.0]
os: [ubuntu]
include:
- rust: stable
@@ -48,37 +47,27 @@ jobs:
os: windows
timeout-minutes: 45
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{matrix.rust}}
targets: ${{matrix.target}}
- - run: cargo check --manifest-path tests/crate/Cargo.toml
- - run: cargo check --manifest-path tests/crate/Cargo.toml --features float_roundtrip
- - run: cargo check --manifest-path tests/crate/Cargo.toml --features arbitrary_precision
- - run: cargo check --manifest-path tests/crate/Cargo.toml --features raw_value
- - run: cargo check --manifest-path tests/crate/Cargo.toml --features unbounded_depth
+ - run: cargo check
+ - run: cargo check --features float_roundtrip
+ - run: cargo check --features arbitrary_precision
+ - run: cargo check --features raw_value
+ - run: cargo check --features unbounded_depth
- run: cargo check --manifest-path tests/crate/Cargo.toml --no-default-features --features alloc
- run: cargo check --manifest-path tests/crate/Cargo.toml --no-default-features --features alloc,arbitrary_precision
- run: cargo check --manifest-path tests/crate/Cargo.toml --no-default-features --features alloc,raw_value
- - run: cargo check --manifest-path tests/crate/Cargo.toml --features serde_json/preserve_order
- if: matrix.rust != '1.56.1'
- - run: cargo check --manifest-path tests/crate/Cargo.toml --no-default-features --features alloc,serde_json/preserve_order
- if: matrix.rust != '1.56.1'
+ - run: cargo check --features preserve_order
+ if: matrix.rust != '1.53.0' && matrix.rust != '1.46.0' && matrix.rust != '1.45.0' && matrix.rust != '1.40.0' && matrix.rust != '1.38.0' && matrix.rust != '1.36.0'
+ - run: cargo check --manifest-path tests/crate/Cargo.toml --no-default-features --features alloc,preserve_order
+ if: matrix.rust != '1.53.0' && matrix.rust != '1.46.0' && matrix.rust != '1.45.0' && matrix.rust != '1.40.0' && matrix.rust != '1.38.0' && matrix.rust != '1.36.0'
- name: Build without std
run: cargo check --manifest-path tests/crate/Cargo.toml --target ${{matrix.target}} --no-default-features --features alloc
if: matrix.target
- minimal:
- name: Minimal versions
- runs-on: ubuntu-latest
- timeout-minutes: 45
- steps:
- - uses: actions/checkout@v4
- - uses: dtolnay/rust-toolchain@nightly
- - run: cargo generate-lockfile -Z minimal-versions
- - run: cargo check --locked
-
miri:
name: Miri
runs-on: ubuntu-latest
@@ -86,9 +75,8 @@ jobs:
MIRIFLAGS: -Zmiri-strict-provenance
timeout-minutes: 45
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@miri
- - run: cargo miri setup
- run: cargo miri test
- run: cargo miri test --features preserve_order,float_roundtrip,arbitrary_precision,raw_value
@@ -98,29 +86,28 @@ jobs:
if: github.event_name != 'pull_request'
timeout-minutes: 45
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@clippy
- run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic
- run: cargo clippy --all-features --tests -- -Dclippy::all -Dclippy::pedantic
- doc:
+ docs:
name: Documentation
runs-on: ubuntu-latest
timeout-minutes: 45
- env:
- RUSTDOCFLAGS: -Dwarnings
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly
- - uses: dtolnay/install@cargo-docs-rs
- - run: cargo docs-rs
+ - run: cargo doc --features raw_value,unbounded_depth
+ env:
+ RUSTDOCFLAGS: --cfg docsrs
fuzz:
name: Fuzz
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly
- uses: dtolnay/install@cargo-fuzz
- run: cargo fuzz check
@@ -131,7 +118,7 @@ jobs:
if: github.event_name != 'pull_request'
timeout-minutes: 45
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v3
- uses: dtolnay/install@cargo-outdated
- - run: cargo outdated --exit-code 1
+ - run: cargo outdated --workspace --exit-code 1
- run: cargo outdated --manifest-path fuzz/Cargo.toml --exit-code 1
diff --git a/Android.bp b/Android.bp
index 678bf00..d448340 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,9 +43,9 @@ rust_library {
host_supported: true,
crate_name: "serde_json",
cargo_env_compat: true,
- cargo_pkg_version: "1.0.113",
+ cargo_pkg_version: "1.0.94",
srcs: ["src/lib.rs"],
- edition: "2021",
+ edition: "2018",
features: [
"default",
"std",
diff --git a/Cargo.toml b/Cargo.toml
index 447641d..fc2253d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,10 +10,10 @@
# See Cargo.toml.orig for the original contents.
[package]
-edition = "2021"
-rust-version = "1.56"
+edition = "2018"
+rust-version = "1.36"
name = "serde_json"
-version = "1.0.113"
+version = "1.0.94"
authors = [
"Erick Tryzelaar <erick.tryzelaar@gmail.com>",
"David Tolnay <dtolnay@gmail.com>",
@@ -36,14 +36,12 @@ repository = "https://github.com/serde-rs/json"
[package.metadata.docs.rs]
features = [
- "preserve_order",
"raw_value",
"unbounded_depth",
]
rustdoc-args = [
"--cfg",
"docsrs",
- "--generate-link-to-definition",
]
targets = ["x86_64-unknown-linux-gnu"]
@@ -54,7 +52,8 @@ features = ["raw_value"]
doc-scrape-examples = false
[dependencies.indexmap]
-version = "2.2.1"
+version = "1.5.2"
+features = ["std"]
optional = true
[dependencies.itoa]
@@ -64,36 +63,36 @@ version = "1.0"
version = "1.0"
[dependencies.serde]
-version = "1.0.194"
+version = "1.0.100"
default-features = false
[dev-dependencies.automod]
-version = "1.0.11"
+version = "1.0"
[dev-dependencies.indoc]
-version = "2.0.2"
+version = "2.0"
[dev-dependencies.ref-cast]
-version = "1.0.18"
+version = "1.0"
[dev-dependencies.rustversion]
-version = "1.0.13"
+version = "1.0"
[dev-dependencies.serde]
-version = "1.0.194"
+version = "1.0.100"
features = ["derive"]
[dev-dependencies.serde_bytes]
-version = "0.11.10"
+version = "0.11"
[dev-dependencies.serde_derive]
-version = "1.0.166"
+version = "1.0"
[dev-dependencies.serde_stacker]
-version = "0.1.8"
+version = "0.1"
[dev-dependencies.trybuild]
-version = "1.0.81"
+version = "1.0.49"
features = ["diff"]
[features]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index cedde61..ee54284 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,40 +1,43 @@
[package]
name = "serde_json"
-version = "1.0.113"
+version = "1.0.94" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
categories = ["encoding", "parser-implementations", "no-std"]
description = "A JSON serialization file format"
documentation = "https://docs.rs/serde_json"
-edition = "2021"
+edition = "2018"
keywords = ["json", "serde", "serialization"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/serde-rs/json"
-rust-version = "1.56"
+rust-version = "1.36"
[dependencies]
-indexmap = { version = "2.2.1", optional = true }
+serde = { version = "1.0.100", default-features = false }
+indexmap = { version = "1.5.2", features = ["std"], optional = true }
itoa = "1.0"
ryu = "1.0"
-serde = { version = "1.0.194", default-features = false }
[dev-dependencies]
-automod = "1.0.11"
-indoc = "2.0.2"
-ref-cast = "1.0.18"
-rustversion = "1.0.13"
-serde = { version = "1.0.194", features = ["derive"] }
-serde_bytes = "0.11.10"
-serde_derive = "1.0.166"
-serde_stacker = "0.1.8"
-trybuild = { version = "1.0.81", features = ["diff"] }
+automod = "1.0"
+indoc = "2.0"
+ref-cast = "1.0"
+rustversion = "1.0"
+serde = { version = "1.0.100", features = ["derive"] }
+serde_bytes = "0.11"
+serde_derive = "1.0"
+serde_stacker = "0.1"
+trybuild = { version = "1.0.49", features = ["diff"] }
+
+[workspace]
+members = ["tests/crate"]
[lib]
doc-scrape-examples = false
[package.metadata.docs.rs]
-features = ["preserve_order", "raw_value", "unbounded_depth"]
+features = ["raw_value", "unbounded_depth"]
targets = ["x86_64-unknown-linux-gnu"]
-rustdoc-args = ["--cfg", "docsrs", "--generate-link-to-definition"]
+rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.playground]
features = ["raw_value"]
diff --git a/METADATA b/METADATA
index a4bf6a6..9fece5b 100644
--- a/METADATA
+++ b/METADATA
@@ -1,20 +1,23 @@
# This project was upgraded with external_updater.
-# Usage: tools/external_updater/updater.sh update external/rust/crates/serde_json
-# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
+# Usage: tools/external_updater/updater.sh update rust/crates/serde_json
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
name: "serde_json"
description: "A JSON serialization file format"
third_party {
+ url {
+ type: HOMEPAGE
+ value: "https://crates.io/crates/serde_json"
+ }
+ url {
+ type: ARCHIVE
+ value: "https://static.crates.io/crates/serde_json/serde_json-1.0.94.crate"
+ }
+ version: "1.0.94"
license_type: NOTICE
last_upgrade_date {
- year: 2024
- month: 2
- day: 5
- }
- homepage: "https://crates.io/crates/serde_json"
- identifier {
- type: "Archive"
- value: "https://static.crates.io/crates/serde_json/serde_json-1.0.113.crate"
- version: "1.0.113"
+ year: 2023
+ month: 3
+ day: 20
}
}
diff --git a/README.md b/README.md
index a3ba288..d704979 100644
--- a/README.md
+++ b/README.md
@@ -76,7 +76,7 @@ enum Value {
A string of JSON data can be parsed into a `serde_json::Value` by the
[`serde_json::from_str`][from_str] function. There is also
-[`from_slice`][from_slice] for parsing from a byte slice &\[u8\] and
+[`from_slice`][from_slice] for parsing from a byte slice &[u8] and
[`from_reader`][from_reader] for parsing from any `io::Read` like a File or a
TCP stream.
diff --git a/build.rs b/build.rs
index dd09e62..0e12602 100644
--- a/build.rs
+++ b/build.rs
@@ -1,4 +1,6 @@
use std::env;
+use std::process::Command;
+use std::str::{self, FromStr};
fn main() {
println!("cargo:rerun-if-changed=build.rs");
@@ -7,11 +9,46 @@ fn main() {
// src/lexical/math.rs for where this has an effect.
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
match target_arch.as_str() {
- "aarch64" | "mips64" | "powerpc64" | "x86_64" | "loongarch64" => {
+ "aarch64" | "mips64" | "powerpc64" | "x86_64" => {
println!("cargo:rustc-cfg=limb_width_64");
}
_ => {
println!("cargo:rustc-cfg=limb_width_32");
}
}
+
+ let minor = match rustc_minor_version() {
+ Some(minor) => minor,
+ None => return,
+ };
+
+ // BTreeMap::get_key_value
+ // https://blog.rust-lang.org/2019/12/19/Rust-1.40.0.html#additions-to-the-standard-library
+ if minor < 40 {
+ println!("cargo:rustc-cfg=no_btreemap_get_key_value");
+ }
+
+ // BTreeMap::remove_entry
+ // https://blog.rust-lang.org/2020/07/16/Rust-1.45.0.html#library-changes
+ if minor < 45 {
+ println!("cargo:rustc-cfg=no_btreemap_remove_entry");
+ }
+
+ // BTreeMap::retain
+ // https://blog.rust-lang.org/2021/06/17/Rust-1.53.0.html#stabilized-apis
+ if minor < 53 {
+ println!("cargo:rustc-cfg=no_btreemap_retain");
+ }
+}
+
+fn rustc_minor_version() -> Option<u32> {
+ let rustc = env::var_os("RUSTC")?;
+ let output = Command::new(rustc).arg("--version").output().ok()?;
+ let version = str::from_utf8(&output.stdout).ok()?;
+ let mut pieces = version.split('.');
+ if pieces.next() != Some("rustc 1") {
+ return None;
+ }
+ let next = pieces.next()?;
+ u32::from_str(next).ok()
}
diff --git a/src/de.rs b/src/de.rs
index 7154f84..88d0f26 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -22,7 +22,6 @@ use crate::number::NumberDeserializer;
pub use crate::read::{Read, SliceRead, StrRead};
#[cfg(feature = "std")]
-#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub use crate::read::IoRead;
//////////////////////////////////////////////////////////////////////////////
@@ -210,7 +209,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
self.disable_recursion_limit = true;
}
- pub(crate) fn peek(&mut self) -> Result<Option<u8>> {
+ fn peek(&mut self) -> Result<Option<u8>> {
self.read.peek()
}
@@ -249,7 +248,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
fn parse_whitespace(&mut self) -> Result<Option<u8>> {
loop {
match tri!(self.peek()) {
- Some(b' ' | b'\n' | b'\t' | b'\r') => {
+ Some(b' ') | Some(b'\n') | Some(b'\t') | Some(b'\r') => {
self.eat_char();
}
other => {
@@ -310,9 +309,9 @@ impl<'de, R: Read<'de>> Deserializer<R> {
self.fix_position(err)
}
- pub(crate) fn deserialize_number<'any, V>(&mut self, visitor: V) -> Result<V::Value>
+ fn deserialize_number<V>(&mut self, visitor: V) -> Result<V::Value>
where
- V: de::Visitor<'any>,
+ V: de::Visitor<'de>,
{
let peek = match tri!(self.parse_whitespace()) {
Some(b) => b,
@@ -336,79 +335,6 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
}
- #[cfg(feature = "float_roundtrip")]
- pub(crate) fn do_deserialize_f32<'any, V>(&mut self, visitor: V) -> Result<V::Value>
- where
- V: de::Visitor<'any>,
- {
- self.single_precision = true;
- let val = self.deserialize_number(visitor);
- self.single_precision = false;
- val
- }
-
- pub(crate) fn do_deserialize_i128<'any, V>(&mut self, visitor: V) -> Result<V::Value>
- where
- V: de::Visitor<'any>,
- {
- let mut buf = String::new();
-
- match tri!(self.parse_whitespace()) {
- Some(b'-') => {
- self.eat_char();
- buf.push('-');
- }
- Some(_) => {}
- None => {
- return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
- }
- };
-
- tri!(self.scan_integer128(&mut buf));
-
- let value = match buf.parse() {
- Ok(int) => visitor.visit_i128(int),
- Err(_) => {
- return Err(self.error(ErrorCode::NumberOutOfRange));
- }
- };
-
- match value {
- Ok(value) => Ok(value),
- Err(err) => Err(self.fix_position(err)),
- }
- }
-
- pub(crate) fn do_deserialize_u128<'any, V>(&mut self, visitor: V) -> Result<V::Value>
- where
- V: de::Visitor<'any>,
- {
- match tri!(self.parse_whitespace()) {
- Some(b'-') => {
- return Err(self.peek_error(ErrorCode::NumberOutOfRange));
- }
- Some(_) => {}
- None => {
- return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
- }
- }
-
- let mut buf = String::new();
- tri!(self.scan_integer128(&mut buf));
-
- let value = match buf.parse() {
- Ok(int) => visitor.visit_u128(int),
- Err(_) => {
- return Err(self.error(ErrorCode::NumberOutOfRange));
- }
- };
-
- match value {
- Ok(value) => Ok(value),
- Err(err) => Err(self.fix_position(err)),
- }
- }
-
fn scan_integer128(&mut self, buf: &mut String) -> Result<()> {
match tri!(self.next_char_or_null()) {
b'0' => {
@@ -934,7 +860,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
if !positive {
buf.push('-');
}
- tri!(self.scan_integer(&mut buf));
+ self.scan_integer(&mut buf)?;
if positive {
if let Ok(unsigned) = buf.parse() {
return Ok(ParserNumber::U64(unsigned));
@@ -987,7 +913,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
fn scan_number(&mut self, buf: &mut String) -> Result<()> {
match tri!(self.peek_or_null()) {
b'.' => self.scan_decimal(buf),
- e @ (b'e' | b'E') => self.scan_exponent(e as char, buf),
+ e @ b'e' | e @ b'E' => self.scan_exponent(e as char, buf),
_ => Ok(()),
}
}
@@ -1012,7 +938,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
match tri!(self.peek_or_null()) {
- e @ (b'e' | b'E') => self.scan_exponent(e as char, buf),
+ e @ b'e' | e @ b'E' => self.scan_exponent(e as char, buf),
_ => Ok(()),
}
}
@@ -1133,7 +1059,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
tri!(self.read.ignore_str());
None
}
- frame @ (b'[' | b'{') => {
+ frame @ b'[' | frame @ b'{' => {
self.scratch.extend(enclosing.take());
self.eat_char();
Some(frame)
@@ -1278,9 +1204,9 @@ impl<'de, R: Read<'de>> Deserializer<R> {
where
V: de::Visitor<'de>,
{
- tri!(self.parse_whitespace());
+ self.parse_whitespace()?;
self.read.begin_raw_buffering();
- tri!(self.ignore_value());
+ self.ignore_value()?;
self.read.end_raw_buffering(visitor)
}
}
@@ -1332,15 +1258,11 @@ static POW10: [f64; 309] = [
macro_rules! deserialize_number {
($method:ident) => {
- deserialize_number!($method, deserialize_number);
- };
-
- ($method:ident, $using:ident) => {
fn $method<V>(self, visitor: V) -> Result<V::Value>
where
V: de::Visitor<'de>,
{
- self.$using(visitor)
+ self.deserialize_number(visitor)
}
};
}
@@ -1502,9 +1424,77 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer<R> {
deserialize_number!(deserialize_f64);
#[cfg(feature = "float_roundtrip")]
- deserialize_number!(deserialize_f32, do_deserialize_f32);
- deserialize_number!(deserialize_i128, do_deserialize_i128);
- deserialize_number!(deserialize_u128, do_deserialize_u128);
+ fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ self.single_precision = true;
+ let val = self.deserialize_number(visitor);
+ self.single_precision = false;
+ val
+ }
+
+ fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ let mut buf = String::new();
+
+ match tri!(self.parse_whitespace()) {
+ Some(b'-') => {
+ self.eat_char();
+ buf.push('-');
+ }
+ Some(_) => {}
+ None => {
+ return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
+ }
+ };
+
+ tri!(self.scan_integer128(&mut buf));
+
+ let value = match buf.parse() {
+ Ok(int) => visitor.visit_i128(int),
+ Err(_) => {
+ return Err(self.error(ErrorCode::NumberOutOfRange));
+ }
+ };
+
+ match value {
+ Ok(value) => Ok(value),
+ Err(err) => Err(self.fix_position(err)),
+ }
+ }
+
+ fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ match tri!(self.parse_whitespace()) {
+ Some(b'-') => {
+ return Err(self.peek_error(ErrorCode::NumberOutOfRange));
+ }
+ Some(_) => {}
+ None => {
+ return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
+ }
+ }
+
+ let mut buf = String::new();
+ tri!(self.scan_integer128(&mut buf));
+
+ let value = match buf.parse() {
+ Ok(int) => visitor.visit_u128(int),
+ Err(_) => {
+ return Err(self.error(ErrorCode::NumberOutOfRange));
+ }
+ };
+
+ match value {
+ Ok(value) => Ok(value),
+ Err(err) => Err(self.fix_position(err)),
+ }
+ }
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
where
@@ -2128,47 +2118,24 @@ struct MapKey<'a, R: 'a> {
de: &'a mut Deserializer<R>,
}
-macro_rules! deserialize_numeric_key {
- ($method:ident) => {
- fn $method<V>(self, visitor: V) -> Result<V::Value>
- where
- V: de::Visitor<'de>,
- {
- self.deserialize_number(visitor)
- }
- };
-
- ($method:ident, $delegate:ident) => {
+macro_rules! deserialize_integer_key {
+ ($method:ident => $visit:ident) => {
fn $method<V>(self, visitor: V) -> Result<V::Value>
where
V: de::Visitor<'de>,
{
self.de.eat_char();
-
- match tri!(self.de.peek()) {
- Some(b'0'..=b'9' | b'-') => {}
- _ => return Err(self.de.error(ErrorCode::ExpectedNumericKey)),
- }
-
- let value = tri!(self.de.$delegate(visitor));
-
- match tri!(self.de.peek()) {
- Some(b'"') => self.de.eat_char(),
- _ => return Err(self.de.peek_error(ErrorCode::ExpectedDoubleQuote)),
+ self.de.scratch.clear();
+ let string = tri!(self.de.read.parse_str(&mut self.de.scratch));
+ match (string.parse(), string) {
+ (Ok(integer), _) => visitor.$visit(integer),
+ (Err(_), Reference::Borrowed(s)) => visitor.visit_borrowed_str(s),
+ (Err(_), Reference::Copied(s)) => visitor.visit_str(s),
}
-
- Ok(value)
}
};
}
-impl<'de, 'a, R> MapKey<'a, R>
-where
- R: Read<'de>,
-{
- deserialize_numeric_key!(deserialize_number, deserialize_number);
-}
-
impl<'de, 'a, R> de::Deserializer<'de> for MapKey<'a, R>
where
R: Read<'de>,
@@ -2188,56 +2155,16 @@ where
}
}
- deserialize_numeric_key!(deserialize_i8);
- deserialize_numeric_key!(deserialize_i16);
- deserialize_numeric_key!(deserialize_i32);
- deserialize_numeric_key!(deserialize_i64);
- deserialize_numeric_key!(deserialize_i128, deserialize_i128);
- deserialize_numeric_key!(deserialize_u8);
- deserialize_numeric_key!(deserialize_u16);
- deserialize_numeric_key!(deserialize_u32);
- deserialize_numeric_key!(deserialize_u64);
- deserialize_numeric_key!(deserialize_u128, deserialize_u128);
- #[cfg(not(feature = "float_roundtrip"))]
- deserialize_numeric_key!(deserialize_f32);
- #[cfg(feature = "float_roundtrip")]
- deserialize_numeric_key!(deserialize_f32, deserialize_f32);
- deserialize_numeric_key!(deserialize_f64);
-
- fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
- where
- V: de::Visitor<'de>,
- {
- self.de.eat_char();
-
- let peek = match tri!(self.de.next_char()) {
- Some(b) => b,
- None => {
- return Err(self.de.peek_error(ErrorCode::EofWhileParsingValue));
- }
- };
-
- let value = match peek {
- b't' => {
- tri!(self.de.parse_ident(b"rue\""));
- visitor.visit_bool(true)
- }
- b'f' => {
- tri!(self.de.parse_ident(b"alse\""));
- visitor.visit_bool(false)
- }
- _ => {
- self.de.scratch.clear();
- let s = tri!(self.de.read.parse_str(&mut self.de.scratch));
- Err(de::Error::invalid_type(Unexpected::Str(&s), &visitor))
- }
- };
-
- match value {
- Ok(value) => Ok(value),
- Err(err) => Err(self.de.fix_position(err)),
- }
- }
+ deserialize_integer_key!(deserialize_i8 => visit_i8);
+ deserialize_integer_key!(deserialize_i16 => visit_i16);
+ deserialize_integer_key!(deserialize_i32 => visit_i32);
+ deserialize_integer_key!(deserialize_i64 => visit_i64);
+ deserialize_integer_key!(deserialize_i128 => visit_i128);
+ deserialize_integer_key!(deserialize_u8 => visit_u8);
+ deserialize_integer_key!(deserialize_u16 => visit_u16);
+ deserialize_integer_key!(deserialize_u32 => visit_u32);
+ deserialize_integer_key!(deserialize_u64 => visit_u64);
+ deserialize_integer_key!(deserialize_u128 => visit_u128);
#[inline]
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
@@ -2294,8 +2221,8 @@ where
}
forward_to_deserialize_any! {
- char str string unit unit_struct seq tuple tuple_struct map struct
- identifier ignored_any
+ bool f32 f64 char str string unit unit_struct seq tuple tuple_struct map
+ struct identifier ignored_any
}
}
@@ -2391,8 +2318,8 @@ where
fn peek_end_of_value(&mut self) -> Result<()> {
match tri!(self.de.peek()) {
- Some(b' ' | b'\n' | b'\t' | b'\r' | b'"' | b'[' | b']' | b'{' | b'}' | b',' | b':')
- | None => Ok(()),
+ Some(b' ') | Some(b'\n') | Some(b'\t') | Some(b'\r') | Some(b'"') | Some(b'[')
+ | Some(b']') | Some(b'{') | Some(b'}') | Some(b',') | Some(b':') | None => Ok(()),
Some(_) => {
let position = self.de.read.peek_position();
Err(Error::syntax(
@@ -2442,7 +2369,7 @@ where
if self_delineated_value {
Ok(value)
} else {
- self.peek_end_of_value().map(|()| value)
+ self.peek_end_of_value().map(|_| value)
}
}
Err(e) => {
@@ -2481,9 +2408,9 @@ where
Ok(value)
}
-/// Deserialize an instance of type `T` from an I/O stream of JSON.
+/// Deserialize an instance of type `T` from an IO stream of JSON.
///
-/// The content of the I/O stream is deserialized directly from the stream
+/// The content of the IO stream is deserialized directly from the stream
/// without being buffered in memory by serde_json.
///
/// When reading from a source against which short reads are not efficient, such
diff --git a/src/error.rs b/src/error.rs
index fbf9eb1..0898baf 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -9,8 +9,6 @@ use core::str::FromStr;
use serde::{de, ser};
#[cfg(feature = "std")]
use std::error;
-#[cfg(feature = "std")]
-use std::io::ErrorKind;
/// This type represents all possible errors that can occur when serializing or
/// deserializing JSON data.
@@ -38,16 +36,15 @@ impl Error {
/// The first character in the input and any characters immediately
/// following a newline character are in column 1.
///
- /// Note that errors may occur in column 0, for example if a read from an
- /// I/O stream fails immediately following a previously read newline
- /// character.
+ /// Note that errors may occur in column 0, for example if a read from an IO
+ /// stream fails immediately following a previously read newline character.
pub fn column(&self) -> usize {
self.err.column
}
/// Categorizes the cause of this error.
///
- /// - `Category::Io` - failure to read or write bytes on an I/O stream
+ /// - `Category::Io` - failure to read or write bytes on an IO stream
/// - `Category::Syntax` - input that is not syntactically valid JSON
/// - `Category::Data` - input data that is semantically incorrect
/// - `Category::Eof` - unexpected end of the input data
@@ -64,15 +61,12 @@ impl Error {
| ErrorCode::ExpectedObjectCommaOrEnd
| ErrorCode::ExpectedSomeIdent
| ErrorCode::ExpectedSomeValue
- | ErrorCode::ExpectedDoubleQuote
| ErrorCode::InvalidEscape
| ErrorCode::InvalidNumber
| ErrorCode::NumberOutOfRange
| ErrorCode::InvalidUnicodeCodePoint
| ErrorCode::ControlCharacterWhileParsingString
| ErrorCode::KeyMustBeAString
- | ErrorCode::ExpectedNumericKey
- | ErrorCode::FloatKeyMustBeFinite
| ErrorCode::LoneLeadingSurrogateInHexEscape
| ErrorCode::TrailingComma
| ErrorCode::TrailingCharacters
@@ -82,7 +76,7 @@ impl Error {
}
/// Returns true if this error was caused by a failure to read or write
- /// bytes on an I/O stream.
+ /// bytes on an IO stream.
pub fn is_io(&self) -> bool {
self.classify() == Category::Io
}
@@ -110,61 +104,12 @@ impl Error {
pub fn is_eof(&self) -> bool {
self.classify() == Category::Eof
}
-
- /// The kind reported by the underlying standard library I/O error, if this
- /// error was caused by a failure to read or write bytes on an I/O stream.
- ///
- /// # Example
- ///
- /// ```
- /// use serde_json::Value;
- /// use std::io::{self, ErrorKind, Read};
- /// use std::process;
- ///
- /// struct ReaderThatWillTimeOut<'a>(&'a [u8]);
- ///
- /// impl<'a> Read for ReaderThatWillTimeOut<'a> {
- /// fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- /// if self.0.is_empty() {
- /// Err(io::Error::new(ErrorKind::TimedOut, "timed out"))
- /// } else {
- /// self.0.read(buf)
- /// }
- /// }
- /// }
- ///
- /// fn main() {
- /// let reader = ReaderThatWillTimeOut(br#" {"k": "#);
- ///
- /// let _: Value = match serde_json::from_reader(reader) {
- /// Ok(value) => value,
- /// Err(error) => {
- /// if error.io_error_kind() == Some(ErrorKind::TimedOut) {
- /// // Maybe this application needs to retry certain kinds of errors.
- ///
- /// # return;
- /// } else {
- /// eprintln!("error: {}", error);
- /// process::exit(1);
- /// }
- /// }
- /// };
- /// }
- /// ```
- #[cfg(feature = "std")]
- pub fn io_error_kind(&self) -> Option<ErrorKind> {
- if let ErrorCode::Io(io_error) = &self.err.code {
- Some(io_error.kind())
- } else {
- None
- }
- }
}
/// Categorizes the cause of a `serde_json::Error`.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Category {
- /// The error was caused by a failure to read or write bytes on an I/O
+ /// The error was caused by a failure to read or write bytes on an IO
/// stream.
Io,
@@ -189,8 +134,8 @@ pub enum Category {
impl From<Error> for io::Error {
/// Convert a `serde_json::Error` into an `io::Error`.
///
- /// JSON syntax and data errors are turned into `InvalidData` I/O errors.
- /// EOF errors are turned into `UnexpectedEof` I/O errors.
+ /// JSON syntax and data errors are turned into `InvalidData` IO errors.
+ /// EOF errors are turned into `UnexpectedEof` IO errors.
///
/// ```
/// use std::io;
@@ -220,8 +165,8 @@ impl From<Error> for io::Error {
} else {
match j.classify() {
Category::Io => unreachable!(),
- Category::Syntax | Category::Data => io::Error::new(ErrorKind::InvalidData, j),
- Category::Eof => io::Error::new(ErrorKind::UnexpectedEof, j),
+ Category::Syntax | Category::Data => io::Error::new(io::ErrorKind::InvalidData, j),
+ Category::Eof => io::Error::new(io::ErrorKind::UnexpectedEof, j),
}
}
}
@@ -237,7 +182,7 @@ pub(crate) enum ErrorCode {
/// Catchall for syntax error messages
Message(Box<str>),
- /// Some I/O error occurred while serializing or deserializing.
+ /// Some IO error occurred while serializing or deserializing.
Io(io::Error),
/// EOF while parsing a list.
@@ -267,9 +212,6 @@ pub(crate) enum ErrorCode {
/// Expected this character to start a JSON value.
ExpectedSomeValue,
- /// Expected this character to be a `"`.
- ExpectedDoubleQuote,
-
/// Invalid hex escape code.
InvalidEscape,
@@ -288,12 +230,6 @@ pub(crate) enum ErrorCode {
/// Object key is not a string.
KeyMustBeAString,
- /// Contents of key were supposed to be a number.
- ExpectedNumericKey,
-
- /// Object key is a non-finite float value.
- FloatKeyMustBeFinite,
-
/// Lone leading surrogate in hex escape.
LoneLeadingSurrogateInHexEscape,
@@ -360,7 +296,6 @@ impl Display for ErrorCode {
ErrorCode::ExpectedObjectCommaOrEnd => f.write_str("expected `,` or `}`"),
ErrorCode::ExpectedSomeIdent => f.write_str("expected ident"),
ErrorCode::ExpectedSomeValue => f.write_str("expected value"),
- ErrorCode::ExpectedDoubleQuote => f.write_str("expected `\"`"),
ErrorCode::InvalidEscape => f.write_str("invalid escape"),
ErrorCode::InvalidNumber => f.write_str("invalid number"),
ErrorCode::NumberOutOfRange => f.write_str("number out of range"),
@@ -369,12 +304,6 @@ impl Display for ErrorCode {
f.write_str("control character (\\u0000-\\u001F) found while parsing a string")
}
ErrorCode::KeyMustBeAString => f.write_str("key must be a string"),
- ErrorCode::ExpectedNumericKey => {
- f.write_str("invalid value: expected key to be a number in quotes")
- }
- ErrorCode::FloatKeyMustBeFinite => {
- f.write_str("float key must be finite (got NaN or +/-inf)")
- }
ErrorCode::LoneLeadingSurrogateInHexEscape => {
f.write_str("lone leading surrogate in hex escape")
}
@@ -438,20 +367,11 @@ impl de::Error for Error {
#[cold]
fn invalid_type(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
- Error::custom(format_args!(
- "invalid type: {}, expected {}",
- JsonUnexpected(unexp),
- exp,
- ))
- }
-
- #[cold]
- fn invalid_value(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
- Error::custom(format_args!(
- "invalid value: {}, expected {}",
- JsonUnexpected(unexp),
- exp,
- ))
+ if let de::Unexpected::Unit = unexp {
+ Error::custom(format_args!("invalid type: null, expected {}", exp))
+ } else {
+ Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
+ }
}
}
@@ -462,22 +382,6 @@ impl ser::Error for Error {
}
}
-struct JsonUnexpected<'a>(de::Unexpected<'a>);
-
-impl<'a> Display for JsonUnexpected<'a> {
- fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- match self.0 {
- de::Unexpected::Unit => formatter.write_str("null"),
- de::Unexpected::Float(value) => write!(
- formatter,
- "floating point `{}`",
- ryu::Buffer::new().format(value),
- ),
- unexp => Display::fmt(&unexp, formatter),
- }
- }
-}
-
// Parse our own error message that looks like "{} at line {} column {}" to work
// around erased-serde round-tripping the error through de::Error::custom.
fn make_error(mut msg: String) -> Error {
diff --git a/src/io/core.rs b/src/io/core.rs
index 54c8ddf..465ab8b 100644
--- a/src/io/core.rs
+++ b/src/io/core.rs
@@ -9,7 +9,7 @@ pub enum ErrorKind {
Other,
}
-// I/O errors can never occur in no-std mode. All our no-std I/O implementations
+// IO errors can never occur in no-std mode. All our no-std IO implementations
// are infallible.
pub struct Error;
diff --git a/src/lexical/algorithm.rs b/src/lexical/algorithm.rs
index eaa5e7e..a2cbf18 100644
--- a/src/lexical/algorithm.rs
+++ b/src/lexical/algorithm.rs
@@ -51,10 +51,7 @@ where
// Compute the product of the power, if it overflows,
// prematurely return early, otherwise, if we didn't overshoot,
// we can get an exact value.
- let value = match mantissa.checked_mul(power) {
- None => return None,
- Some(value) => value,
- };
+ let value = mantissa.checked_mul(power)?;
if value >> mantissa_size != 0 {
None
} else {
diff --git a/src/lexical/digit.rs b/src/lexical/digit.rs
index 3d150a1..882aa9e 100644
--- a/src/lexical/digit.rs
+++ b/src/lexical/digit.rs
@@ -11,8 +11,5 @@ pub(crate) fn to_digit(c: u8) -> Option<u32> {
// Add digit to mantissa.
#[inline]
pub(crate) fn add_digit(value: u64, digit: u32) -> Option<u64> {
- match value.checked_mul(10) {
- None => None,
- Some(n) => n.checked_add(digit as u64),
- }
+ value.checked_mul(10)?.checked_add(digit as u64)
}
diff --git a/src/lexical/errors.rs b/src/lexical/errors.rs
index f4f41cd..cad4bd3 100644
--- a/src/lexical/errors.rs
+++ b/src/lexical/errors.rs
@@ -5,7 +5,8 @@
//! This estimates the error in a floating-point representation.
//!
//! This implementation is loosely based off the Golang implementation,
-//! found here: <https://golang.org/src/strconv/atof.go>
+//! found here:
+//! https://golang.org/src/strconv/atof.go
use super::float::*;
use super::num::*;
diff --git a/src/lexical/math.rs b/src/lexical/math.rs
index d7122bf..37cc1d2 100644
--- a/src/lexical/math.rs
+++ b/src/lexical/math.rs
@@ -336,7 +336,7 @@ mod small {
pub fn imul(x: &mut Vec<Limb>, y: Limb) {
// Multiply iteratively over all elements, adding the carry each time.
let mut carry: Limb = 0;
- for xi in &mut *x {
+ for xi in x.iter_mut() {
carry = scalar::imul(xi, y, carry);
}
@@ -482,7 +482,7 @@ mod small {
let rshift = bits - n;
let lshift = n;
let mut prev: Limb = 0;
- for xi in &mut *x {
+ for xi in x.iter_mut() {
let tmp = *xi;
*xi <<= lshift;
*xi |= prev >> rshift;
diff --git a/src/lexical/num.rs b/src/lexical/num.rs
index af10afd..e47e003 100644
--- a/src/lexical/num.rs
+++ b/src/lexical/num.rs
@@ -223,7 +223,7 @@ pub trait Float: Number {
const NEGATIVE_INFINITY_BITS: Self::Unsigned;
/// Size of the significand (mantissa) without hidden bit.
const MANTISSA_SIZE: i32;
- /// Bias of the exponent
+ /// Bias of the exponet
const EXPONENT_BIAS: i32;
/// Exponent portion of a denormal float.
const DENORMAL_EXPONENT: i32;
diff --git a/src/lib.rs b/src/lib.rs
index aa3fcfc..bd49763 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -55,9 +55,10 @@
//! ```
//!
//! A string of JSON data can be parsed into a `serde_json::Value` by the
-//! [`serde_json::from_str`][from_str] function. There is also [`from_slice`]
-//! for parsing from a byte slice &\[u8\] and [`from_reader`] for parsing from
-//! any `io::Read` like a File or a TCP stream.
+//! [`serde_json::from_str`][from_str] function. There is also
+//! [`from_slice`][from_slice] for parsing from a byte slice &[u8] and
+//! [`from_reader`][from_reader] for parsing from any `io::Read` like a File or
+//! a TCP stream.
//!
//! ```
//! use serde_json::{Result, Value};
@@ -299,7 +300,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.113")]
+#![doc(html_root_url = "https://docs.rs/serde_json/1.0.94")]
// Ignored clippy lints
#![allow(
clippy::collapsible_else_if,
@@ -314,13 +315,18 @@
clippy::match_single_binding,
clippy::needless_doctest_main,
clippy::needless_late_init,
+ // clippy bug: https://github.com/rust-lang/rust-clippy/issues/8366
+ clippy::ptr_arg,
clippy::return_self_not_must_use,
clippy::transmute_ptr_to_ptr,
- clippy::unconditional_recursion, // https://github.com/rust-lang/rust-clippy/issues/12133
- clippy::unnecessary_wraps
+ clippy::unnecessary_wraps,
+ // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
+ clippy::unnested_or_patterns,
)]
// Ignored clippy_pedantic lints
#![allow(
+ // buggy
+ clippy::iter_not_returning_iterator, // https://github.com/rust-lang/rust-clippy/issues/8285
// Deserializer::from_str, into_iter
clippy::should_implement_trait,
// integer and float ser/de requires these sorts of casts
@@ -356,8 +362,6 @@
clippy::missing_errors_doc,
clippy::must_use_candidate,
)]
-// Restrictions
-#![deny(clippy::question_mark_used)]
#![allow(non_upper_case_globals)]
#![deny(missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]
@@ -366,7 +370,6 @@
extern crate alloc;
#[cfg(feature = "std")]
-#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[doc(inline)]
pub use crate::de::from_reader;
#[doc(inline)]
@@ -376,7 +379,6 @@ pub use crate::error::{Error, Result};
#[doc(inline)]
pub use crate::ser::{to_string, to_string_pretty, to_vec, to_vec_pretty};
#[cfg(feature = "std")]
-#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[doc(inline)]
pub use crate::ser::{to_writer, to_writer_pretty, Serializer};
#[doc(inline)]
diff --git a/src/macros.rs b/src/macros.rs
index e8c6cd2..5287998 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -10,8 +10,7 @@
/// "features": [
/// "serde",
/// "json"
-/// ],
-/// "homepage": null
+/// ]
/// }
/// });
/// ```
diff --git a/src/map.rs b/src/map.rs
index 1d74e1b..3e8a381 100644
--- a/src/map.rs
+++ b/src/map.rs
@@ -11,7 +11,7 @@ use alloc::string::String;
use core::borrow::Borrow;
use core::fmt::{self, Debug};
use core::hash::Hash;
-use core::iter::FusedIterator;
+use core::iter::{FromIterator, FusedIterator};
#[cfg(feature = "preserve_order")]
use core::mem;
use core::ops;
@@ -106,6 +106,7 @@ impl Map<String, Value> {
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
#[inline]
+ #[cfg(any(feature = "preserve_order", not(no_btreemap_get_key_value)))]
pub fn get_key_value<Q>(&self, key: &Q) -> Option<(&String, &Value)>
where
String: Borrow<Q>,
@@ -130,12 +131,6 @@ impl Map<String, Value> {
///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
- ///
- /// If serde_json's "preserve_order" is enabled, `.remove(key)` is
- /// equivalent to [`.swap_remove(key)`][Self::swap_remove], replacing this
- /// entry's position with the last element. If you need to preserve the
- /// relative order of the keys in the map, use
- /// [`.shift_remove(key)`][Self::shift_remove] instead.
#[inline]
pub fn remove<Q>(&mut self, key: &Q) -> Option<Value>
where
@@ -143,7 +138,7 @@ impl Map<String, Value> {
Q: ?Sized + Ord + Eq + Hash,
{
#[cfg(feature = "preserve_order")]
- return self.swap_remove(key);
+ return self.map.swap_remove(key);
#[cfg(not(feature = "preserve_order"))]
return self.map.remove(key);
}
@@ -153,86 +148,49 @@ impl Map<String, Value> {
///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
- ///
- /// If serde_json's "preserve_order" is enabled, `.remove_entry(key)` is
- /// equivalent to [`.swap_remove_entry(key)`][Self::swap_remove_entry],
- /// replacing this entry's position with the last element. If you need to
- /// preserve the relative order of the keys in the map, use
- /// [`.shift_remove_entry(key)`][Self::shift_remove_entry] instead.
- #[inline]
pub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(String, Value)>
where
String: Borrow<Q>,
Q: ?Sized + Ord + Eq + Hash,
{
- #[cfg(feature = "preserve_order")]
- return self.swap_remove_entry(key);
- #[cfg(not(feature = "preserve_order"))]
+ #[cfg(any(feature = "preserve_order", not(no_btreemap_remove_entry)))]
return self.map.remove_entry(key);
- }
-
- /// Removes and returns the value corresponding to the key from the map.
- ///
- /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the
- /// last element of the map and popping it off. This perturbs the position
- /// of what used to be the last element!
- #[cfg(feature = "preserve_order")]
- #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))]
- #[inline]
- pub fn swap_remove<Q>(&mut self, key: &Q) -> Option<Value>
- where
- String: Borrow<Q>,
- Q: ?Sized + Ord + Eq + Hash,
- {
- self.map.swap_remove(key)
- }
-
- /// Remove and return the key-value pair.
- ///
- /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the
- /// last element of the map and popping it off. This perturbs the position
- /// of what used to be the last element!
- #[cfg(feature = "preserve_order")]
- #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))]
- #[inline]
- pub fn swap_remove_entry<Q>(&mut self, key: &Q) -> Option<(String, Value)>
- where
- String: Borrow<Q>,
- Q: ?Sized + Ord + Eq + Hash,
- {
- self.map.swap_remove_entry(key)
- }
-
- /// Removes and returns the value corresponding to the key from the map.
- ///
- /// Like [`Vec::remove`], the entry is removed by shifting all of the
- /// elements that follow it, preserving their relative order. This perturbs
- /// the index of all of those elements!
- #[cfg(feature = "preserve_order")]
- #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))]
- #[inline]
- pub fn shift_remove<Q>(&mut self, key: &Q) -> Option<Value>
- where
- String: Borrow<Q>,
- Q: ?Sized + Ord + Eq + Hash,
- {
- self.map.shift_remove(key)
- }
+ #[cfg(all(
+ not(feature = "preserve_order"),
+ no_btreemap_remove_entry,
+ not(no_btreemap_get_key_value),
+ ))]
+ {
+ let (key, _value) = self.map.get_key_value(key)?;
+ let key = key.clone();
+ let value = self.map.remove::<String>(&key)?;
+ Some((key, value))
+ }
+ #[cfg(all(
+ not(feature = "preserve_order"),
+ no_btreemap_remove_entry,
+ no_btreemap_get_key_value,
+ ))]
+ {
+ use core::ops::{Bound, RangeBounds};
+
+ struct Key<'a, Q: ?Sized>(&'a Q);
+
+ impl<'a, Q: ?Sized> RangeBounds<Q> for Key<'a, Q> {
+ fn start_bound(&self) -> Bound<&Q> {
+ Bound::Included(self.0)
+ }
+ fn end_bound(&self) -> Bound<&Q> {
+ Bound::Included(self.0)
+ }
+ }
- /// Remove and return the key-value pair.
- ///
- /// Like [`Vec::remove`], the entry is removed by shifting all of the
- /// elements that follow it, preserving their relative order. This perturbs
- /// the index of all of those elements!
- #[cfg(feature = "preserve_order")]
- #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))]
- #[inline]
- pub fn shift_remove_entry<Q>(&mut self, key: &Q) -> Option<(String, Value)>
- where
- String: Borrow<Q>,
- Q: ?Sized + Ord + Eq + Hash,
- {
- self.map.shift_remove_entry(key)
+ let mut range = self.map.range(Key(key));
+ let (key, _value) = range.next()?;
+ let key = key.clone();
+ let value = self.map.remove::<String>(&key)?;
+ Some((key, value))
+ }
}
/// Moves all elements from other into self, leaving other empty.
@@ -318,6 +276,7 @@ impl Map<String, Value> {
///
/// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)`
/// returns `false`.
+ #[cfg(not(no_btreemap_retain))]
#[inline]
pub fn retain<F>(&mut self, f: F)
where
diff --git a/src/number.rs b/src/number.rs
index b0231a8..21a7641 100644
--- a/src/number.rs
+++ b/src/number.rs
@@ -279,62 +279,6 @@ impl Number {
}
}
- /// 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")))]
- pub fn as_str(&self) -> &str {
- &self.n
- }
-
- pub(crate) fn as_f32(&self) -> Option<f32> {
- #[cfg(not(feature = "arbitrary_precision"))]
- match self.n {
- N::PosInt(n) => Some(n as f32),
- N::NegInt(n) => Some(n as f32),
- N::Float(n) => Some(n as f32),
- }
- #[cfg(feature = "arbitrary_precision")]
- self.n.parse::<f32>().ok().filter(|float| float.is_finite())
- }
-
- 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)]
@@ -388,8 +332,8 @@ impl Serialize for Number {
{
use serde::ser::SerializeStruct;
- let mut s = tri!(serializer.serialize_struct(TOKEN, 1));
- tri!(s.serialize_field(TOKEN, &self.n));
+ let mut s = serializer.serialize_struct(TOKEN, 1)?;
+ s.serialize_field(TOKEN, &self.n)?;
s.end()
}
}
@@ -433,11 +377,11 @@ impl<'de> Deserialize<'de> for Number {
where
V: de::MapAccess<'de>,
{
- let value = tri!(visitor.next_key::<NumberKey>());
+ let value = visitor.next_key::<NumberKey>()?;
if value.is_none() {
return Err(de::Error::invalid_type(Unexpected::Map, &self));
}
- let v: NumberFromString = tri!(visitor.next_value());
+ let v: NumberFromString = visitor.next_value()?;
Ok(v.value)
}
}
@@ -476,7 +420,7 @@ impl<'de> de::Deserialize<'de> for NumberKey {
}
}
- tri!(deserializer.deserialize_identifier(FieldVisitor));
+ deserializer.deserialize_identifier(FieldVisitor)?;
Ok(NumberKey)
}
}
@@ -579,7 +523,7 @@ macro_rules! deserialize_number {
where
V: de::Visitor<'de>,
{
- visitor.$visit(tri!(self.n.parse().map_err(|_| invalid_number())))
+ visitor.$visit(self.n.parse().map_err(|_| invalid_number())?)
}
};
}
diff --git a/src/raw.rs b/src/raw.rs
index a2bf0ec..6aa4ffc 100644
--- a/src/raw.rs
+++ b/src/raw.rs
@@ -177,9 +177,11 @@ impl RawValue {
/// - the input has no leading or trailing whitespace, and
/// - the input has capacity equal to its length.
pub fn from_string(json: String) -> Result<Box<Self>, Error> {
- let borrowed = tri!(crate::from_str::<&Self>(&json));
- if borrowed.json.len() < json.len() {
- return Ok(borrowed.to_owned());
+ {
+ let borrowed = crate::from_str::<&Self>(&json)?;
+ if borrowed.json.len() < json.len() {
+ return Ok(borrowed.to_owned());
+ }
}
Ok(Self::from_owned(json.into_boxed_str()))
}
@@ -285,7 +287,7 @@ pub fn to_raw_value<T>(value: &T) -> Result<Box<RawValue>, Error>
where
T: ?Sized + Serialize,
{
- let json_string = tri!(crate::to_string(value));
+ let json_string = crate::to_string(value)?;
Ok(RawValue::from_owned(json_string.into_boxed_str()))
}
@@ -296,8 +298,8 @@ impl Serialize for RawValue {
where
S: Serializer,
{
- let mut s = tri!(serializer.serialize_struct(TOKEN, 1));
- tri!(s.serialize_field(TOKEN, &self.json));
+ let mut s = serializer.serialize_struct(TOKEN, 1)?;
+ s.serialize_field(TOKEN, &self.json)?;
s.end()
}
}
@@ -320,7 +322,7 @@ impl<'de: 'a, 'a> Deserialize<'de> for &'a RawValue {
where
V: MapAccess<'de>,
{
- let value = tri!(visitor.next_key::<RawKey>());
+ let value = visitor.next_key::<RawKey>()?;
if value.is_none() {
return Err(de::Error::invalid_type(Unexpected::Map, &self));
}
@@ -350,7 +352,7 @@ impl<'de> Deserialize<'de> for Box<RawValue> {
where
V: MapAccess<'de>,
{
- let value = tri!(visitor.next_key::<RawKey>());
+ let value = visitor.next_key::<RawKey>()?;
if value.is_none() {
return Err(de::Error::invalid_type(Unexpected::Map, &self));
}
@@ -390,7 +392,7 @@ impl<'de> Deserialize<'de> for RawKey {
}
}
- tri!(deserializer.deserialize_identifier(FieldVisitor));
+ deserializer.deserialize_identifier(FieldVisitor)?;
Ok(RawKey)
}
}
@@ -527,251 +529,3 @@ impl<'de> MapAccess<'de> for BorrowedRawDeserializer<'de> {
seed.deserialize(BorrowedStrDeserializer::new(self.raw_value.take().unwrap()))
}
}
-
-impl<'de> IntoDeserializer<'de, Error> for &'de RawValue {
- type Deserializer = &'de RawValue;
-
- fn into_deserializer(self) -> Self::Deserializer {
- self
- }
-}
-
-impl<'de> Deserializer<'de> for &'de RawValue {
- type Error = Error;
-
- fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_any(visitor)
- }
-
- fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_bool(visitor)
- }
-
- fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_i8(visitor)
- }
-
- fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_i16(visitor)
- }
-
- fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_i32(visitor)
- }
-
- fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_i64(visitor)
- }
-
- fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_i128(visitor)
- }
-
- fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_u8(visitor)
- }
-
- fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_u16(visitor)
- }
-
- fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_u32(visitor)
- }
-
- fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_u64(visitor)
- }
-
- fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_u128(visitor)
- }
-
- fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_f32(visitor)
- }
-
- fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_f64(visitor)
- }
-
- fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_char(visitor)
- }
-
- fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_str(visitor)
- }
-
- fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_string(visitor)
- }
-
- fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_bytes(visitor)
- }
-
- fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_byte_buf(visitor)
- }
-
- fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_option(visitor)
- }
-
- fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_unit(visitor)
- }
-
- fn deserialize_unit_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_unit_struct(name, visitor)
- }
-
- fn deserialize_newtype_struct<V>(
- self,
- name: &'static str,
- visitor: V,
- ) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_newtype_struct(name, visitor)
- }
-
- fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_seq(visitor)
- }
-
- fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_tuple(len, visitor)
- }
-
- fn deserialize_tuple_struct<V>(
- self,
- name: &'static str,
- len: usize,
- visitor: V,
- ) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_tuple_struct(name, len, visitor)
- }
-
- fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_map(visitor)
- }
-
- fn deserialize_struct<V>(
- self,
- name: &'static str,
- fields: &'static [&'static str],
- visitor: V,
- ) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_struct(name, fields, visitor)
- }
-
- fn deserialize_enum<V>(
- self,
- name: &'static str,
- variants: &'static [&'static str],
- visitor: V,
- ) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_enum(name, variants, visitor)
- }
-
- fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_identifier(visitor)
- }
-
- fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- crate::Deserializer::from_str(&self.json).deserialize_ignored_any(visitor)
- }
-}
diff --git a/src/read.rs b/src/read.rs
index 7446f28..fc3a3ca 100644
--- a/src/read.rs
+++ b/src/read.rs
@@ -81,7 +81,7 @@ pub trait Read<'de>: private::Sealed {
#[doc(hidden)]
fn ignore_str(&mut self) -> Result<()>;
- /// Assumes the previous byte was a hex escape sequence ('\u') in a string.
+ /// Assumes the previous byte was a hex escape sequnce ('\u') in a string.
/// Parses next hexadecimal sequence.
#[doc(hidden)]
fn decode_hex_escape(&mut self) -> Result<u16>;
diff --git a/src/ser.rs b/src/ser.rs
index 3742e0b..80c2deb 100644
--- a/src/ser.rs
+++ b/src/ser.rs
@@ -189,9 +189,12 @@ where
#[inline]
fn serialize_bytes(self, value: &[u8]) -> Result<()> {
- self.formatter
- .write_byte_array(&mut self.writer, value)
- .map_err(Error::io)
+ use serde::ser::SerializeSeq;
+ let mut seq = tri!(self.serialize_seq(Some(value.len())));
+ for byte in value {
+ tri!(seq.serialize_element(byte));
+ }
+ seq.end()
}
#[inline]
@@ -436,15 +439,17 @@ where
.formatter
.begin_string(&mut self.writer)
.map_err(Error::io));
- let mut adapter = Adapter {
- writer: &mut self.writer,
- formatter: &mut self.formatter,
- error: None,
- };
- match write!(adapter, "{}", value) {
- Ok(()) => debug_assert!(adapter.error.is_none()),
- Err(fmt::Error) => {
- return Err(Error::io(adapter.error.expect("there should be an error")));
+ {
+ let mut adapter = Adapter {
+ writer: &mut self.writer,
+ formatter: &mut self.formatter,
+ error: None,
+ };
+ match write!(adapter, "{}", value) {
+ Ok(()) => debug_assert!(adapter.error.is_none()),
+ Err(fmt::Error) => {
+ return Err(Error::io(adapter.error.expect("there should be an error")));
+ }
}
}
self.formatter
@@ -784,10 +789,6 @@ fn key_must_be_a_string() -> Error {
Error::syntax(ErrorCode::KeyMustBeAString, 0, 0)
}
-fn float_key_must_be_finite() -> Error {
- Error::syntax(ErrorCode::FloatKeyMustBeFinite, 0, 0)
-}
-
impl<'a, W, F> ser::Serializer for MapKeySerializer<'a, W, F>
where
W: io::Write,
@@ -827,21 +828,8 @@ where
type SerializeStruct = Impossible<(), Error>;
type SerializeStructVariant = Impossible<(), Error>;
- fn serialize_bool(self, value: bool) -> Result<()> {
- tri!(self
- .ser
- .formatter
- .begin_string(&mut self.ser.writer)
- .map_err(Error::io));
- tri!(self
- .ser
- .formatter
- .write_bool(&mut self.ser.writer, value)
- .map_err(Error::io));
- self.ser
- .formatter
- .end_string(&mut self.ser.writer)
- .map_err(Error::io)
+ fn serialize_bool(self, _value: bool) -> Result<()> {
+ Err(key_must_be_a_string())
}
fn serialize_i8(self, value: i8) -> Result<()> {
@@ -1014,46 +1002,12 @@ where
.map_err(Error::io)
}
- fn serialize_f32(self, value: f32) -> Result<()> {
- if !value.is_finite() {
- return Err(float_key_must_be_finite());
- }
-
- tri!(self
- .ser
- .formatter
- .begin_string(&mut self.ser.writer)
- .map_err(Error::io));
- tri!(self
- .ser
- .formatter
- .write_f32(&mut self.ser.writer, value)
- .map_err(Error::io));
- self.ser
- .formatter
- .end_string(&mut self.ser.writer)
- .map_err(Error::io)
+ fn serialize_f32(self, _value: f32) -> Result<()> {
+ Err(key_must_be_a_string())
}
- fn serialize_f64(self, value: f64) -> Result<()> {
- if !value.is_finite() {
- return Err(float_key_must_be_finite());
- }
-
- tri!(self
- .ser
- .formatter
- .begin_string(&mut self.ser.writer)
- .map_err(Error::io));
- tri!(self
- .ser
- .formatter
- .write_f64(&mut self.ser.writer, value)
- .map_err(Error::io));
- self.ser
- .formatter
- .end_string(&mut self.ser.writer)
- .map_err(Error::io)
+ fn serialize_f64(self, _value: f64) -> Result<()> {
+ Err(key_must_be_a_string())
}
fn serialize_char(self, value: char) -> Result<()> {
@@ -1089,11 +1043,11 @@ where
Err(key_must_be_a_string())
}
- fn serialize_some<T>(self, value: &T) -> Result<()>
+ fn serialize_some<T>(self, _value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
- value.serialize(self)
+ Err(key_must_be_a_string())
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
@@ -1780,24 +1734,6 @@ pub trait Formatter {
writer.write_all(s)
}
- /// Writes the representation of a byte array. Formatters can choose whether
- /// to represent bytes as a JSON array of integers (the default), or some
- /// JSON string encoding like hex or base64.
- fn write_byte_array<W>(&mut self, writer: &mut W, value: &[u8]) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- tri!(self.begin_array(writer));
- let mut first = true;
- for byte in value {
- tri!(self.begin_array_value(writer, first));
- tri!(self.write_u8(writer, *byte));
- tri!(self.end_array_value(writer));
- first = false;
- }
- self.end_array(writer)
- }
-
/// Called before every array. Writes a `[` to the specified
/// writer.
#[inline]
@@ -2126,9 +2062,7 @@ static ESCAPE: [u8; 256] = [
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F
];
-/// Serialize the given data structure as JSON into the I/O stream.
-///
-/// Serialization guarantees it only feeds valid UTF-8 sequences to the writer.
+/// Serialize the given data structure as JSON into the IO stream.
///
/// # Errors
///
@@ -2145,11 +2079,9 @@ where
value.serialize(&mut ser)
}
-/// Serialize the given data structure as pretty-printed JSON into the I/O
+/// Serialize the given data structure as pretty-printed JSON into the IO
/// stream.
///
-/// Serialization guarantees it only feeds valid UTF-8 sequences to the writer.
-///
/// # Errors
///
/// Serialization can fail if `T`'s implementation of `Serialize` decides to
diff --git a/src/value/de.rs b/src/value/de.rs
index 1e8b5ac..9c266d0 100644
--- a/src/value/de.rs
+++ b/src/value/de.rs
@@ -1,4 +1,4 @@
-use crate::error::{Error, ErrorCode};
+use crate::error::Error;
use crate::map::Map;
use crate::number::Number;
use crate::value::Value;
@@ -106,15 +106,15 @@ impl<'de> Deserialize<'de> for Value {
where
V: MapAccess<'de>,
{
- match tri!(visitor.next_key_seed(KeyClassifier)) {
+ match visitor.next_key_seed(KeyClassifier)? {
#[cfg(feature = "arbitrary_precision")]
Some(KeyClass::Number) => {
- let number: NumberFromString = tri!(visitor.next_value());
+ let number: NumberFromString = visitor.next_value()?;
Ok(Value::Number(number.value))
}
#[cfg(feature = "raw_value")]
Some(KeyClass::RawValue) => {
- let value = tri!(visitor.next_value_seed(crate::raw::BoxedFromString));
+ let value = visitor.next_value_seed(crate::raw::BoxedFromString)?;
crate::from_str(value.get()).map_err(de::Error::custom)
}
Some(KeyClass::Map(first_key)) => {
@@ -482,14 +482,6 @@ impl<'de> IntoDeserializer<'de, Error> for Value {
}
}
-impl<'de> IntoDeserializer<'de, Error> for &'de Value {
- type Deserializer = Self;
-
- fn into_deserializer(self) -> Self::Deserializer {
- self
- }
-}
-
struct VariantDeserializer {
value: Option<Value>,
}
@@ -1128,30 +1120,18 @@ struct MapKeyDeserializer<'de> {
key: Cow<'de, str>,
}
-macro_rules! deserialize_numeric_key {
- ($method:ident) => {
- deserialize_numeric_key!($method, deserialize_number);
- };
-
- ($method:ident, $using:ident) => {
+macro_rules! deserialize_integer_key {
+ ($method:ident => $visit:ident) => {
fn $method<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
- let mut de = crate::Deserializer::from_str(&self.key);
-
- match tri!(de.peek()) {
- Some(b'0'..=b'9' | b'-') => {}
- _ => return Err(Error::syntax(ErrorCode::ExpectedNumericKey, 0, 0)),
- }
-
- let number = tri!(de.$using(visitor));
-
- if tri!(de.peek()).is_some() {
- return Err(Error::syntax(ErrorCode::ExpectedNumericKey, 0, 0));
+ match (self.key.parse(), self.key) {
+ (Ok(integer), _) => visitor.$visit(integer),
+ (Err(_), Cow::Borrowed(s)) => visitor.visit_borrowed_str(s),
+ #[cfg(any(feature = "std", feature = "alloc"))]
+ (Err(_), Cow::Owned(s)) => visitor.visit_string(s),
}
-
- Ok(number)
}
};
}
@@ -1166,38 +1146,16 @@ impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> {
BorrowedCowStrDeserializer::new(self.key).deserialize_any(visitor)
}
- deserialize_numeric_key!(deserialize_i8);
- deserialize_numeric_key!(deserialize_i16);
- deserialize_numeric_key!(deserialize_i32);
- deserialize_numeric_key!(deserialize_i64);
- deserialize_numeric_key!(deserialize_u8);
- deserialize_numeric_key!(deserialize_u16);
- deserialize_numeric_key!(deserialize_u32);
- deserialize_numeric_key!(deserialize_u64);
- #[cfg(not(feature = "float_roundtrip"))]
- deserialize_numeric_key!(deserialize_f32);
- deserialize_numeric_key!(deserialize_f64);
-
- #[cfg(feature = "float_roundtrip")]
- deserialize_numeric_key!(deserialize_f32, do_deserialize_f32);
- deserialize_numeric_key!(deserialize_i128, do_deserialize_i128);
- deserialize_numeric_key!(deserialize_u128, do_deserialize_u128);
-
- fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Error>
- where
- V: Visitor<'de>,
- {
- if self.key == "true" {
- visitor.visit_bool(true)
- } else if self.key == "false" {
- visitor.visit_bool(false)
- } else {
- Err(serde::de::Error::invalid_type(
- Unexpected::Str(&self.key),
- &visitor,
- ))
- }
- }
+ deserialize_integer_key!(deserialize_i8 => visit_i8);
+ deserialize_integer_key!(deserialize_i16 => visit_i16);
+ deserialize_integer_key!(deserialize_i32 => visit_i32);
+ deserialize_integer_key!(deserialize_i64 => visit_i64);
+ deserialize_integer_key!(deserialize_i128 => visit_i128);
+ deserialize_integer_key!(deserialize_u8 => visit_u8);
+ deserialize_integer_key!(deserialize_u16 => visit_u16);
+ deserialize_integer_key!(deserialize_u32 => visit_u32);
+ deserialize_integer_key!(deserialize_u64 => visit_u64);
+ deserialize_integer_key!(deserialize_u128 => visit_u128);
#[inline]
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
@@ -1235,8 +1193,8 @@ impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> {
}
forward_to_deserialize_any! {
- char str string bytes byte_buf unit unit_struct seq tuple tuple_struct
- map struct identifier ignored_any
+ bool f32 f64 char str string bytes byte_buf unit unit_struct seq tuple
+ tuple_struct map struct identifier ignored_any
}
}
@@ -1369,7 +1327,7 @@ impl<'de> de::EnumAccess<'de> for BorrowedCowStrDeserializer<'de> {
where
T: de::DeserializeSeed<'de>,
{
- let value = tri!(seed.deserialize(self));
+ let value = seed.deserialize(self)?;
Ok((value, UnitOnly))
}
}
diff --git a/src/value/from.rs b/src/value/from.rs
index ed1e333..c5a6a39 100644
--- a/src/value/from.rs
+++ b/src/value/from.rs
@@ -4,6 +4,7 @@ use crate::number::Number;
use alloc::borrow::Cow;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
+use core::iter::FromIterator;
macro_rules! from_integer {
($($ty:ident)*) => {
@@ -28,8 +29,7 @@ from_integer! {
}
impl From<f32> for Value {
- /// Convert 32-bit floating point number to `Value::Number`, or
- /// `Value::Null` if infinite or NaN.
+ /// Convert 32-bit floating point number to `Value`
///
/// # Examples
///
@@ -40,13 +40,12 @@ impl From<f32> for Value {
/// let x: Value = f.into();
/// ```
fn from(f: f32) -> Self {
- Number::from_f32(f).map_or(Value::Null, Value::Number)
+ From::from(f as f64)
}
}
impl From<f64> for Value {
- /// Convert 64-bit floating point number to `Value::Number`, or
- /// `Value::Null` if infinite or NaN.
+ /// Convert 64-bit floating point number to `Value`
///
/// # Examples
///
@@ -62,7 +61,7 @@ impl From<f64> for Value {
}
impl From<bool> for Value {
- /// Convert boolean to `Value::Bool`.
+ /// Convert boolean to `Value`
///
/// # Examples
///
@@ -78,7 +77,7 @@ impl From<bool> for Value {
}
impl From<String> for Value {
- /// Convert `String` to `Value::String`.
+ /// Convert `String` to `Value`
///
/// # Examples
///
@@ -93,8 +92,8 @@ impl From<String> for Value {
}
}
-impl From<&str> for Value {
- /// Convert string slice to `Value::String`.
+impl<'a> From<&'a str> for Value {
+ /// Convert string slice to `Value`
///
/// # Examples
///
@@ -110,7 +109,7 @@ impl From<&str> for Value {
}
impl<'a> From<Cow<'a, str>> for Value {
- /// Convert copy-on-write string to `Value::String`.
+ /// Convert copy-on-write string to `Value`
///
/// # Examples
///
@@ -135,7 +134,7 @@ impl<'a> From<Cow<'a, str>> for Value {
}
impl From<Number> for Value {
- /// Convert `Number` to `Value::Number`.
+ /// Convert `Number` to `Value`
///
/// # Examples
///
@@ -151,7 +150,7 @@ impl From<Number> for Value {
}
impl From<Map<String, Value>> for Value {
- /// Convert map (with string keys) to `Value::Object`.
+ /// Convert map (with string keys) to `Value`
///
/// # Examples
///
@@ -168,7 +167,7 @@ impl From<Map<String, Value>> for Value {
}
impl<T: Into<Value>> From<Vec<T>> for Value {
- /// Convert a `Vec` to `Value::Array`.
+ /// Convert a `Vec` to `Value`
///
/// # Examples
///
@@ -183,8 +182,8 @@ impl<T: Into<Value>> From<Vec<T>> for Value {
}
}
-impl<T: Clone + Into<Value>> From<&[T]> for Value {
- /// Convert a slice to `Value::Array`.
+impl<'a, T: Clone + Into<Value>> From<&'a [T]> for Value {
+ /// Convert a slice to `Value`
///
/// # Examples
///
@@ -194,13 +193,13 @@ impl<T: Clone + Into<Value>> From<&[T]> for Value {
/// let v: &[&str] = &["lorem", "ipsum", "dolor"];
/// let x: Value = v.into();
/// ```
- fn from(f: &[T]) -> Self {
+ fn from(f: &'a [T]) -> Self {
Value::Array(f.iter().cloned().map(Into::into).collect())
}
}
impl<T: Into<Value>> FromIterator<T> for Value {
- /// Create a `Value::Array` by collecting an iterator of array elements.
+ /// Convert an iteratable type to a `Value`
///
/// # Examples
///
@@ -230,7 +229,7 @@ impl<T: Into<Value>> FromIterator<T> for Value {
}
impl<K: Into<String>, V: Into<Value>> FromIterator<(K, V)> for Value {
- /// Create a `Value::Object` by collecting an iterator of key-value pairs.
+ /// Convert an iteratable type to a `Value`
///
/// # Examples
///
@@ -250,7 +249,7 @@ impl<K: Into<String>, V: Into<Value>> FromIterator<(K, V)> for Value {
}
impl From<()> for Value {
- /// Convert `()` to `Value::Null`.
+ /// Convert `()` to `Value`
///
/// # Examples
///
diff --git a/src/value/index.rs b/src/value/index.rs
index 891ca8e..c74042b 100644
--- a/src/value/index.rs
+++ b/src/value/index.rs
@@ -116,7 +116,7 @@ impl Index for String {
}
}
-impl<T> Index for &T
+impl<'a, T> Index for &'a T
where
T: ?Sized + Index,
{
diff --git a/src/value/mod.rs b/src/value/mod.rs
index b3f51ea..470b6b2 100644
--- a/src/value/mod.rs
+++ b/src/value/mod.rs
@@ -106,7 +106,6 @@ pub use crate::map::Map;
pub use crate::number::Number;
#[cfg(feature = "raw_value")]
-#[cfg_attr(docsrs, doc(cfg(feature = "raw_value")))]
pub use crate::raw::{to_raw_value, RawValue};
/// Represents any valid JSON value.
@@ -183,11 +182,11 @@ impl Debug for Value {
Value::Number(number) => Debug::fmt(number, formatter),
Value::String(string) => write!(formatter, "String({:?})", string),
Value::Array(vec) => {
- tri!(formatter.write_str("Array "));
+ formatter.write_str("Array ")?;
Debug::fmt(vec, formatter)
}
Value::Object(map) => {
- tri!(formatter.write_str("Object "));
+ formatter.write_str("Object ")?;
Debug::fmt(map, formatter)
}
}
@@ -515,28 +514,6 @@ impl Value {
}
}
- /// If the `Value` is a Number, returns the associated [`Number`]. Returns
- /// None otherwise.
- ///
- /// ```
- /// # use serde_json::{json, Number};
- /// #
- /// let v = json!({ "a": 1, "b": 2.2, "c": -3, "d": "4" });
- ///
- /// assert_eq!(v["a"].as_number(), Some(&Number::from(1u64)));
- /// assert_eq!(v["b"].as_number(), Some(&Number::from_f64(2.2).unwrap()));
- /// assert_eq!(v["c"].as_number(), Some(&Number::from(-3i64)));
- ///
- /// // The string `"4"` is not a number.
- /// assert_eq!(v["d"].as_number(), None);
- /// ```
- pub fn as_number(&self) -> Option<&Number> {
- match self {
- Value::Number(number) => Some(number),
- _ => None,
- }
- }
-
/// Returns true if the `Value` is an integer between `i64::MIN` and
/// `i64::MAX`.
///
@@ -912,6 +889,7 @@ mod ser;
/// ```
/// use serde::Serialize;
/// use serde_json::json;
+///
/// use std::error::Error;
///
/// #[derive(Serialize)]
@@ -920,7 +898,7 @@ mod ser;
/// location: String,
/// }
///
-/// fn compare_json_values() -> Result<(), Box<dyn Error>> {
+/// fn compare_json_values() -> Result<(), Box<Error>> {
/// let u = User {
/// fingerprint: "0xF9BA143B95FF6D82".to_owned(),
/// location: "Menlo Park, CA".to_owned(),
diff --git a/src/value/partial_eq.rs b/src/value/partial_eq.rs
index 46c1dbc..b4ef84c 100644
--- a/src/value/partial_eq.rs
+++ b/src/value/partial_eq.rs
@@ -9,13 +9,6 @@ fn eq_u64(value: &Value, other: u64) -> bool {
value.as_u64().map_or(false, |i| i == other)
}
-fn eq_f32(value: &Value, other: f32) -> bool {
- match value {
- Value::Number(n) => n.as_f32().map_or(false, |i| i == other),
- _ => false,
- }
-}
-
fn eq_f64(value: &Value, other: f64) -> bool {
value.as_f64().map_or(false, |i| i == other)
}
@@ -34,7 +27,7 @@ impl PartialEq<str> for Value {
}
}
-impl PartialEq<&str> for Value {
+impl<'a> PartialEq<&'a str> for Value {
fn eq(&self, other: &&str) -> bool {
eq_str(self, *other)
}
@@ -46,7 +39,7 @@ impl PartialEq<Value> for str {
}
}
-impl PartialEq<Value> for &str {
+impl<'a> PartialEq<Value> for &'a str {
fn eq(&self, other: &Value) -> bool {
eq_str(other, *self)
}
@@ -97,7 +90,6 @@ macro_rules! partialeq_numeric {
partialeq_numeric! {
eq_i64[i8 i16 i32 i64 isize]
eq_u64[u8 u16 u32 u64 usize]
- eq_f32[f32]
- eq_f64[f64]
+ eq_f64[f32 f64]
eq_bool[bool]
}
diff --git a/src/value/ser.rs b/src/value/ser.rs
index 835fa90..a29814e 100644
--- a/src/value/ser.rs
+++ b/src/value/ser.rs
@@ -1,9 +1,12 @@
use crate::error::{Error, ErrorCode, Result};
use crate::map::Map;
+use crate::number::Number;
use crate::value::{to_value, Value};
use alloc::borrow::ToOwned;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
+#[cfg(not(feature = "arbitrary_precision"))]
+use core::convert::TryFrom;
use core::fmt::Display;
use core::result;
use serde::ser::{Impossible, Serialize};
@@ -146,13 +149,13 @@ impl serde::Serializer for Serializer {
}
#[inline]
- fn serialize_f32(self, float: f32) -> Result<Value> {
- Ok(Value::from(float))
+ fn serialize_f32(self, value: f32) -> Result<Value> {
+ self.serialize_f64(value as f64)
}
#[inline]
- fn serialize_f64(self, float: f64) -> Result<Value> {
- Ok(Value::from(float))
+ fn serialize_f64(self, value: f64) -> Result<Value> {
+ Ok(Number::from_f64(value).map_or(Value::Null, Value::Number))
}
#[inline]
@@ -449,10 +452,6 @@ fn key_must_be_a_string() -> Error {
Error::syntax(ErrorCode::KeyMustBeAString, 0, 0)
}
-fn float_key_must_be_finite() -> Error {
- Error::syntax(ErrorCode::FloatKeyMustBeFinite, 0, 0)
-}
-
impl serde::Serializer for MapKeySerializer {
type Ok = String;
type Error = Error;
@@ -483,8 +482,8 @@ impl serde::Serializer for MapKeySerializer {
value.serialize(self)
}
- fn serialize_bool(self, value: bool) -> Result<String> {
- Ok(value.to_string())
+ fn serialize_bool(self, _value: bool) -> Result<String> {
+ Err(key_must_be_a_string())
}
fn serialize_i8(self, value: i8) -> Result<String> {
@@ -519,20 +518,12 @@ impl serde::Serializer for MapKeySerializer {
Ok(value.to_string())
}
- fn serialize_f32(self, value: f32) -> Result<String> {
- if value.is_finite() {
- Ok(ryu::Buffer::new().format_finite(value).to_owned())
- } else {
- Err(float_key_must_be_finite())
- }
+ fn serialize_f32(self, _value: f32) -> Result<String> {
+ Err(key_must_be_a_string())
}
- fn serialize_f64(self, value: f64) -> Result<String> {
- if value.is_finite() {
- Ok(ryu::Buffer::new().format_finite(value).to_owned())
- } else {
- Err(float_key_must_be_finite())
- }
+ fn serialize_f64(self, _value: f64) -> Result<String> {
+ Err(key_must_be_a_string())
}
#[inline]
@@ -650,7 +641,7 @@ impl serde::ser::SerializeStruct for SerializeMap {
#[cfg(feature = "arbitrary_precision")]
SerializeMap::Number { out_value } => {
if key == crate::number::TOKEN {
- *out_value = Some(tri!(value.serialize(NumberValueEmitter)));
+ *out_value = Some(value.serialize(NumberValueEmitter)?);
Ok(())
} else {
Err(invalid_number())
@@ -659,7 +650,7 @@ impl serde::ser::SerializeStruct for SerializeMap {
#[cfg(feature = "raw_value")]
SerializeMap::RawValue { out_value } => {
if key == crate::raw::TOKEN {
- *out_value = Some(tri!(value.serialize(RawValueEmitter)));
+ *out_value = Some(value.serialize(RawValueEmitter)?);
Ok(())
} else {
Err(invalid_raw_value())
diff --git a/tests/lexical.rs b/tests/lexical.rs
index 368c844..d3dfb85 100644
--- a/tests/lexical.rs
+++ b/tests/lexical.rs
@@ -26,6 +26,11 @@ extern crate alloc;
#[path = "../src/lexical/mod.rs"]
mod lexical;
+mod lib {
+ pub use std::vec::Vec;
+ pub use std::{cmp, iter, mem, ops};
+}
+
#[path = "lexical/algorithm.rs"]
mod algorithm;
diff --git a/tests/lexical/parse.rs b/tests/lexical/parse.rs
index 03ec1a9..80ca25e 100644
--- a/tests/lexical/parse.rs
+++ b/tests/lexical/parse.rs
@@ -1,7 +1,7 @@
// Adapted from https://github.com/Alexhuszagh/rust-lexical.
use crate::lexical::num::Float;
-use crate::lexical::{parse_concise_float, parse_truncated_float};
+use crate::lexical::parse::{parse_concise_float, parse_truncated_float};
use core::f64;
use core::fmt::Debug;
diff --git a/tests/map.rs b/tests/map.rs
index 538cd16..ae01969 100644
--- a/tests/map.rs
+++ b/tests/map.rs
@@ -35,6 +35,7 @@ fn test_append() {
assert!(val.is_empty());
}
+#[cfg(not(no_btreemap_retain))]
#[test]
fn test_retain() {
let mut v: Value = from_str(r#"{"b":null,"a":null,"c":null}"#).unwrap();
diff --git a/tests/regression/issue1004.rs b/tests/regression/issue1004.rs
deleted file mode 100644
index c09fb96..0000000
--- a/tests/regression/issue1004.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-#![cfg(feature = "arbitrary_precision")]
-
-#[test]
-fn test() {
- let float = 5.55f32;
- let value = serde_json::to_value(float).unwrap();
- let json = serde_json::to_string(&value).unwrap();
-
- // If the f32 were cast to f64 by Value before serialization, then this
- // would incorrectly serialize as 5.550000190734863.
- assert_eq!(json, "5.55");
-}
diff --git a/tests/regression/issue845.rs b/tests/regression/issue845.rs
index e8b0c0f..56037ae 100644
--- a/tests/regression/issue845.rs
+++ b/tests/regression/issue845.rs
@@ -1,6 +1,7 @@
#![allow(clippy::trait_duplication_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/8757
use serde::{Deserialize, Deserializer};
+use std::convert::TryFrom;
use std::fmt::{self, Display};
use std::marker::PhantomData;
use std::str::FromStr;
diff --git a/tests/test.rs b/tests/test.rs
index 05b7f86..6c08cc8 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -14,6 +14,9 @@
clippy::vec_init_then_push,
clippy::zero_sized_map_values
)]
+#![cfg_attr(feature = "trace-macros", feature(trace_macros))]
+#[cfg(feature = "trace-macros")]
+trace_macros!(true);
#[macro_use]
mod macros;
@@ -30,12 +33,11 @@ use serde_json::{
from_reader, from_slice, from_str, from_value, json, to_string, to_string_pretty, to_value,
to_vec, Deserializer, Number, Value,
};
+use std::collections::hash_map::DefaultHasher;
use std::collections::BTreeMap;
#[cfg(feature = "raw_value")]
use std::collections::HashMap;
use std::fmt::{self, Debug};
-use std::hash::BuildHasher;
-#[cfg(feature = "raw_value")]
use std::hash::{Hash, Hasher};
use std::io;
use std::iter;
@@ -51,7 +53,7 @@ macro_rules! treemap {
() => {
BTreeMap::new()
};
- ($($k:expr => $v:expr),+ $(,)?) => {
+ ($($k:expr => $v:expr),+) => {
{
let mut m = BTreeMap::new();
$(
@@ -158,29 +160,17 @@ fn test_write_f64() {
#[test]
fn test_encode_nonfinite_float_yields_null() {
- let v = to_value(::std::f64::NAN.copysign(1.0)).unwrap();
- assert!(v.is_null());
-
- let v = to_value(::std::f64::NAN.copysign(-1.0)).unwrap();
+ let v = to_value(::std::f64::NAN).unwrap();
assert!(v.is_null());
let v = to_value(::std::f64::INFINITY).unwrap();
assert!(v.is_null());
- let v = to_value(-::std::f64::INFINITY).unwrap();
- assert!(v.is_null());
-
- let v = to_value(::std::f32::NAN.copysign(1.0)).unwrap();
- assert!(v.is_null());
-
- let v = to_value(::std::f32::NAN.copysign(-1.0)).unwrap();
+ let v = to_value(::std::f32::NAN).unwrap();
assert!(v.is_null());
let v = to_value(::std::f32::INFINITY).unwrap();
assert!(v.is_null());
-
- let v = to_value(-::std::f32::INFINITY).unwrap();
- assert!(v.is_null());
}
#[test]
@@ -274,7 +264,7 @@ fn test_write_object() {
(
treemap!(
"a".to_string() => true,
- "b".to_string() => false,
+ "b".to_string() => false
),
"{\"a\":true,\"b\":false}",
),
@@ -285,7 +275,7 @@ fn test_write_object() {
treemap![
"a".to_string() => treemap![],
"b".to_string() => treemap![],
- "c".to_string() => treemap![],
+ "c".to_string() => treemap![]
],
"{\"a\":{},\"b\":{},\"c\":{}}",
),
@@ -294,10 +284,10 @@ fn test_write_object() {
"a".to_string() => treemap![
"a".to_string() => treemap!["a" => vec![1,2,3]],
"b".to_string() => treemap![],
- "c".to_string() => treemap![],
+ "c".to_string() => treemap![]
],
"b".to_string() => treemap![],
- "c".to_string() => treemap![],
+ "c".to_string() => treemap![]
],
"{\"a\":{\"a\":{\"a\":[1,2,3]},\"b\":{},\"c\":{}},\"b\":{},\"c\":{}}",
),
@@ -307,9 +297,9 @@ fn test_write_object() {
"b".to_string() => treemap![
"a".to_string() => treemap!["a" => vec![1,2,3]],
"b".to_string() => treemap![],
- "c".to_string() => treemap![],
+ "c".to_string() => treemap![]
],
- "c".to_string() => treemap![],
+ "c".to_string() => treemap![]
],
"{\"a\":{},\"b\":{\"a\":{\"a\":[1,2,3]},\"b\":{},\"c\":{}},\"c\":{}}",
),
@@ -320,8 +310,8 @@ fn test_write_object() {
"c".to_string() => treemap![
"a".to_string() => treemap!["a" => vec![1,2,3]],
"b".to_string() => treemap![],
- "c".to_string() => treemap![],
- ],
+ "c".to_string() => treemap![]
+ ]
],
"{\"a\":{},\"b\":{},\"c\":{\"a\":{\"a\":[1,2,3]},\"b\":{},\"c\":{}}}",
),
@@ -334,7 +324,7 @@ fn test_write_object() {
treemap![
"a".to_string() => treemap![],
"b".to_string() => treemap![],
- "c".to_string() => treemap![],
+ "c".to_string() => treemap![]
],
pretty_str!({
"a": {},
@@ -347,10 +337,10 @@ fn test_write_object() {
"a".to_string() => treemap![
"a".to_string() => treemap!["a" => vec![1,2,3]],
"b".to_string() => treemap![],
- "c".to_string() => treemap![],
+ "c".to_string() => treemap![]
],
"b".to_string() => treemap![],
- "c".to_string() => treemap![],
+ "c".to_string() => treemap![]
],
pretty_str!({
"a": {
@@ -374,9 +364,9 @@ fn test_write_object() {
"b".to_string() => treemap![
"a".to_string() => treemap!["a" => vec![1,2,3]],
"b".to_string() => treemap![],
- "c".to_string() => treemap![],
+ "c".to_string() => treemap![]
],
- "c".to_string() => treemap![],
+ "c".to_string() => treemap![]
],
pretty_str!({
"a": {},
@@ -401,8 +391,8 @@ fn test_write_object() {
"c".to_string() => treemap![
"a".to_string() => treemap!["a" => vec![1,2,3]],
"b".to_string() => treemap![],
- "c".to_string() => treemap![],
- ],
+ "c".to_string() => treemap![]
+ ]
],
pretty_str!({
"a": {},
@@ -433,7 +423,7 @@ fn test_write_object() {
(
treemap!(
"a".to_string() => true,
- "b".to_string() => false,
+ "b".to_string() => false
),
pretty_str!( {
"a": true,
@@ -1202,8 +1192,8 @@ fn test_parse_object() {
treemap!(
"a".to_string() => treemap!(
"b".to_string() => 3u64,
- "c".to_string() => 4,
- ),
+ "c".to_string() => 4
+ )
),
)]);
@@ -1379,7 +1369,7 @@ fn test_parse_enum() {
),
treemap!(
"a".to_string() => Animal::Dog,
- "b".to_string() => Animal::Frog("Henry".to_string(), vec![]),
+ "b".to_string() => Animal::Frog("Henry".to_string(), vec![])
),
)]);
}
@@ -1462,6 +1452,7 @@ fn test_serialize_seq_with_no_len() {
where
T: ser::Serialize,
{
+ #[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -1488,6 +1479,7 @@ fn test_serialize_seq_with_no_len() {
formatter.write_str("array")
}
+ #[inline]
fn visit_unit<E>(self) -> Result<MyVec<T>, E>
where
E: de::Error,
@@ -1495,6 +1487,7 @@ fn test_serialize_seq_with_no_len() {
Ok(MyVec(Vec::new()))
}
+ #[inline]
fn visit_seq<V>(self, mut visitor: V) -> Result<MyVec<T>, V::Error>
where
V: de::SeqAccess<'de>,
@@ -1545,6 +1538,7 @@ fn test_serialize_map_with_no_len() {
K: ser::Serialize + Ord,
V: ser::Serialize,
{
+ #[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -1572,6 +1566,7 @@ fn test_serialize_map_with_no_len() {
formatter.write_str("map")
}
+ #[inline]
fn visit_unit<E>(self) -> Result<MyMap<K, V>, E>
where
E: de::Error,
@@ -1579,6 +1574,7 @@ fn test_serialize_map_with_no_len() {
Ok(MyMap(BTreeMap::new()))
}
+ #[inline]
fn visit_map<Visitor>(self, mut visitor: Visitor) -> Result<MyMap<K, V>, Visitor::Error>
where
Visitor: de::MapAccess<'de>,
@@ -1665,11 +1661,22 @@ fn test_deserialize_from_stream() {
}
#[test]
+fn test_serialize_rejects_bool_keys() {
+ let map = treemap!(
+ true => 2,
+ false => 4
+ );
+
+ let err = to_vec(&map).unwrap_err();
+ assert_eq!(err.to_string(), "key must be a string");
+}
+
+#[test]
fn test_serialize_rejects_adt_keys() {
let map = treemap!(
Some("a") => 2,
Some("b") => 4,
- None => 6,
+ None => 6
);
let err = to_vec(&map).unwrap_err();
@@ -1883,41 +1890,23 @@ fn test_integer_key() {
// map with integer keys
let map = treemap!(
1 => 2,
- -1 => 6,
+ -1 => 6
);
let j = r#"{"-1":6,"1":2}"#;
test_encode_ok(&[(&map, j)]);
test_parse_ok(vec![(j, map)]);
- test_parse_err::<BTreeMap<i32, ()>>(&[
- (
- r#"{"x":null}"#,
- "invalid value: expected key to be a number in quotes at line 1 column 2",
- ),
- (
- r#"{" 123":null}"#,
- "invalid value: expected key to be a number in quotes at line 1 column 2",
- ),
- (r#"{"123 ":null}"#, "expected `\"` at line 1 column 6"),
- ]);
-
- let err = from_value::<BTreeMap<i32, ()>>(json!({" 123":null})).unwrap_err();
- assert_eq!(
- err.to_string(),
- "invalid value: expected key to be a number in quotes",
- );
-
- let err = from_value::<BTreeMap<i32, ()>>(json!({"123 ":null})).unwrap_err();
- assert_eq!(
- err.to_string(),
- "invalid value: expected key to be a number in quotes",
- );
+ let j = r#"{"x":null}"#;
+ test_parse_err::<BTreeMap<i32, ()>>(&[(
+ j,
+ "invalid type: string \"x\", expected i32 at line 1 column 4",
+ )]);
}
#[test]
fn test_integer128_key() {
let map = treemap! {
- 100000000000000000000000000000000000000u128 => (),
+ 100000000000000000000000000000000000000u128 => ()
};
let j = r#"{"100000000000000000000000000000000000000":null}"#;
assert_eq!(to_string(&map).unwrap(), j);
@@ -1925,107 +1914,24 @@ fn test_integer128_key() {
}
#[test]
-fn test_float_key() {
- #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone)]
+fn test_deny_float_key() {
+ #[derive(Eq, PartialEq, Ord, PartialOrd)]
struct Float;
impl Serialize for Float {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
- serializer.serialize_f32(1.23)
- }
- }
- impl<'de> Deserialize<'de> for Float {
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where
- D: de::Deserializer<'de>,
- {
- f32::deserialize(deserializer).map(|_| Float)
+ serializer.serialize_f32(1.0)
}
}
// map with float key
- let map = treemap!(Float => "x".to_owned());
- let j = r#"{"1.23":"x"}"#;
-
- test_encode_ok(&[(&map, j)]);
- test_parse_ok(vec![(j, map)]);
-
- let j = r#"{"x": null}"#;
- test_parse_err::<BTreeMap<Float, ()>>(&[(
- j,
- "invalid value: expected key to be a number in quotes at line 1 column 2",
- )]);
-}
-
-#[test]
-fn test_deny_non_finite_f32_key() {
- // We store float bits so that we can derive Ord, and other traits. In a
- // real context the code might involve a crate like ordered-float.
-
- #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone)]
- struct F32Bits(u32);
- impl Serialize for F32Bits {
- fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
- where
- S: Serializer,
- {
- serializer.serialize_f32(f32::from_bits(self.0))
- }
- }
-
- let map = treemap!(F32Bits(f32::INFINITY.to_bits()) => "x".to_owned());
- assert!(serde_json::to_string(&map).is_err());
- assert!(serde_json::to_value(map).is_err());
-
- let map = treemap!(F32Bits(f32::NEG_INFINITY.to_bits()) => "x".to_owned());
- assert!(serde_json::to_string(&map).is_err());
- assert!(serde_json::to_value(map).is_err());
-
- let map = treemap!(F32Bits(f32::NAN.to_bits()) => "x".to_owned());
- assert!(serde_json::to_string(&map).is_err());
+ let map = treemap!(Float => "x");
assert!(serde_json::to_value(map).is_err());
}
#[test]
-fn test_deny_non_finite_f64_key() {
- // We store float bits so that we can derive Ord, and other traits. In a
- // real context the code might involve a crate like ordered-float.
-
- #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone)]
- struct F64Bits(u64);
- impl Serialize for F64Bits {
- fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
- where
- S: Serializer,
- {
- serializer.serialize_f64(f64::from_bits(self.0))
- }
- }
-
- let map = treemap!(F64Bits(f64::INFINITY.to_bits()) => "x".to_owned());
- assert!(serde_json::to_string(&map).is_err());
- assert!(serde_json::to_value(map).is_err());
-
- let map = treemap!(F64Bits(f64::NEG_INFINITY.to_bits()) => "x".to_owned());
- assert!(serde_json::to_string(&map).is_err());
- assert!(serde_json::to_value(map).is_err());
-
- let map = treemap!(F64Bits(f64::NAN.to_bits()) => "x".to_owned());
- assert!(serde_json::to_string(&map).is_err());
- assert!(serde_json::to_value(map).is_err());
-}
-
-#[test]
-fn test_boolean_key() {
- let map = treemap!(false => 0, true => 1);
- let j = r#"{"false":0,"true":1}"#;
- test_encode_ok(&[(&map, j)]);
- test_parse_ok(vec![(j, map)]);
-}
-
-#[test]
fn test_borrowed_key() {
let map: BTreeMap<&str, ()> = from_str("{\"borrowed\":null}").unwrap();
let expected = treemap! { "borrowed" => () };
@@ -2048,7 +1954,7 @@ fn test_effectively_string_keys() {
}
let map = treemap! {
Enum::One => 1,
- Enum::Two => 2,
+ Enum::Two => 2
};
let expected = r#"{"One":1,"Two":2}"#;
test_encode_ok(&[(&map, expected)]);
@@ -2058,7 +1964,7 @@ fn test_effectively_string_keys() {
struct Wrapper(String);
let map = treemap! {
Wrapper("zero".to_owned()) => 0,
- Wrapper("one".to_owned()) => 1,
+ Wrapper("one".to_owned()) => 1
};
let expected = r#"{"one":1,"zero":0}"#;
test_encode_ok(&[(&map, expected)]);
@@ -2479,27 +2385,25 @@ fn test_value_into_deserializer() {
let mut map = BTreeMap::new();
map.insert("inner", json!({ "string": "Hello World" }));
- let outer = Outer::deserialize(serde::de::value::MapDeserializer::new(
- map.iter().map(|(k, v)| (*k, v)),
- ))
- .unwrap();
- assert_eq!(outer.inner.string, "Hello World");
-
let outer = Outer::deserialize(map.into_deserializer()).unwrap();
assert_eq!(outer.inner.string, "Hello World");
}
#[test]
fn hash_positive_and_negative_zero() {
- let rand = std::hash::RandomState::new();
+ fn hash(obj: impl Hash) -> u64 {
+ let mut hasher = DefaultHasher::new();
+ obj.hash(&mut hasher);
+ hasher.finish()
+ }
let k1 = serde_json::from_str::<Number>("0.0").unwrap();
let k2 = serde_json::from_str::<Number>("-0.0").unwrap();
if cfg!(feature = "arbitrary_precision") {
assert_ne!(k1, k2);
- assert_ne!(rand.hash_one(k1), rand.hash_one(k2));
+ assert_ne!(hash(k1), hash(k2));
} else {
assert_eq!(k1, k2);
- assert_eq!(rand.hash_one(k1), rand.hash_one(k2));
+ assert_eq!(hash(k1), hash(k2));
}
}
diff --git a/tests/ui/parse_key.stderr b/tests/ui/parse_key.stderr
index 15662dc..f10c218 100644
--- a/tests/ui/parse_key.stderr
+++ b/tests/ui/parse_key.stderr
@@ -2,4 +2,4 @@ error[E0609]: no field `s` on type `&'static str`
--> tests/ui/parse_key.rs:4:16
|
4 | json!({ "".s : true });
- | ^ unknown field
+ | ^