aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
21 files changed, 959 insertions, 293 deletions
diff --git a/src/de.rs b/src/de.rs
index 88d0f26..7154f84 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -22,6 +22,7 @@ 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;
//////////////////////////////////////////////////////////////////////////////
@@ -209,7 +210,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
self.disable_recursion_limit = true;
}
- fn peek(&mut self) -> Result<Option<u8>> {
+ pub(crate) fn peek(&mut self) -> Result<Option<u8>> {
self.read.peek()
}
@@ -248,7 +249,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
fn parse_whitespace(&mut self) -> Result<Option<u8>> {
loop {
match tri!(self.peek()) {
- Some(b' ') | Some(b'\n') | Some(b'\t') | Some(b'\r') => {
+ Some(b' ' | b'\n' | b'\t' | b'\r') => {
self.eat_char();
}
other => {
@@ -309,9 +310,9 @@ impl<'de, R: Read<'de>> Deserializer<R> {
self.fix_position(err)
}
- fn deserialize_number<V>(&mut self, visitor: V) -> Result<V::Value>
+ pub(crate) fn deserialize_number<'any, V>(&mut self, visitor: V) -> Result<V::Value>
where
- V: de::Visitor<'de>,
+ V: de::Visitor<'any>,
{
let peek = match tri!(self.parse_whitespace()) {
Some(b) => b,
@@ -335,6 +336,79 @@ 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' => {
@@ -860,7 +934,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
if !positive {
buf.push('-');
}
- self.scan_integer(&mut buf)?;
+ tri!(self.scan_integer(&mut buf));
if positive {
if let Ok(unsigned) = buf.parse() {
return Ok(ParserNumber::U64(unsigned));
@@ -913,7 +987,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' | e @ b'E' => self.scan_exponent(e as char, buf),
+ e @ (b'e' | b'E') => self.scan_exponent(e as char, buf),
_ => Ok(()),
}
}
@@ -938,7 +1012,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
match tri!(self.peek_or_null()) {
- e @ b'e' | e @ b'E' => self.scan_exponent(e as char, buf),
+ e @ (b'e' | b'E') => self.scan_exponent(e as char, buf),
_ => Ok(()),
}
}
@@ -1059,7 +1133,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
tri!(self.read.ignore_str());
None
}
- frame @ b'[' | frame @ b'{' => {
+ frame @ (b'[' | b'{') => {
self.scratch.extend(enclosing.take());
self.eat_char();
Some(frame)
@@ -1204,9 +1278,9 @@ impl<'de, R: Read<'de>> Deserializer<R> {
where
V: de::Visitor<'de>,
{
- self.parse_whitespace()?;
+ tri!(self.parse_whitespace());
self.read.begin_raw_buffering();
- self.ignore_value()?;
+ tri!(self.ignore_value());
self.read.end_raw_buffering(visitor)
}
}
@@ -1258,11 +1332,15 @@ 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.deserialize_number(visitor)
+ self.$using(visitor)
}
};
}
@@ -1424,77 +1502,9 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer<R> {
deserialize_number!(deserialize_f64);
#[cfg(feature = "float_roundtrip")]
- 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)),
- }
- }
+ deserialize_number!(deserialize_f32, do_deserialize_f32);
+ deserialize_number!(deserialize_i128, do_deserialize_i128);
+ deserialize_number!(deserialize_u128, do_deserialize_u128);
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
where
@@ -2118,24 +2128,47 @@ struct MapKey<'a, R: 'a> {
de: &'a mut Deserializer<R>,
}
-macro_rules! deserialize_integer_key {
- ($method:ident => $visit:ident) => {
+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) => {
fn $method<V>(self, visitor: V) -> Result<V::Value>
where
V: de::Visitor<'de>,
{
self.de.eat_char();
- 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),
+
+ 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)),
}
+
+ 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>,
@@ -2155,16 +2188,56 @@ where
}
}
- 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);
+ 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)),
+ }
+ }
#[inline]
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
@@ -2221,8 +2294,8 @@ where
}
forward_to_deserialize_any! {
- bool f32 f64 char str string unit unit_struct seq tuple tuple_struct map
- struct identifier ignored_any
+ char str string unit unit_struct seq tuple tuple_struct map struct
+ identifier ignored_any
}
}
@@ -2318,8 +2391,8 @@ where
fn peek_end_of_value(&mut self) -> Result<()> {
match tri!(self.de.peek()) {
- 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(b' ' | b'\n' | b'\t' | b'\r' | b'"' | b'[' | b']' | b'{' | b'}' | b',' | b':')
+ | None => Ok(()),
Some(_) => {
let position = self.de.read.peek_position();
Err(Error::syntax(
@@ -2369,7 +2442,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) => {
@@ -2408,9 +2481,9 @@ where
Ok(value)
}
-/// Deserialize an instance of type `T` from an IO stream of JSON.
+/// Deserialize an instance of type `T` from an I/O stream of JSON.
///
-/// The content of the IO stream is deserialized directly from the stream
+/// The content of the I/O 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 0898baf..fbf9eb1 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -9,6 +9,8 @@ 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.
@@ -36,15 +38,16 @@ 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 IO
- /// stream fails immediately following a previously read newline character.
+ /// 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.
pub fn column(&self) -> usize {
self.err.column
}
/// Categorizes the cause of this error.
///
- /// - `Category::Io` - failure to read or write bytes on an IO stream
+ /// - `Category::Io` - failure to read or write bytes on an I/O 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
@@ -61,12 +64,15 @@ 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
@@ -76,7 +82,7 @@ impl Error {
}
/// Returns true if this error was caused by a failure to read or write
- /// bytes on an IO stream.
+ /// bytes on an I/O stream.
pub fn is_io(&self) -> bool {
self.classify() == Category::Io
}
@@ -104,12 +110,61 @@ 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 IO
+ /// The error was caused by a failure to read or write bytes on an I/O
/// stream.
Io,
@@ -134,8 +189,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` IO errors.
- /// EOF errors are turned into `UnexpectedEof` IO errors.
+ /// JSON syntax and data errors are turned into `InvalidData` I/O errors.
+ /// EOF errors are turned into `UnexpectedEof` I/O errors.
///
/// ```
/// use std::io;
@@ -165,8 +220,8 @@ impl From<Error> for io::Error {
} else {
match j.classify() {
Category::Io => unreachable!(),
- Category::Syntax | Category::Data => io::Error::new(io::ErrorKind::InvalidData, j),
- Category::Eof => io::Error::new(io::ErrorKind::UnexpectedEof, j),
+ Category::Syntax | Category::Data => io::Error::new(ErrorKind::InvalidData, j),
+ Category::Eof => io::Error::new(ErrorKind::UnexpectedEof, j),
}
}
}
@@ -182,7 +237,7 @@ pub(crate) enum ErrorCode {
/// Catchall for syntax error messages
Message(Box<str>),
- /// Some IO error occurred while serializing or deserializing.
+ /// Some I/O error occurred while serializing or deserializing.
Io(io::Error),
/// EOF while parsing a list.
@@ -212,6 +267,9 @@ 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,
@@ -230,6 +288,12 @@ 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,
@@ -296,6 +360,7 @@ 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"),
@@ -304,6 +369,12 @@ 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")
}
@@ -367,11 +438,20 @@ impl de::Error for Error {
#[cold]
fn invalid_type(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
- 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))
- }
+ 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,
+ ))
}
}
@@ -382,6 +462,22 @@ 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 465ab8b..54c8ddf 100644
--- a/src/io/core.rs
+++ b/src/io/core.rs
@@ -9,7 +9,7 @@ pub enum ErrorKind {
Other,
}
-// IO errors can never occur in no-std mode. All our no-std IO implementations
+// I/O errors can never occur in no-std mode. All our no-std I/O implementations
// are infallible.
pub struct Error;
diff --git a/src/lexical/algorithm.rs b/src/lexical/algorithm.rs
index a2cbf18..eaa5e7e 100644
--- a/src/lexical/algorithm.rs
+++ b/src/lexical/algorithm.rs
@@ -51,7 +51,10 @@ 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 = mantissa.checked_mul(power)?;
+ let value = match mantissa.checked_mul(power) {
+ None => return None,
+ Some(value) => value,
+ };
if value >> mantissa_size != 0 {
None
} else {
diff --git a/src/lexical/digit.rs b/src/lexical/digit.rs
index 882aa9e..3d150a1 100644
--- a/src/lexical/digit.rs
+++ b/src/lexical/digit.rs
@@ -11,5 +11,8 @@ 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> {
- value.checked_mul(10)?.checked_add(digit as u64)
+ match value.checked_mul(10) {
+ None => None,
+ Some(n) => n.checked_add(digit as u64),
+ }
}
diff --git a/src/lexical/errors.rs b/src/lexical/errors.rs
index cad4bd3..f4f41cd 100644
--- a/src/lexical/errors.rs
+++ b/src/lexical/errors.rs
@@ -5,8 +5,7 @@
//! 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 37cc1d2..d7122bf 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 x.iter_mut() {
+ for xi in &mut *x {
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 x.iter_mut() {
+ for xi in &mut *x {
let tmp = *xi;
*xi <<= lshift;
*xi |= prev >> rshift;
diff --git a/src/lexical/num.rs b/src/lexical/num.rs
index e47e003..af10afd 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 exponet
+ /// Bias of the exponent
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 bd49763..aa3fcfc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -55,10 +55,9 @@
//! ```
//!
//! 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_reader`][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`]
+//! for parsing from a byte slice &\[u8\] and [`from_reader`] for parsing from
+//! any `io::Read` like a File or a TCP stream.
//!
//! ```
//! use serde_json::{Result, Value};
@@ -300,7 +299,7 @@
//! [macro]: crate::json
//! [`serde-json-core`]: https://github.com/rust-embedded-community/serde-json-core
-#![doc(html_root_url = "https://docs.rs/serde_json/1.0.94")]
+#![doc(html_root_url = "https://docs.rs/serde_json/1.0.113")]
// Ignored clippy lints
#![allow(
clippy::collapsible_else_if,
@@ -315,18 +314,13 @@
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
- clippy::unnested_or_patterns,
+ clippy::unconditional_recursion, // https://github.com/rust-lang/rust-clippy/issues/12133
+ clippy::unnecessary_wraps
)]
// 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
@@ -362,6 +356,8 @@
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)]
@@ -370,6 +366,7 @@
extern crate alloc;
#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[doc(inline)]
pub use crate::de::from_reader;
#[doc(inline)]
@@ -379,6 +376,7 @@ 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 5287998..e8c6cd2 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -10,7 +10,8 @@
/// "features": [
/// "serde",
/// "json"
-/// ]
+/// ],
+/// "homepage": null
/// }
/// });
/// ```
diff --git a/src/map.rs b/src/map.rs
index 3e8a381..1d74e1b 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::{FromIterator, FusedIterator};
+use core::iter::FusedIterator;
#[cfg(feature = "preserve_order")]
use core::mem;
use core::ops;
@@ -106,7 +106,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.
#[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>,
@@ -131,6 +130,12 @@ 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
@@ -138,7 +143,7 @@ impl Map<String, Value> {
Q: ?Sized + Ord + Eq + Hash,
{
#[cfg(feature = "preserve_order")]
- return self.map.swap_remove(key);
+ return self.swap_remove(key);
#[cfg(not(feature = "preserve_order"))]
return self.map.remove(key);
}
@@ -148,49 +153,86 @@ 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(any(feature = "preserve_order", not(no_btreemap_remove_entry)))]
+ #[cfg(feature = "preserve_order")]
+ return self.swap_remove_entry(key);
+ #[cfg(not(feature = "preserve_order"))]
return self.map.remove_entry(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)
- }
- }
+ }
- 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))
- }
+ /// 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)
+ }
+
+ /// 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)
}
/// Moves all elements from other into self, leaving other empty.
@@ -276,7 +318,6 @@ 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 21a7641..b0231a8 100644
--- a/src/number.rs
+++ b/src/number.rs
@@ -279,6 +279,62 @@ 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)]
@@ -332,8 +388,8 @@ impl Serialize for Number {
{
use serde::ser::SerializeStruct;
- let mut s = serializer.serialize_struct(TOKEN, 1)?;
- s.serialize_field(TOKEN, &self.n)?;
+ let mut s = tri!(serializer.serialize_struct(TOKEN, 1));
+ tri!(s.serialize_field(TOKEN, &self.n));
s.end()
}
}
@@ -377,11 +433,11 @@ impl<'de> Deserialize<'de> for Number {
where
V: de::MapAccess<'de>,
{
- let value = visitor.next_key::<NumberKey>()?;
+ let value = tri!(visitor.next_key::<NumberKey>());
if value.is_none() {
return Err(de::Error::invalid_type(Unexpected::Map, &self));
}
- let v: NumberFromString = visitor.next_value()?;
+ let v: NumberFromString = tri!(visitor.next_value());
Ok(v.value)
}
}
@@ -420,7 +476,7 @@ impl<'de> de::Deserialize<'de> for NumberKey {
}
}
- deserializer.deserialize_identifier(FieldVisitor)?;
+ tri!(deserializer.deserialize_identifier(FieldVisitor));
Ok(NumberKey)
}
}
@@ -523,7 +579,7 @@ macro_rules! deserialize_number {
where
V: de::Visitor<'de>,
{
- visitor.$visit(self.n.parse().map_err(|_| invalid_number())?)
+ visitor.$visit(tri!(self.n.parse().map_err(|_| invalid_number())))
}
};
}
diff --git a/src/raw.rs b/src/raw.rs
index 6aa4ffc..a2bf0ec 100644
--- a/src/raw.rs
+++ b/src/raw.rs
@@ -177,11 +177,9 @@ 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 = crate::from_str::<&Self>(&json)?;
- if borrowed.json.len() < json.len() {
- return Ok(borrowed.to_owned());
- }
+ let borrowed = tri!(crate::from_str::<&Self>(&json));
+ if borrowed.json.len() < json.len() {
+ return Ok(borrowed.to_owned());
}
Ok(Self::from_owned(json.into_boxed_str()))
}
@@ -287,7 +285,7 @@ pub fn to_raw_value<T>(value: &T) -> Result<Box<RawValue>, Error>
where
T: ?Sized + Serialize,
{
- let json_string = crate::to_string(value)?;
+ let json_string = tri!(crate::to_string(value));
Ok(RawValue::from_owned(json_string.into_boxed_str()))
}
@@ -298,8 +296,8 @@ impl Serialize for RawValue {
where
S: Serializer,
{
- let mut s = serializer.serialize_struct(TOKEN, 1)?;
- s.serialize_field(TOKEN, &self.json)?;
+ let mut s = tri!(serializer.serialize_struct(TOKEN, 1));
+ tri!(s.serialize_field(TOKEN, &self.json));
s.end()
}
}
@@ -322,7 +320,7 @@ impl<'de: 'a, 'a> Deserialize<'de> for &'a RawValue {
where
V: MapAccess<'de>,
{
- let value = visitor.next_key::<RawKey>()?;
+ let value = tri!(visitor.next_key::<RawKey>());
if value.is_none() {
return Err(de::Error::invalid_type(Unexpected::Map, &self));
}
@@ -352,7 +350,7 @@ impl<'de> Deserialize<'de> for Box<RawValue> {
where
V: MapAccess<'de>,
{
- let value = visitor.next_key::<RawKey>()?;
+ let value = tri!(visitor.next_key::<RawKey>());
if value.is_none() {
return Err(de::Error::invalid_type(Unexpected::Map, &self));
}
@@ -392,7 +390,7 @@ impl<'de> Deserialize<'de> for RawKey {
}
}
- deserializer.deserialize_identifier(FieldVisitor)?;
+ tri!(deserializer.deserialize_identifier(FieldVisitor));
Ok(RawKey)
}
}
@@ -529,3 +527,251 @@ 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 fc3a3ca..7446f28 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 sequnce ('\u') in a string.
+ /// Assumes the previous byte was a hex escape sequence ('\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 80c2deb..3742e0b 100644
--- a/src/ser.rs
+++ b/src/ser.rs
@@ -189,12 +189,9 @@ where
#[inline]
fn serialize_bytes(self, value: &[u8]) -> Result<()> {
- 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()
+ self.formatter
+ .write_byte_array(&mut self.writer, value)
+ .map_err(Error::io)
}
#[inline]
@@ -439,17 +436,15 @@ 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
@@ -789,6 +784,10 @@ 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,
@@ -828,8 +827,21 @@ where
type SerializeStruct = Impossible<(), Error>;
type SerializeStructVariant = Impossible<(), Error>;
- fn serialize_bool(self, _value: bool) -> Result<()> {
- Err(key_must_be_a_string())
+ 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_i8(self, value: i8) -> Result<()> {
@@ -1002,12 +1014,46 @@ where
.map_err(Error::io)
}
- fn serialize_f32(self, _value: f32) -> Result<()> {
- Err(key_must_be_a_string())
+ 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_f64(self, _value: f64) -> 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_char(self, value: char) -> Result<()> {
@@ -1043,11 +1089,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,
{
- Err(key_must_be_a_string())
+ value.serialize(self)
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
@@ -1734,6 +1780,24 @@ 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]
@@ -2062,7 +2126,9 @@ static ESCAPE: [u8; 256] = [
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F
];
-/// Serialize the given data structure as JSON into the IO stream.
+/// Serialize the given data structure as JSON into the I/O stream.
+///
+/// Serialization guarantees it only feeds valid UTF-8 sequences to the writer.
///
/// # Errors
///
@@ -2079,9 +2145,11 @@ where
value.serialize(&mut ser)
}
-/// Serialize the given data structure as pretty-printed JSON into the IO
+/// Serialize the given data structure as pretty-printed JSON into the I/O
/// 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 9c266d0..1e8b5ac 100644
--- a/src/value/de.rs
+++ b/src/value/de.rs
@@ -1,4 +1,4 @@
-use crate::error::Error;
+use crate::error::{Error, ErrorCode};
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 visitor.next_key_seed(KeyClassifier)? {
+ match tri!(visitor.next_key_seed(KeyClassifier)) {
#[cfg(feature = "arbitrary_precision")]
Some(KeyClass::Number) => {
- let number: NumberFromString = visitor.next_value()?;
+ let number: NumberFromString = tri!(visitor.next_value());
Ok(Value::Number(number.value))
}
#[cfg(feature = "raw_value")]
Some(KeyClass::RawValue) => {
- let value = visitor.next_value_seed(crate::raw::BoxedFromString)?;
+ let value = tri!(visitor.next_value_seed(crate::raw::BoxedFromString));
crate::from_str(value.get()).map_err(de::Error::custom)
}
Some(KeyClass::Map(first_key)) => {
@@ -482,6 +482,14 @@ 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>,
}
@@ -1120,18 +1128,30 @@ struct MapKeyDeserializer<'de> {
key: Cow<'de, str>,
}
-macro_rules! deserialize_integer_key {
- ($method:ident => $visit:ident) => {
+macro_rules! deserialize_numeric_key {
+ ($method:ident) => {
+ deserialize_numeric_key!($method, deserialize_number);
+ };
+
+ ($method:ident, $using:ident) => {
fn $method<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
- 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),
+ 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));
}
+
+ Ok(number)
}
};
}
@@ -1146,16 +1166,38 @@ impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> {
BorrowedCowStrDeserializer::new(self.key).deserialize_any(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);
+ 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,
+ ))
+ }
+ }
#[inline]
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
@@ -1193,8 +1235,8 @@ impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> {
}
forward_to_deserialize_any! {
- bool f32 f64 char str string bytes byte_buf unit unit_struct seq tuple
- tuple_struct map struct identifier ignored_any
+ char str string bytes byte_buf unit unit_struct seq tuple tuple_struct
+ map struct identifier ignored_any
}
}
@@ -1327,7 +1369,7 @@ impl<'de> de::EnumAccess<'de> for BorrowedCowStrDeserializer<'de> {
where
T: de::DeserializeSeed<'de>,
{
- let value = seed.deserialize(self)?;
+ let value = tri!(seed.deserialize(self));
Ok((value, UnitOnly))
}
}
diff --git a/src/value/from.rs b/src/value/from.rs
index c5a6a39..ed1e333 100644
--- a/src/value/from.rs
+++ b/src/value/from.rs
@@ -4,7 +4,6 @@ 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)*) => {
@@ -29,7 +28,8 @@ from_integer! {
}
impl From<f32> for Value {
- /// Convert 32-bit floating point number to `Value`
+ /// Convert 32-bit floating point number to `Value::Number`, or
+ /// `Value::Null` if infinite or NaN.
///
/// # Examples
///
@@ -40,12 +40,13 @@ impl From<f32> for Value {
/// let x: Value = f.into();
/// ```
fn from(f: f32) -> Self {
- From::from(f as f64)
+ Number::from_f32(f).map_or(Value::Null, Value::Number)
}
}
impl From<f64> for Value {
- /// Convert 64-bit floating point number to `Value`
+ /// Convert 64-bit floating point number to `Value::Number`, or
+ /// `Value::Null` if infinite or NaN.
///
/// # Examples
///
@@ -61,7 +62,7 @@ impl From<f64> for Value {
}
impl From<bool> for Value {
- /// Convert boolean to `Value`
+ /// Convert boolean to `Value::Bool`.
///
/// # Examples
///
@@ -77,7 +78,7 @@ impl From<bool> for Value {
}
impl From<String> for Value {
- /// Convert `String` to `Value`
+ /// Convert `String` to `Value::String`.
///
/// # Examples
///
@@ -92,8 +93,8 @@ impl From<String> for Value {
}
}
-impl<'a> From<&'a str> for Value {
- /// Convert string slice to `Value`
+impl From<&str> for Value {
+ /// Convert string slice to `Value::String`.
///
/// # Examples
///
@@ -109,7 +110,7 @@ impl<'a> From<&'a str> for Value {
}
impl<'a> From<Cow<'a, str>> for Value {
- /// Convert copy-on-write string to `Value`
+ /// Convert copy-on-write string to `Value::String`.
///
/// # Examples
///
@@ -134,7 +135,7 @@ impl<'a> From<Cow<'a, str>> for Value {
}
impl From<Number> for Value {
- /// Convert `Number` to `Value`
+ /// Convert `Number` to `Value::Number`.
///
/// # Examples
///
@@ -150,7 +151,7 @@ impl From<Number> for Value {
}
impl From<Map<String, Value>> for Value {
- /// Convert map (with string keys) to `Value`
+ /// Convert map (with string keys) to `Value::Object`.
///
/// # Examples
///
@@ -167,7 +168,7 @@ impl From<Map<String, Value>> for Value {
}
impl<T: Into<Value>> From<Vec<T>> for Value {
- /// Convert a `Vec` to `Value`
+ /// Convert a `Vec` to `Value::Array`.
///
/// # Examples
///
@@ -182,8 +183,8 @@ impl<T: Into<Value>> From<Vec<T>> for Value {
}
}
-impl<'a, T: Clone + Into<Value>> From<&'a [T]> for Value {
- /// Convert a slice to `Value`
+impl<T: Clone + Into<Value>> From<&[T]> for Value {
+ /// Convert a slice to `Value::Array`.
///
/// # Examples
///
@@ -193,13 +194,13 @@ impl<'a, T: Clone + Into<Value>> From<&'a [T]> for Value {
/// let v: &[&str] = &["lorem", "ipsum", "dolor"];
/// let x: Value = v.into();
/// ```
- fn from(f: &'a [T]) -> Self {
+ fn from(f: &[T]) -> Self {
Value::Array(f.iter().cloned().map(Into::into).collect())
}
}
impl<T: Into<Value>> FromIterator<T> for Value {
- /// Convert an iteratable type to a `Value`
+ /// Create a `Value::Array` by collecting an iterator of array elements.
///
/// # Examples
///
@@ -229,7 +230,7 @@ impl<T: Into<Value>> FromIterator<T> for Value {
}
impl<K: Into<String>, V: Into<Value>> FromIterator<(K, V)> for Value {
- /// Convert an iteratable type to a `Value`
+ /// Create a `Value::Object` by collecting an iterator of key-value pairs.
///
/// # Examples
///
@@ -249,7 +250,7 @@ impl<K: Into<String>, V: Into<Value>> FromIterator<(K, V)> for Value {
}
impl From<()> for Value {
- /// Convert `()` to `Value`
+ /// Convert `()` to `Value::Null`.
///
/// # Examples
///
diff --git a/src/value/index.rs b/src/value/index.rs
index c74042b..891ca8e 100644
--- a/src/value/index.rs
+++ b/src/value/index.rs
@@ -116,7 +116,7 @@ impl Index for String {
}
}
-impl<'a, T> Index for &'a T
+impl<T> Index for &T
where
T: ?Sized + Index,
{
diff --git a/src/value/mod.rs b/src/value/mod.rs
index 470b6b2..b3f51ea 100644
--- a/src/value/mod.rs
+++ b/src/value/mod.rs
@@ -106,6 +106,7 @@ 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.
@@ -182,11 +183,11 @@ impl Debug for Value {
Value::Number(number) => Debug::fmt(number, formatter),
Value::String(string) => write!(formatter, "String({:?})", string),
Value::Array(vec) => {
- formatter.write_str("Array ")?;
+ tri!(formatter.write_str("Array "));
Debug::fmt(vec, formatter)
}
Value::Object(map) => {
- formatter.write_str("Object ")?;
+ tri!(formatter.write_str("Object "));
Debug::fmt(map, formatter)
}
}
@@ -514,6 +515,28 @@ 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`.
///
@@ -889,7 +912,6 @@ mod ser;
/// ```
/// use serde::Serialize;
/// use serde_json::json;
-///
/// use std::error::Error;
///
/// #[derive(Serialize)]
@@ -898,7 +920,7 @@ mod ser;
/// location: String,
/// }
///
-/// fn compare_json_values() -> Result<(), Box<Error>> {
+/// fn compare_json_values() -> Result<(), Box<dyn 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 b4ef84c..46c1dbc 100644
--- a/src/value/partial_eq.rs
+++ b/src/value/partial_eq.rs
@@ -9,6 +9,13 @@ 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)
}
@@ -27,7 +34,7 @@ impl PartialEq<str> for Value {
}
}
-impl<'a> PartialEq<&'a str> for Value {
+impl PartialEq<&str> for Value {
fn eq(&self, other: &&str) -> bool {
eq_str(self, *other)
}
@@ -39,7 +46,7 @@ impl PartialEq<Value> for str {
}
}
-impl<'a> PartialEq<Value> for &'a str {
+impl PartialEq<Value> for &str {
fn eq(&self, other: &Value) -> bool {
eq_str(other, *self)
}
@@ -90,6 +97,7 @@ macro_rules! partialeq_numeric {
partialeq_numeric! {
eq_i64[i8 i16 i32 i64 isize]
eq_u64[u8 u16 u32 u64 usize]
- eq_f64[f32 f64]
+ eq_f32[f32]
+ eq_f64[f64]
eq_bool[bool]
}
diff --git a/src/value/ser.rs b/src/value/ser.rs
index a29814e..835fa90 100644
--- a/src/value/ser.rs
+++ b/src/value/ser.rs
@@ -1,12 +1,9 @@
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};
@@ -149,13 +146,13 @@ impl serde::Serializer for Serializer {
}
#[inline]
- fn serialize_f32(self, value: f32) -> Result<Value> {
- self.serialize_f64(value as f64)
+ fn serialize_f32(self, float: f32) -> Result<Value> {
+ Ok(Value::from(float))
}
#[inline]
- fn serialize_f64(self, value: f64) -> Result<Value> {
- Ok(Number::from_f64(value).map_or(Value::Null, Value::Number))
+ fn serialize_f64(self, float: f64) -> Result<Value> {
+ Ok(Value::from(float))
}
#[inline]
@@ -452,6 +449,10 @@ 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;
@@ -482,8 +483,8 @@ impl serde::Serializer for MapKeySerializer {
value.serialize(self)
}
- fn serialize_bool(self, _value: bool) -> Result<String> {
- Err(key_must_be_a_string())
+ fn serialize_bool(self, value: bool) -> Result<String> {
+ Ok(value.to_string())
}
fn serialize_i8(self, value: i8) -> Result<String> {
@@ -518,12 +519,20 @@ impl serde::Serializer for MapKeySerializer {
Ok(value.to_string())
}
- fn serialize_f32(self, _value: f32) -> Result<String> {
- Err(key_must_be_a_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_f64(self, _value: f64) -> 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())
+ }
}
#[inline]
@@ -641,7 +650,7 @@ impl serde::ser::SerializeStruct for SerializeMap {
#[cfg(feature = "arbitrary_precision")]
SerializeMap::Number { out_value } => {
if key == crate::number::TOKEN {
- *out_value = Some(value.serialize(NumberValueEmitter)?);
+ *out_value = Some(tri!(value.serialize(NumberValueEmitter)));
Ok(())
} else {
Err(invalid_number())
@@ -650,7 +659,7 @@ impl serde::ser::SerializeStruct for SerializeMap {
#[cfg(feature = "raw_value")]
SerializeMap::RawValue { out_value } => {
if key == crate::raw::TOKEN {
- *out_value = Some(value.serialize(RawValueEmitter)?);
+ *out_value = Some(tri!(value.serialize(RawValueEmitter)));
Ok(())
} else {
Err(invalid_raw_value())