diff options
author | David LeGare <legare@google.com> | 2022-03-02 16:21:22 +0000 |
---|---|---|
committer | David LeGare <legare@google.com> | 2022-03-02 16:21:22 +0000 |
commit | 2f2c465ed15d06f9bac021f14c63506cfe700ae9 (patch) | |
tree | 58f7f050cf3633807c295fb927d3752b7b5a1a0d /src | |
parent | 88d364f35e6339938bed10e0272e4cbd0aa70f3f (diff) | |
download | serde_json-2f2c465ed15d06f9bac021f14c63506cfe700ae9.tar.gz |
Update serde_json to 1.0.79
Test: cd external/rust/crates && atest --host -c
Change-Id: Ic547cf00640b27bac6afe4f77c3c546d472c3d6e
Diffstat (limited to 'src')
-rw-r--r-- | src/de.rs | 54 | ||||
-rw-r--r-- | src/error.rs | 9 | ||||
-rw-r--r-- | src/io/core.rs | 4 | ||||
-rw-r--r-- | src/lexical/algorithm.rs | 2 | ||||
-rw-r--r-- | src/lexical/bhcomp.rs | 2 | ||||
-rw-r--r-- | src/lexical/bignum.rs | 2 | ||||
-rw-r--r-- | src/lexical/float.rs | 2 | ||||
-rw-r--r-- | src/lexical/math.rs | 11 | ||||
-rw-r--r-- | src/lexical/num.rs | 2 | ||||
-rw-r--r-- | src/lexical/rounding.rs | 2 | ||||
-rw-r--r-- | src/lexical/shift.rs | 2 | ||||
-rw-r--r-- | src/lib.rs | 76 | ||||
-rw-r--r-- | src/map.rs | 44 | ||||
-rw-r--r-- | src/number.rs | 44 | ||||
-rw-r--r-- | src/raw.rs | 21 | ||||
-rw-r--r-- | src/read.rs | 133 | ||||
-rw-r--r-- | src/ser.rs | 17 | ||||
-rw-r--r-- | src/value/de.rs | 10 | ||||
-rw-r--r-- | src/value/from.rs | 6 | ||||
-rw-r--r-- | src/value/index.rs | 9 | ||||
-rw-r--r-- | src/value/mod.rs | 8 | ||||
-rw-r--r-- | src/value/partial_eq.rs | 2 | ||||
-rw-r--r-- | src/value/ser.rs | 13 |
23 files changed, 301 insertions, 174 deletions
@@ -3,10 +3,16 @@ use crate::error::{Error, ErrorCode, Result}; #[cfg(feature = "float_roundtrip")] use crate::lexical; -use crate::lib::str::FromStr; -use crate::lib::*; use crate::number::Number; use crate::read::{self, Fused, Reference}; +use alloc::string::String; +use alloc::vec::Vec; +#[cfg(feature = "float_roundtrip")] +use core::iter; +use core::iter::FusedIterator; +use core::marker::PhantomData; +use core::result; +use core::str::FromStr; use serde::de::{self, Expected, Unexpected}; use serde::{forward_to_deserialize_any, serde_if_integer128}; @@ -87,7 +93,9 @@ impl<'a> Deserializer<read::StrRead<'a>> { macro_rules! overflow { ($a:ident * 10 + $b:ident, $c:expr) => { - $a >= $c / 10 && ($a > $c / 10 || $b > $c % 10) + match $c { + c => $a >= c / 10 && ($a > c / 10 || $b > c % 10), + } }; } @@ -856,6 +864,15 @@ impl<'de, R: Read<'de>> Deserializer<R> { buf.push('-'); } self.scan_integer(&mut buf)?; + if positive { + if let Ok(unsigned) = buf.parse() { + return Ok(ParserNumber::U64(unsigned)); + } + } else { + if let Ok(signed) = buf.parse() { + return Ok(ParserNumber::I64(signed)); + } + } Ok(ParserNumber::String(buf)) } @@ -1560,7 +1577,8 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer<R> { /// /// # Examples /// - /// You can use this to parse JSON strings containing invalid UTF-8 bytes. + /// You can use this to parse JSON strings containing invalid UTF-8 bytes, + /// or unpaired surrogates. /// /// ``` /// use serde_bytes::ByteBuf; @@ -1580,20 +1598,18 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer<R> { /// ``` /// /// Backslash escape sequences like `\n` are still interpreted and required - /// to be valid, and `\u` escape sequences are required to represent valid - /// Unicode code points. + /// to be valid. `\u` escape sequences are required to represent a valid + /// Unicode code point or lone surrogate. /// /// ``` /// use serde_bytes::ByteBuf; /// - /// fn look_at_bytes() { - /// let json_data = b"\"invalid unicode surrogate: \\uD801\""; - /// let parsed: Result<ByteBuf, _> = serde_json::from_slice(json_data); - /// - /// assert!(parsed.is_err()); - /// - /// let expected_msg = "unexpected end of hex escape at line 1 column 35"; - /// assert_eq!(expected_msg, parsed.unwrap_err().to_string()); + /// fn look_at_bytes() -> Result<(), serde_json::Error> { + /// let json_data = b"\"lone surrogate: \\uD801\""; + /// let bytes: ByteBuf = serde_json::from_slice(json_data)?; + /// let expected = b"lone surrogate: \xED\xA0\x81"; + /// assert_eq!(expected, bytes.as_slice()); + /// Ok(()) /// } /// # /// # look_at_bytes(); @@ -2168,10 +2184,18 @@ where } #[inline] - fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value> + fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value> where V: de::Visitor<'de>, { + #[cfg(feature = "raw_value")] + { + if name == crate::raw::TOKEN { + return self.de.deserialize_raw_value(visitor); + } + } + + let _ = name; visitor.visit_newtype_struct(self) } diff --git a/src/error.rs b/src/error.rs index 4219d32..6390c43 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,9 +1,14 @@ //! When serializing or deserializing JSON goes wrong. use crate::io; -use crate::lib::str::FromStr; -use crate::lib::*; +use alloc::boxed::Box; +use alloc::string::{String, ToString}; +use core::fmt::{self, Debug, Display}; +use core::result; +use core::str::FromStr; use serde::{de, ser}; +#[cfg(feature = "std")] +use std::error; /// This type represents all possible errors that can occur when serializing or /// deserializing JSON data. diff --git a/src/io/core.rs b/src/io/core.rs index 97354eb..465ab8b 100644 --- a/src/io/core.rs +++ b/src/io/core.rs @@ -1,7 +1,9 @@ //! Reimplements core logic and types from `std::io` in an `alloc`-friendly //! fashion. -use crate::lib::*; +use alloc::vec::Vec; +use core::fmt::{self, Display}; +use core::result; pub enum ErrorKind { Other, diff --git a/src/lexical/algorithm.rs b/src/lexical/algorithm.rs index d01e5b9..a2cbf18 100644 --- a/src/lexical/algorithm.rs +++ b/src/lexical/algorithm.rs @@ -133,7 +133,7 @@ where let shift = fp.normalize(); errors <<= shift; - u64::error_is_accurate::<F>(errors, &fp) + u64::error_is_accurate::<F>(errors, fp) } } diff --git a/src/lexical/bhcomp.rs b/src/lexical/bhcomp.rs index 6d76c59..1f2a7bb 100644 --- a/src/lexical/bhcomp.rs +++ b/src/lexical/bhcomp.rs @@ -12,7 +12,7 @@ use super::float::*; use super::math::*; use super::num::*; use super::rounding::*; -use crate::lib::{cmp, mem}; +use core::{cmp, mem}; // MANTISSA diff --git a/src/lexical/bignum.rs b/src/lexical/bignum.rs index dee4e68..f9551f5 100644 --- a/src/lexical/bignum.rs +++ b/src/lexical/bignum.rs @@ -3,7 +3,7 @@ //! Big integer type definition. use super::math::*; -use crate::lib::Vec; +use alloc::vec::Vec; /// Storage for a big integer type. #[derive(Clone, PartialEq, Eq)] diff --git a/src/lexical/float.rs b/src/lexical/float.rs index e320ead..2d434a2 100644 --- a/src/lexical/float.rs +++ b/src/lexical/float.rs @@ -108,7 +108,7 @@ impl ExtendedFloat { F: Float, Algorithm: FnOnce(&mut ExtendedFloat, i32), { - round_to_native::<F, _>(self, algorithm) + round_to_native::<F, _>(self, algorithm); } // FROM diff --git a/src/lexical/math.rs b/src/lexical/math.rs index 4890c0f..37cc1d2 100644 --- a/src/lexical/math.rs +++ b/src/lexical/math.rs @@ -9,7 +9,8 @@ use super::large_powers; use super::num::*; use super::small_powers::*; -use crate::lib::{cmp, iter, mem, Vec}; +use alloc::vec::Vec; +use core::{cmp, iter, mem}; // ALIASES // ------- @@ -593,7 +594,7 @@ mod large { // Iteratively add elements from y to x. let mut carry = false; - for (xi, yi) in (&mut x[xstart..]).iter_mut().zip(y.iter()) { + for (xi, yi) in x[xstart..].iter_mut().zip(y.iter()) { // Only one op of the two can overflow, since we added at max // Limb::max_value() + Limb::max_value(). Add the previous carry, // and store the current carry for the next. @@ -613,7 +614,7 @@ mod large { /// AddAssign bigint to bigint. #[inline] pub fn iadd(x: &mut Vec<Limb>, y: &[Limb]) { - iadd_impl(x, y, 0) + iadd_impl(x, y, 0); } /// Add bigint to bigint. @@ -859,13 +860,13 @@ pub(crate) trait Math: Clone + Sized + Default { /// Multiply by a power of 2. #[inline] fn imul_pow2(&mut self, n: u32) { - self.ishl(n as usize) + self.ishl(n as usize); } /// Multiply by a power of 5. #[inline] fn imul_pow5(&mut self, n: u32) { - small::imul_pow5(self.data_mut(), n) + small::imul_pow5(self.data_mut(), n); } /// MulAssign by a power of 10. diff --git a/src/lexical/num.rs b/src/lexical/num.rs index 27c78ed..e47e003 100644 --- a/src/lexical/num.rs +++ b/src/lexical/num.rs @@ -2,7 +2,7 @@ //! Utilities for Rust numbers. -use crate::lib::ops; +use core::ops; /// Precalculated values of radix**i for i in range [0, arr.len()-1]. /// Each value can be **exactly** represented as that type. diff --git a/src/lexical/rounding.rs b/src/lexical/rounding.rs index d2704c9..6ec1292 100644 --- a/src/lexical/rounding.rs +++ b/src/lexical/rounding.rs @@ -5,7 +5,7 @@ use super::float::ExtendedFloat; use super::num::*; use super::shift::*; -use crate::lib::mem; +use core::mem; // MASKS diff --git a/src/lexical/shift.rs b/src/lexical/shift.rs index b0bd469..a0bae01 100644 --- a/src/lexical/shift.rs +++ b/src/lexical/shift.rs @@ -3,7 +3,7 @@ //! Bit-shift helpers. use super::float::ExtendedFloat; -use crate::lib::mem; +use core::mem; // Shift extended-precision float right `shift` bytes. #[inline] @@ -300,10 +300,10 @@ //! [macro]: https://docs.serde.rs/serde_json/macro.json.html //! [`serde-json-core`]: https://github.com/rust-embedded-community/serde-json-core -#![doc(html_root_url = "https://docs.rs/serde_json/1.0.68")] -#![deny(clippy::all, clippy::pedantic)] +#![doc(html_root_url = "https://docs.rs/serde_json/1.0.79")] // Ignored clippy lints #![allow( + clippy::collapsible_else_if, clippy::comparison_chain, clippy::deprecated_cfg_attr, clippy::doc_markdown, @@ -313,6 +313,10 @@ clippy::match_like_matches_macro, 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::unnecessary_wraps, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704 @@ -320,6 +324,8 @@ )] // 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 @@ -359,65 +365,8 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(docsrs, feature(doc_cfg))] -//////////////////////////////////////////////////////////////////////////////// - -#[cfg(not(feature = "std"))] extern crate alloc; -/// A facade around all the types we need from the `std`, `core`, and `alloc` -/// crates. This avoids elaborate import wrangling having to happen in every -/// module. -mod lib { - mod core { - #[cfg(not(feature = "std"))] - pub use core::*; - #[cfg(feature = "std")] - pub use std::*; - } - - pub use self::core::cell::{Cell, RefCell}; - pub use self::core::clone::{self, Clone}; - pub use self::core::convert::{self, From, Into}; - pub use self::core::default::{self, Default}; - pub use self::core::fmt::{self, Debug, Display}; - pub use self::core::hash::{self, Hash}; - pub use self::core::iter::FusedIterator; - pub use self::core::marker::{self, PhantomData}; - pub use self::core::ops::{Bound, RangeBounds}; - pub use self::core::result::{self, Result}; - pub use self::core::{borrow, char, cmp, iter, mem, num, ops, slice, str}; - - #[cfg(not(feature = "std"))] - pub use alloc::borrow::{Cow, ToOwned}; - #[cfg(feature = "std")] - pub use std::borrow::{Cow, ToOwned}; - - #[cfg(not(feature = "std"))] - pub use alloc::string::{String, ToString}; - #[cfg(feature = "std")] - pub use std::string::{String, ToString}; - - #[cfg(not(feature = "std"))] - pub use alloc::vec::{self, Vec}; - #[cfg(feature = "std")] - pub use std::vec::{self, Vec}; - - #[cfg(not(feature = "std"))] - pub use alloc::boxed::Box; - #[cfg(feature = "std")] - pub use std::boxed::Box; - - #[cfg(not(feature = "std"))] - pub use alloc::collections::{btree_map, BTreeMap}; - #[cfg(feature = "std")] - pub use std::collections::{btree_map, BTreeMap}; - - #[cfg(feature = "std")] - pub use std::error; -} - -//////////////////////////////////////////////////////////////////////////////// - #[cfg(feature = "std")] #[doc(inline)] pub use crate::de::from_reader; @@ -436,15 +385,12 @@ pub use crate::value::{from_value, to_value, Map, Number, Value}; // We only use our own error type; no need for From conversions provided by the // standard library's try! macro. This reduces lines of LLVM IR by 4%. macro_rules! tri { - ($e:expr) => { + ($e:expr $(,)?) => { match $e { - crate::lib::Result::Ok(val) => val, - crate::lib::Result::Err(err) => return crate::lib::Result::Err(err), + core::result::Result::Ok(val) => val, + core::result::Result::Err(err) => return core::result::Result::Err(err), } }; - ($e:expr,) => { - tri!($e) - }; } #[macro_use] @@ -6,12 +6,19 @@ //! [`BTreeMap`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html //! [`IndexMap`]: https://docs.rs/indexmap/*/indexmap/map/struct.IndexMap.html -use crate::lib::borrow::Borrow; -use crate::lib::iter::FromIterator; -use crate::lib::*; use crate::value::Value; +use alloc::string::String; +use core::borrow::Borrow; +use core::fmt::{self, Debug}; +use core::hash::Hash; +use core::iter::{FromIterator, FusedIterator}; +#[cfg(feature = "preserve_order")] +use core::mem; +use core::ops; use serde::de; +#[cfg(not(feature = "preserve_order"))] +use alloc::collections::{btree_map, BTreeMap}; #[cfg(feature = "preserve_order")] use indexmap::{self, IndexMap}; @@ -94,6 +101,20 @@ impl Map<String, Value> { self.map.get_mut(key) } + /// Returns the key-value pair matching the given key. + /// + /// 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>, + Q: ?Sized + Ord + Eq + Hash, + { + self.map.get_key_value(key) + } + /// Inserts a key-value pair into the map. /// /// If the map did not have this key present, `None` is returned. @@ -151,6 +172,8 @@ impl Map<String, Value> { 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> { @@ -188,7 +211,7 @@ impl Map<String, Value> { S: Into<String>, { #[cfg(not(feature = "preserve_order"))] - use crate::lib::btree_map::Entry as EntryImpl; + use alloc::collections::btree_map::Entry as EntryImpl; #[cfg(feature = "preserve_order")] use indexmap::map::Entry as EntryImpl; @@ -249,6 +272,19 @@ impl Map<String, Value> { iter: self.map.values_mut(), } } + + /// Retains only the elements specified by the predicate. + /// + /// 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 + F: FnMut(&String, &mut Value) -> bool, + { + self.map.retain(f); + } } #[allow(clippy::derivable_impls)] // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7655 diff --git a/src/number.rs b/src/number.rs index c147618..b965271 100644 --- a/src/number.rs +++ b/src/number.rs @@ -1,6 +1,8 @@ use crate::de::ParserNumber; use crate::error::Error; -use crate::lib::*; +use core::fmt::{self, Debug, Display}; +#[cfg(not(feature = "arbitrary_precision"))] +use core::hash::{Hash, Hasher}; use serde::de::{self, Unexpected, Visitor}; use serde::{ forward_to_deserialize_any, serde_if_integer128, Deserialize, Deserializer, Serialize, @@ -16,13 +18,13 @@ use serde::de::{IntoDeserializer, MapAccess}; pub(crate) const TOKEN: &str = "$serde_json::private::Number"; /// Represents a JSON number, whether integer or floating point. -#[derive(Clone, Eq, PartialEq)] +#[derive(Clone, PartialEq, Eq, Hash)] pub struct Number { n: N, } #[cfg(not(feature = "arbitrary_precision"))] -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone)] enum N { PosInt(u64), /// Always less than zero. @@ -31,10 +33,42 @@ enum N { Float(f64), } +#[cfg(not(feature = "arbitrary_precision"))] +impl PartialEq for N { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (N::PosInt(a), N::PosInt(b)) => a == b, + (N::NegInt(a), N::NegInt(b)) => a == b, + (N::Float(a), N::Float(b)) => a == b, + _ => false, + } + } +} + // Implementing Eq is fine since any float values are always finite. #[cfg(not(feature = "arbitrary_precision"))] impl Eq for N {} +#[cfg(not(feature = "arbitrary_precision"))] +impl Hash for N { + fn hash<H: Hasher>(&self, h: &mut H) { + match *self { + N::PosInt(i) => i.hash(h), + N::NegInt(i) => i.hash(h), + N::Float(f) => { + if f == 0.0f64 { + // There are 2 zero representations, +0 and -0, which + // compare equal but have different bits. We use the +0 hash + // for both so that hash(+0) == hash(-0). + 0.0f64.to_bits().hash(h); + } else { + f.to_bits().hash(h); + } + } + } + } +} + #[cfg(feature = "arbitrary_precision")] type N = String; @@ -130,7 +164,7 @@ impl Number { { for c in self.n.chars() { if c == '.' || c == 'e' || c == 'E' { - return self.n.parse::<f64>().ok().map_or(false, |f| f.is_finite()); + return self.n.parse::<f64>().ok().map_or(false, f64::is_finite); } } false @@ -254,7 +288,7 @@ impl Number { } } -impl fmt::Display for Number { +impl Display for Number { #[cfg(not(feature = "arbitrary_precision"))] fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match self.n { @@ -1,5 +1,9 @@ use crate::error::Error; -use crate::lib::*; +use alloc::borrow::ToOwned; +use alloc::boxed::Box; +use alloc::string::String; +use core::fmt::{self, Debug, Display}; +use core::mem; use serde::de::value::BorrowedStrDeserializer; use serde::de::{ self, Deserialize, DeserializeSeed, Deserializer, IntoDeserializer, MapAccess, Unexpected, @@ -122,6 +126,10 @@ impl RawValue { fn from_owned(json: Box<str>) -> Box<Self> { unsafe { mem::transmute::<Box<str>, Box<RawValue>>(json) } } + + fn into_owned(raw_value: Box<Self>) -> Box<str> { + unsafe { mem::transmute::<Box<RawValue>, Box<str>>(raw_value) } + } } impl Clone for Box<RawValue> { @@ -216,6 +224,12 @@ impl RawValue { } } +impl From<Box<RawValue>> for Box<str> { + fn from(raw_value: Box<RawValue>) -> Self { + RawValue::into_owned(raw_value) + } +} + /// Convert a `T` into a boxed `RawValue`. /// /// # Example @@ -271,7 +285,7 @@ impl RawValue { #[cfg_attr(docsrs, doc(cfg(feature = "raw_value")))] pub fn to_raw_value<T>(value: &T) -> Result<Box<RawValue>, Error> where - T: Serialize, + T: ?Sized + Serialize, { let json_string = crate::to_string(value)?; Ok(RawValue::from_owned(json_string.into_boxed_str())) @@ -435,9 +449,10 @@ impl<'de> Visitor<'de> for BoxedFromString { where E: de::Error, { - self.visit_string(s.to_owned()) + Ok(RawValue::from_owned(s.to_owned().into_boxed_str())) } + #[cfg(any(feature = "std", feature = "alloc"))] fn visit_string<E>(self, s: String) -> Result<Self::Value, E> where E: de::Error, diff --git a/src/read.rs b/src/read.rs index 8ed3d7d..1319d89 100644 --- a/src/read.rs +++ b/src/read.rs @@ -1,6 +1,9 @@ use crate::error::{Error, ErrorCode, Result}; -use crate::lib::ops::Deref; -use crate::lib::*; +use alloc::vec::Vec; +use core::char; +use core::cmp; +use core::ops::Deref; +use core::str; #[cfg(feature = "std")] use crate::io; @@ -225,7 +228,7 @@ where return result(self, scratch); } b'\\' => { - tri!(parse_escape(self, scratch)); + tri!(parse_escape(self, validate, scratch)); } _ => { if validate { @@ -465,7 +468,7 @@ impl<'a> SliceRead<'a> { b'\\' => { scratch.extend_from_slice(&self.slice[start..self.index]); self.index += 1; - tri!(parse_escape(self, scratch)); + tri!(parse_escape(self, validate, scratch)); start = self.index; } _ => { @@ -654,8 +657,9 @@ impl<'a> Read<'a> for StrRead<'a> { fn parse_str<'s>(&'s mut self, scratch: &'s mut Vec<u8>) -> Result<Reference<'a, 's, str>> { self.delegate.parse_str_bytes(scratch, true, |_, bytes| { - // The input is assumed to be valid UTF-8 and the \u-escapes are - // checked along the way, so don't need to check here. + // The deserialization input came in as &str with a UTF-8 guarantee, + // and the \u-escapes are checked along the way, so don't need to + // check here. Ok(unsafe { str::from_utf8_unchecked(bytes) }) }) } @@ -677,7 +681,7 @@ impl<'a> Read<'a> for StrRead<'a> { #[cfg(feature = "raw_value")] fn begin_raw_buffering(&mut self) { - self.delegate.begin_raw_buffering() + self.delegate.begin_raw_buffering(); } #[cfg(feature = "raw_value")] @@ -753,7 +757,7 @@ where #[cfg(feature = "raw_value")] fn begin_raw_buffering(&mut self) { - R::begin_raw_buffering(self) + R::begin_raw_buffering(self); } #[cfg(feature = "raw_value")] @@ -816,6 +820,16 @@ where } } +fn peek_or_eof<'de, R>(read: &mut R) -> Result<u8> +where + R: ?Sized + Read<'de>, +{ + match tri!(read.peek()) { + Some(b) => Ok(b), + None => error(read, ErrorCode::EofWhileParsingString), + } +} + fn error<'de, R, T>(read: &R, reason: ErrorCode) -> Result<T> where R: ?Sized + Read<'de>, @@ -830,7 +844,11 @@ fn as_str<'de, 's, R: Read<'de>>(read: &R, slice: &'s [u8]) -> Result<&'s str> { /// Parses a JSON escape sequence and appends it into the scratch space. Assumes /// the previous byte read was a backslash. -fn parse_escape<'de, R: Read<'de>>(read: &mut R, scratch: &mut Vec<u8>) -> Result<()> { +fn parse_escape<'de, R: Read<'de>>( + read: &mut R, + validate: bool, + scratch: &mut Vec<u8>, +) -> Result<()> { let ch = tri!(next_or_eof(read)); match ch { @@ -843,19 +861,56 @@ fn parse_escape<'de, R: Read<'de>>(read: &mut R, scratch: &mut Vec<u8>) -> Resul b'r' => scratch.push(b'\r'), b't' => scratch.push(b'\t'), b'u' => { + fn encode_surrogate(scratch: &mut Vec<u8>, n: u16) { + scratch.extend_from_slice(&[ + (n >> 12 & 0b0000_1111) as u8 | 0b1110_0000, + (n >> 6 & 0b0011_1111) as u8 | 0b1000_0000, + (n & 0b0011_1111) as u8 | 0b1000_0000, + ]); + } + let c = match tri!(read.decode_hex_escape()) { - 0xDC00..=0xDFFF => { - return error(read, ErrorCode::LoneLeadingSurrogateInHexEscape); + n @ 0xDC00..=0xDFFF => { + return if validate { + error(read, ErrorCode::LoneLeadingSurrogateInHexEscape) + } else { + encode_surrogate(scratch, n); + Ok(()) + }; } - // Non-BMP characters are encoded as a sequence of - // two hex escapes, representing UTF-16 surrogates. + // Non-BMP characters are encoded as a sequence of two hex + // escapes, representing UTF-16 surrogates. If deserializing a + // utf-8 string the surrogates are required to be paired, + // whereas deserializing a byte string accepts lone surrogates. n1 @ 0xD800..=0xDBFF => { - if tri!(next_or_eof(read)) != b'\\' { - return error(read, ErrorCode::UnexpectedEndOfHexEscape); + if tri!(peek_or_eof(read)) == b'\\' { + read.discard(); + } else { + return if validate { + read.discard(); + error(read, ErrorCode::UnexpectedEndOfHexEscape) + } else { + encode_surrogate(scratch, n1); + Ok(()) + }; } - if tri!(next_or_eof(read)) != b'u' { - return error(read, ErrorCode::UnexpectedEndOfHexEscape); + + if tri!(peek_or_eof(read)) == b'u' { + read.discard(); + } else { + return if validate { + read.discard(); + error(read, ErrorCode::UnexpectedEndOfHexEscape) + } else { + encode_surrogate(scratch, n1); + // The \ prior to this byte started an escape sequence, + // so we need to parse that now. This recursive call + // does not blow the stack on malicious input because + // the escape is not \u, so it will be handled by one + // of the easy nonrecursive cases. + parse_escape(read, validate, scratch) + }; } let n2 = tri!(read.decode_hex_escape()); @@ -874,12 +929,9 @@ fn parse_escape<'de, R: Read<'de>>(read: &mut R, scratch: &mut Vec<u8>) -> Resul } } - n => match char::from_u32(n as u32) { - Some(c) => c, - None => { - return error(read, ErrorCode::InvalidUnicodeCodePoint); - } - }, + // Every u16 outside of the surrogate ranges above is guaranteed + // to be a legal char. + n => char::from_u32(n as u32).unwrap(), }; scratch.extend_from_slice(c.encode_utf8(&mut [0_u8; 4]).as_bytes()); @@ -903,36 +955,13 @@ where match ch { b'"' | b'\\' | b'/' | b'b' | b'f' | b'n' | b'r' | b't' => {} b'u' => { - let n = match tri!(read.decode_hex_escape()) { - 0xDC00..=0xDFFF => { - return error(read, ErrorCode::LoneLeadingSurrogateInHexEscape); - } + // At this point we don't care if the codepoint is valid. We just + // want to consume it. We don't actually know what is valid or not + // at this point, because that depends on if this string will + // ultimately be parsed into a string or a byte buffer in the "real" + // parse. - // Non-BMP characters are encoded as a sequence of - // two hex escapes, representing UTF-16 surrogates. - n1 @ 0xD800..=0xDBFF => { - if tri!(next_or_eof(read)) != b'\\' { - return error(read, ErrorCode::UnexpectedEndOfHexEscape); - } - if tri!(next_or_eof(read)) != b'u' { - return error(read, ErrorCode::UnexpectedEndOfHexEscape); - } - - let n2 = tri!(read.decode_hex_escape()); - - if n2 < 0xDC00 || n2 > 0xDFFF { - return error(read, ErrorCode::LoneLeadingSurrogateInHexEscape); - } - - (((n1 - 0xD800) as u32) << 10 | (n2 - 0xDC00) as u32) + 0x1_0000 - } - - n => n as u32, - }; - - if char::from_u32(n).is_none() { - return error(read, ErrorCode::InvalidUnicodeCodePoint); - } + tri!(read.decode_hex_escape()); } _ => { return error(read, ErrorCode::InvalidEscape); @@ -2,8 +2,10 @@ use crate::error::{Error, ErrorCode, Result}; use crate::io; -use crate::lib::num::FpCategory; -use crate::lib::*; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; +use core::fmt::{self, Display}; +use core::num::FpCategory; use serde::ser::{self, Impossible, Serialize}; use serde::serde_if_integer128; @@ -756,7 +758,7 @@ where #[cfg(feature = "arbitrary_precision")] Compound::Number { ref mut ser, .. } => { if key == crate::number::TOKEN { - tri!(value.serialize(NumberStrEmitter(&mut *ser))); + tri!(value.serialize(NumberStrEmitter(ser))); Ok(()) } else { Err(invalid_number()) @@ -765,7 +767,7 @@ where #[cfg(feature = "raw_value")] Compound::RawValue { ref mut ser, .. } => { if key == crate::raw::TOKEN { - tri!(value.serialize(RawValueStrEmitter(&mut *ser))); + tri!(value.serialize(RawValueStrEmitter(ser))); Ok(()) } else { Err(invalid_raw_value()) @@ -1546,6 +1548,13 @@ impl<'a, W: io::Write, F: Formatter> ser::Serializer for RawValueStrEmitter<'a, ) -> Result<Self::SerializeStructVariant> { Err(ser::Error::custom("expected RawValue")) } + + fn collect_str<T>(self, value: &T) -> Result<Self::Ok> + where + T: ?Sized + Display, + { + self.serialize_str(&value.to_string()) + } } /// Represents a character escape code in a type-safe manner. diff --git a/src/value/de.rs b/src/value/de.rs index 24ca826..75e49df 100644 --- a/src/value/de.rs +++ b/src/value/de.rs @@ -1,9 +1,15 @@ use crate::error::Error; -use crate::lib::str::FromStr; -use crate::lib::*; use crate::map::Map; use crate::number::Number; use crate::value::Value; +use alloc::borrow::{Cow, ToOwned}; +use alloc::string::String; +#[cfg(feature = "raw_value")] +use alloc::string::ToString; +use alloc::vec::{self, Vec}; +use core::fmt; +use core::slice; +use core::str::FromStr; use serde::de::{ self, Deserialize, DeserializeSeed, EnumAccess, Expected, IntoDeserializer, MapAccess, SeqAccess, Unexpected, VariantAccess, Visitor, diff --git a/src/value/from.rs b/src/value/from.rs index 59e09fd..7b37ef6 100644 --- a/src/value/from.rs +++ b/src/value/from.rs @@ -1,8 +1,10 @@ use super::Value; -use crate::lib::iter::FromIterator; -use crate::lib::*; use crate::map::Map; use crate::number::Number; +use alloc::borrow::Cow; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; +use core::iter::FromIterator; #[cfg(feature = "arbitrary_precision")] use serde::serde_if_integer128; diff --git a/src/value/index.rs b/src/value/index.rs index d759a1d..0d90a5d 100644 --- a/src/value/index.rs +++ b/src/value/index.rs @@ -1,6 +1,9 @@ use super::Value; -use crate::lib::*; use crate::map::Map; +use alloc::borrow::ToOwned; +use alloc::string::String; +use core::fmt::{self, Display}; +use core::ops; /// A type that can be used to index into a `serde_json::Value`. /// @@ -133,14 +136,14 @@ mod private { pub trait Sealed {} impl Sealed for usize {} impl Sealed for str {} - impl Sealed for super::String {} + impl Sealed for alloc::string::String {} impl<'a, T> Sealed for &'a T where T: ?Sized + Sealed {} } /// Used in panic messages. struct Type<'a>(&'a Value); -impl<'a> fmt::Display for Type<'a> { +impl<'a> Display for Type<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match *self.0 { Value::Null => formatter.write_str("null"), diff --git a/src/value/mod.rs b/src/value/mod.rs index a28da66..3f00c95 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -92,7 +92,11 @@ use crate::error::Error; use crate::io; -use crate::lib::*; +use alloc::string::String; +use alloc::vec::Vec; +use core::fmt::{self, Debug, Display}; +use core::mem; +use core::str; use serde::de::DeserializeOwned; use serde::ser::Serialize; @@ -191,7 +195,7 @@ impl Debug for Value { } } -impl fmt::Display for Value { +impl Display for Value { /// Display a JSON value as a string. /// /// ``` diff --git a/src/value/partial_eq.rs b/src/value/partial_eq.rs index 354ea5a..b4ef84c 100644 --- a/src/value/partial_eq.rs +++ b/src/value/partial_eq.rs @@ -1,5 +1,5 @@ use super::Value; -use crate::lib::*; +use alloc::string::String; fn eq_i64(value: &Value, other: i64) -> bool { value.as_i64().map_or(false, |i| i == other) diff --git a/src/value/ser.rs b/src/value/ser.rs index 03cb12b..179380a 100644 --- a/src/value/ser.rs +++ b/src/value/ser.rs @@ -1,8 +1,12 @@ use crate::error::{Error, ErrorCode, Result}; -use crate::lib::*; 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; +use core::fmt::Display; +use core::result; use serde::ser::{Impossible, Serialize}; #[cfg(feature = "arbitrary_precision")] @@ -1016,4 +1020,11 @@ impl serde::ser::Serializer for RawValueEmitter { ) -> Result<Self::SerializeStructVariant> { Err(invalid_raw_value()) } + + fn collect_str<T>(self, value: &T) -> Result<Self::Ok> + where + T: ?Sized + Display, + { + self.serialize_str(&value.to_string()) + } } |