mirror of
https://github.com/serde-rs/json.git
synced 2025-10-02 15:26:00 +00:00
Arbitrary-precision numerics support (#416)
Added support for arbitrary-precision numerics, in a similar way that the toml crate does for date-times (using an internal special struct).
This commit is contained in:
parent
21d623d7bb
commit
31bba4b5a1
@ -37,3 +37,10 @@ default = []
|
||||
# This allows data to be read into a Value and written back to a JSON string
|
||||
# while preserving the order of map keys in the input.
|
||||
preserve_order = ["linked-hash-map"]
|
||||
|
||||
# Use `String` to represent numbers internally, thus allowing the serialization
|
||||
# and deserialization of numbers of arbitrary size/precision, instead of just
|
||||
# the primitive integers and floats.
|
||||
# This feature does not provide provide the ability to do arithmetic on
|
||||
# arbitrary-precision numbers; this is left to the discretion of the consumer.
|
||||
arbitrary_precision = []
|
||||
|
282
src/de.rs
282
src/de.rs
@ -20,6 +20,9 @@ use read::{self, Reference};
|
||||
|
||||
pub use read::{Read, IoRead, SliceRead, StrRead};
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
use number::NumberDeserializer;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// A structure that deserializes JSON into Rust values.
|
||||
@ -80,10 +83,14 @@ macro_rules! overflow {
|
||||
}
|
||||
}
|
||||
|
||||
enum Number {
|
||||
// Not public API. Should be pub(crate).
|
||||
#[doc(hidden)]
|
||||
pub enum Number {
|
||||
F64(f64),
|
||||
U64(u64),
|
||||
I64(i64),
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
String(String),
|
||||
}
|
||||
|
||||
impl Number {
|
||||
@ -95,6 +102,12 @@ impl Number {
|
||||
Number::F64(x) => visitor.visit_f64(x),
|
||||
Number::U64(x) => visitor.visit_u64(x),
|
||||
Number::I64(x) => visitor.visit_i64(x),
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
Number::String(x) => {
|
||||
visitor.visit_map(NumberDeserializer {
|
||||
number: x.into(),
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,6 +116,8 @@ impl Number {
|
||||
Number::F64(x) => de::Error::invalid_type(Unexpected::Float(x), exp),
|
||||
Number::U64(x) => de::Error::invalid_type(Unexpected::Unsigned(x), exp),
|
||||
Number::I64(x) => de::Error::invalid_type(Unexpected::Signed(x), exp),
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
Number::String(_) => de::Error::invalid_type(Unexpected::Other("number"), exp),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -209,13 +224,13 @@ impl<'de, R: Read<'de>> Deserializer<R> {
|
||||
}
|
||||
b'-' => {
|
||||
self.eat_char();
|
||||
match self.parse_integer(false) {
|
||||
match self.parse_any_number(false) {
|
||||
Ok(n) => n.invalid_type(exp),
|
||||
Err(err) => return err,
|
||||
}
|
||||
}
|
||||
b'0'...b'9' => {
|
||||
match self.parse_integer(true) {
|
||||
match self.parse_any_number(true) {
|
||||
Ok(n) => n.invalid_type(exp),
|
||||
Err(err) => return err,
|
||||
}
|
||||
@ -240,7 +255,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
|
||||
self.fix_position(err)
|
||||
}
|
||||
|
||||
fn deserialize_number<V>(&mut self, visitor: V) -> Result<V::Value>
|
||||
fn deserialize_prim_number<V>(&mut self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
@ -476,6 +491,165 @@ impl<'de, R: Read<'de>> Deserializer<R> {
|
||||
Ok(if positive { 0.0 } else { -0.0 })
|
||||
}
|
||||
|
||||
// Not public API. Should be pub(crate).
|
||||
#[doc(hidden)]
|
||||
pub fn parse_any_signed_number(&mut self) -> Result<Number> {
|
||||
let peek = match try!(self.peek()) {
|
||||
Some(b) => b,
|
||||
None => {
|
||||
return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
|
||||
}
|
||||
};
|
||||
|
||||
let value = match peek {
|
||||
b'-' => {
|
||||
self.eat_char();
|
||||
self.parse_any_number(false)
|
||||
}
|
||||
b'0'...b'9' => {
|
||||
self.parse_any_number(true)
|
||||
}
|
||||
_ => Err(self.peek_error(ErrorCode::InvalidNumber)),
|
||||
};
|
||||
|
||||
let value = match try!(self.peek()) {
|
||||
Some(_) => Err(self.peek_error(ErrorCode::InvalidNumber)),
|
||||
None => value,
|
||||
};
|
||||
|
||||
match value {
|
||||
Ok(value) => Ok(value),
|
||||
// The de::Error impl creates errors with unknown line and column.
|
||||
// Fill in the position here by looking at the current index in the
|
||||
// input. There is no way to tell whether this should call `error`
|
||||
// or `peek_error` so pick the one that seems correct more often.
|
||||
// Worst case, the position is off by one character.
|
||||
Err(err) => Err(self.fix_position(err)),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
fn parse_any_number(&mut self, pos: bool) -> Result<Number>
|
||||
{
|
||||
self.parse_integer(pos)
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn parse_any_number(&mut self, pos: bool) -> Result<Number>
|
||||
{
|
||||
let mut buf = String::with_capacity(16);
|
||||
if !pos {
|
||||
buf.push('-');
|
||||
}
|
||||
self.scan_integer(&mut buf)?;
|
||||
Ok(Number::String(buf))
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn scan_or_null(&mut self, buf: &mut String) -> Result<u8> {
|
||||
match try!(self.next_char()) {
|
||||
Some(b) => {
|
||||
buf.push(b as char);
|
||||
Ok(b)
|
||||
}
|
||||
None => {
|
||||
Ok(b'\x00')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn scan_integer(&mut self, buf: &mut String) -> Result<()> {
|
||||
match try!(self.scan_or_null(buf)) {
|
||||
b'0' => {
|
||||
// There can be only one leading '0'.
|
||||
match try!(self.peek_or_null()) {
|
||||
b'0'...b'9' => {
|
||||
Err(self.peek_error(ErrorCode::InvalidNumber))
|
||||
}
|
||||
_ => self.scan_number(buf),
|
||||
}
|
||||
}
|
||||
b'1'...b'9' => {
|
||||
loop {
|
||||
match try!(self.peek_or_null()) {
|
||||
c @ b'0'...b'9' => {
|
||||
self.eat_char();
|
||||
buf.push(c as char);
|
||||
}
|
||||
_ => {
|
||||
return self.scan_number(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => Err(self.error(ErrorCode::InvalidNumber)),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn scan_number(&mut self, buf: &mut String) -> Result<()> {
|
||||
match try!(self.peek_or_null()) {
|
||||
b'.' => self.scan_decimal(buf),
|
||||
b'e' | b'E' => self.scan_exponent(buf),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn scan_decimal(&mut self, buf: &mut String) -> Result<()> {
|
||||
self.eat_char();
|
||||
buf.push('.');
|
||||
|
||||
let mut at_least_one_digit = false;
|
||||
while let c @ b'0'...b'9' = try!(self.peek_or_null()) {
|
||||
self.eat_char();
|
||||
buf.push(c as char);
|
||||
at_least_one_digit = true;
|
||||
}
|
||||
|
||||
if !at_least_one_digit {
|
||||
return Err(self.peek_error(ErrorCode::InvalidNumber));
|
||||
}
|
||||
|
||||
match try!(self.peek_or_null()) {
|
||||
b'e' | b'E' => self.scan_exponent(buf),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn scan_exponent(&mut self, buf: &mut String) -> Result<()> {
|
||||
self.eat_char();
|
||||
buf.push('e');
|
||||
|
||||
match try!(self.peek_or_null()) {
|
||||
b'+' => {
|
||||
self.eat_char();
|
||||
}
|
||||
b'-' => {
|
||||
self.eat_char();
|
||||
buf.push('-');
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Make sure a digit follows the exponent place.
|
||||
match try!(self.scan_or_null(buf)) {
|
||||
b'0'...b'9' => {}
|
||||
_ => {
|
||||
return Err(self.error(ErrorCode::InvalidNumber));
|
||||
}
|
||||
}
|
||||
|
||||
while let c @ b'0'...b'9' = try!(self.peek_or_null()) {
|
||||
self.eat_char();
|
||||
buf.push(c as char);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn f64_from_parts(
|
||||
&mut self,
|
||||
positive: bool,
|
||||
@ -796,6 +970,17 @@ static POW10: [f64; 309] =
|
||||
1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299,
|
||||
1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308];
|
||||
|
||||
macro_rules! deserialize_prim_number {
|
||||
($method:ident) => {
|
||||
fn $method<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
self.deserialize_prim_number(visitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer<R> {
|
||||
type Error = Error;
|
||||
|
||||
@ -829,9 +1014,11 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer<R> {
|
||||
}
|
||||
b'-' => {
|
||||
self.eat_char();
|
||||
try!(self.parse_integer(false)).visit(visitor)
|
||||
try!(self.parse_any_number(false)).visit(visitor)
|
||||
}
|
||||
b'0'...b'9' => {
|
||||
try!(self.parse_any_number(true)).visit(visitor)
|
||||
}
|
||||
b'0'...b'9' => try!(self.parse_integer(true)).visit(visitor),
|
||||
b'"' => {
|
||||
self.eat_char();
|
||||
self.str_buf.clear();
|
||||
@ -917,75 +1104,16 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer<R> {
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
self.deserialize_number(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
self.deserialize_number(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
self.deserialize_number(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
self.deserialize_number(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
self.deserialize_number(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
self.deserialize_number(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
self.deserialize_number(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
self.deserialize_number(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
self.deserialize_number(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
self.deserialize_number(visitor)
|
||||
}
|
||||
deserialize_prim_number!(deserialize_i8);
|
||||
deserialize_prim_number!(deserialize_i16);
|
||||
deserialize_prim_number!(deserialize_i32);
|
||||
deserialize_prim_number!(deserialize_i64);
|
||||
deserialize_prim_number!(deserialize_u8);
|
||||
deserialize_prim_number!(deserialize_u16);
|
||||
deserialize_prim_number!(deserialize_u32);
|
||||
deserialize_prim_number!(deserialize_u64);
|
||||
deserialize_prim_number!(deserialize_f32);
|
||||
deserialize_prim_number!(deserialize_f64);
|
||||
|
||||
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
@ -1646,8 +1774,8 @@ struct MapKey<'a, R: 'a> {
|
||||
}
|
||||
|
||||
macro_rules! deserialize_integer_key {
|
||||
($deserialize:ident => $visit:ident) => {
|
||||
fn $deserialize<V>(self, visitor: V) -> Result<V::Value>
|
||||
($method:ident => $visit:ident) => {
|
||||
fn $method<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
|
459
src/number.rs
459
src/number.rs
@ -7,11 +7,34 @@
|
||||
// except according to those terms.
|
||||
|
||||
use error::Error;
|
||||
use num_traits::NumCast;
|
||||
use serde::de::{self, Visitor, Unexpected};
|
||||
use serde::{Serialize, Serializer, Deserialize, Deserializer};
|
||||
use std::fmt::{self, Debug, Display};
|
||||
use std::i64;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
use num_traits::{NumCast};
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
use dtoa;
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
use itoa;
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
use serde::de::{IntoDeserializer, MapAccess};
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
use error::{ErrorCode};
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
/// Not public API. Should be pub(crate).
|
||||
#[doc(hidden)]
|
||||
pub const SERDE_STRUCT_FIELD_NAME: &'static str = "$__serde_private_number";
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
/// Not public API. Should be pub(crate).
|
||||
#[doc(hidden)]
|
||||
pub const SERDE_STRUCT_NAME: &'static str = "$__serde_private_Number";
|
||||
|
||||
/// Represents a JSON number, whether integer or floating point.
|
||||
#[derive(Clone, PartialEq)]
|
||||
@ -19,6 +42,7 @@ pub struct Number {
|
||||
n: N,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
enum N {
|
||||
PosInt(u64),
|
||||
@ -28,6 +52,9 @@ enum N {
|
||||
Float(f64),
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
type N = String;
|
||||
|
||||
impl Number {
|
||||
/// Returns true if the `Number` is an integer between `i64::MIN` and
|
||||
/// `i64::MAX`.
|
||||
@ -56,11 +83,14 @@ impl Number {
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_i64(&self) -> bool {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
match self.n {
|
||||
N::PosInt(v) => v <= i64::max_value() as u64,
|
||||
N::NegInt(_) => true,
|
||||
N::Float(_) => false,
|
||||
}
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
self.as_i64().is_some()
|
||||
}
|
||||
|
||||
/// Returns true if the `Number` is an integer between zero and `u64::MAX`.
|
||||
@ -86,10 +116,13 @@ impl Number {
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_u64(&self) -> bool {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
match self.n {
|
||||
N::PosInt(_) => true,
|
||||
N::NegInt(_) | N::Float(_) => false,
|
||||
}
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
self.as_u64().is_some()
|
||||
}
|
||||
|
||||
/// Returns true if the `Number` can be represented by f64.
|
||||
@ -116,10 +149,21 @@ impl Number {
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_f64(&self) -> bool {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
match self.n {
|
||||
N::Float(_) => true,
|
||||
N::PosInt(_) | N::NegInt(_) => false,
|
||||
}
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// If the `Number` is an integer, represent it as i64 if possible. Returns
|
||||
@ -142,11 +186,14 @@ impl Number {
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn as_i64(&self) -> Option<i64> {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
match self.n {
|
||||
N::PosInt(n) => NumCast::from(n),
|
||||
N::NegInt(n) => Some(n),
|
||||
N::Float(_) => None,
|
||||
}
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
self.n.parse().ok()
|
||||
}
|
||||
|
||||
/// If the `Number` is an integer, represent it as u64 if possible. Returns
|
||||
@ -166,11 +213,14 @@ impl Number {
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn as_u64(&self) -> Option<u64> {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
match self.n {
|
||||
N::PosInt(n) => Some(n),
|
||||
N::NegInt(n) => NumCast::from(n),
|
||||
N::Float(_) => None,
|
||||
}
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
self.n.parse().ok()
|
||||
}
|
||||
|
||||
/// Represents the number as f64 if possible. Returns None otherwise.
|
||||
@ -189,11 +239,14 @@ impl Number {
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn as_f64(&self) -> Option<f64> {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
match self.n {
|
||||
N::PosInt(n) => NumCast::from(n),
|
||||
N::NegInt(n) => NumCast::from(n),
|
||||
N::Float(n) => Some(n),
|
||||
}
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
self.n.parse().ok()
|
||||
}
|
||||
|
||||
/// Converts a finite `f64` to a `Number`. Infinite or NaN values are not JSON
|
||||
@ -211,24 +264,49 @@ impl Number {
|
||||
#[inline]
|
||||
pub fn from_f64(f: f64) -> Option<Number> {
|
||||
if f.is_finite() {
|
||||
Some(Number { n: N::Float(f) })
|
||||
let n = {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
{ N::Float(f) }
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
{
|
||||
let mut buf = Vec::new();
|
||||
dtoa::write(&mut buf, f).unwrap();
|
||||
String::from_utf8(buf).unwrap()
|
||||
}
|
||||
};
|
||||
Some(Number { n: n })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
/// Not public API. Only tests use this.
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
pub fn from_string_unchecked(n: String) -> Self {
|
||||
Number { n: n }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Number {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.n {
|
||||
N::PosInt(i) => Display::fmt(&i, formatter),
|
||||
N::PosInt(u) => Display::fmt(&u, formatter),
|
||||
N::NegInt(i) => Display::fmt(&i, formatter),
|
||||
N::Float(f) => Display::fmt(&f, formatter),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.n, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Number {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut debug = formatter.debug_tuple("Number");
|
||||
match self.n {
|
||||
@ -244,20 +322,39 @@ impl Debug for Number {
|
||||
}
|
||||
debug.finish()
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "Number({})", &self.n)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Number {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match self.n {
|
||||
N::PosInt(i) => serializer.serialize_u64(i),
|
||||
N::PosInt(u) => serializer.serialize_u64(u),
|
||||
N::NegInt(i) => serializer.serialize_i64(i),
|
||||
N::Float(f) => serializer.serialize_f64(f),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
use serde::ser::SerializeStruct;
|
||||
|
||||
let mut s = serializer.serialize_struct(SERDE_STRUCT_NAME, 1)?;
|
||||
s.serialize_field(SERDE_STRUCT_FIELD_NAME, &self.n)?;
|
||||
s.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Number {
|
||||
@ -272,7 +369,7 @@ impl<'de> Deserialize<'de> for Number {
|
||||
type Value = Number;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a number")
|
||||
formatter.write_str("a JSON number")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -292,90 +389,355 @@ impl<'de> Deserialize<'de> for Number {
|
||||
{
|
||||
Number::from_f64(value).ok_or_else(|| de::Error::custom("not a JSON number"))
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
#[inline]
|
||||
fn visit_map<V>(self, mut visitor: V) -> Result<Number, V::Error>
|
||||
where
|
||||
V: de::MapAccess<'de>
|
||||
{
|
||||
let value = visitor.next_key::<NumberKey>()?;
|
||||
if value.is_none() {
|
||||
return Err(de::Error::invalid_type(Unexpected::Map, &self));
|
||||
}
|
||||
let v: NumberFromString = visitor.next_value()?;
|
||||
Ok(v.value)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(NumberVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
struct NumberKey;
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
impl<'de> de::Deserialize<'de> for NumberKey {
|
||||
fn deserialize<D>(deserializer: D) -> Result<NumberKey, D::Error>
|
||||
where
|
||||
D: de::Deserializer<'de>
|
||||
{
|
||||
struct FieldVisitor;
|
||||
|
||||
impl<'de> de::Visitor<'de> for FieldVisitor {
|
||||
type Value = ();
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a valid number field")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> Result<(), E>
|
||||
where E: de::Error
|
||||
{
|
||||
if s == SERDE_STRUCT_FIELD_NAME {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(de::Error::custom("expected field with custom name"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_identifier(FieldVisitor)?;
|
||||
Ok(NumberKey)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
pub struct NumberFromString {
|
||||
pub value: Number,
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
impl<'de> de::Deserialize<'de> for NumberFromString {
|
||||
fn deserialize<D>(deserializer: D) -> Result<NumberFromString, D::Error>
|
||||
where
|
||||
D: de::Deserializer<'de>
|
||||
{
|
||||
struct Visitor;
|
||||
|
||||
impl<'de> de::Visitor<'de> for Visitor {
|
||||
type Value = NumberFromString;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("string containing a number")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> Result<NumberFromString, E>
|
||||
where E: de::Error,
|
||||
{
|
||||
let n = try!(s.parse().map_err(de::Error::custom));
|
||||
Ok(NumberFromString { value: n })
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_str(Visitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn invalid_number() -> Error {
|
||||
Error::syntax(ErrorCode::InvalidNumber, 0, 0)
|
||||
}
|
||||
|
||||
macro_rules! deserialize_any {
|
||||
(@expand [$($num_string:tt)*]) => {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
#[inline]
|
||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.n {
|
||||
N::PosInt(u) => visitor.visit_u64(u),
|
||||
N::NegInt(i) => visitor.visit_i64(i),
|
||||
N::Float(f) => visitor.visit_f64(f),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
#[inline]
|
||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where V: Visitor<'de>
|
||||
{
|
||||
if let Some(u) = self.as_u64() {
|
||||
return visitor.visit_u64(u);
|
||||
} else if let Some(i) = self.as_i64() {
|
||||
return visitor.visit_i64(i);
|
||||
} else if let Some(f) = self.as_f64() {
|
||||
if f.to_string() == self.n {
|
||||
return visitor.visit_f64(f);
|
||||
}
|
||||
}
|
||||
|
||||
visitor.visit_map(NumberDeserializer {
|
||||
number: Some(self.$($num_string)*),
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
(owned) => {
|
||||
deserialize_any!(@expand [n]);
|
||||
};
|
||||
|
||||
(ref) => {
|
||||
deserialize_any!(@expand [n.clone()]);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! deserialize_number {
|
||||
($deserialize:ident => $visit:ident) => {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
fn $deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.deserialize_any(visitor)
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn $deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.$visit(self.n.parse().map_err(|_| invalid_number())?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserializer<'de> for Number {
|
||||
type Error = Error;
|
||||
|
||||
#[inline]
|
||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.n {
|
||||
N::PosInt(i) => visitor.visit_u64(i),
|
||||
N::NegInt(i) => visitor.visit_i64(i),
|
||||
N::Float(f) => visitor.visit_f64(f),
|
||||
}
|
||||
}
|
||||
deserialize_any!(owned);
|
||||
|
||||
deserialize_number!(deserialize_i8 => visit_i8);
|
||||
deserialize_number!(deserialize_i16 => visit_i16);
|
||||
deserialize_number!(deserialize_i32 => visit_i32);
|
||||
deserialize_number!(deserialize_i64 => visit_i64);
|
||||
deserialize_number!(deserialize_u8 => visit_u8);
|
||||
deserialize_number!(deserialize_u16 => visit_u16);
|
||||
deserialize_number!(deserialize_u32 => visit_u32);
|
||||
deserialize_number!(deserialize_u64 => visit_u64);
|
||||
deserialize_number!(deserialize_f32 => visit_f32);
|
||||
deserialize_number!(deserialize_f64 => visit_f64);
|
||||
|
||||
forward_to_deserialize_any! {
|
||||
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
|
||||
byte_buf option unit unit_struct newtype_struct seq tuple
|
||||
tuple_struct map struct enum identifier ignored_any
|
||||
bool char str string bytes byte_buf option unit unit_struct
|
||||
newtype_struct seq tuple tuple_struct map struct enum identifier
|
||||
ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, 'a> Deserializer<'de> for &'a Number {
|
||||
type Error = Error;
|
||||
|
||||
#[inline]
|
||||
deserialize_any!(ref);
|
||||
|
||||
deserialize_number!(deserialize_i8 => visit_i8);
|
||||
deserialize_number!(deserialize_i16 => visit_i16);
|
||||
deserialize_number!(deserialize_i32 => visit_i32);
|
||||
deserialize_number!(deserialize_i64 => visit_i64);
|
||||
deserialize_number!(deserialize_u8 => visit_u8);
|
||||
deserialize_number!(deserialize_u16 => visit_u16);
|
||||
deserialize_number!(deserialize_u32 => visit_u32);
|
||||
deserialize_number!(deserialize_u64 => visit_u64);
|
||||
deserialize_number!(deserialize_f32 => visit_f32);
|
||||
deserialize_number!(deserialize_f64 => visit_f64);
|
||||
|
||||
forward_to_deserialize_any! {
|
||||
bool char str string bytes byte_buf option unit unit_struct
|
||||
newtype_struct seq tuple tuple_struct map struct enum identifier
|
||||
ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
// Not public API. Should be pub(crate).
|
||||
#[doc(hidden)]
|
||||
pub struct NumberDeserializer {
|
||||
pub number: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
impl<'de> MapAccess<'de> for NumberDeserializer {
|
||||
type Error = Error;
|
||||
|
||||
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
|
||||
where
|
||||
K: de::DeserializeSeed<'de>,
|
||||
{
|
||||
if self.number.is_none() {
|
||||
return Ok(None)
|
||||
}
|
||||
seed.deserialize(NumberFieldDeserializer).map(Some)
|
||||
}
|
||||
|
||||
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: de::DeserializeSeed<'de>,
|
||||
{
|
||||
seed.deserialize(self.number.take().unwrap().into_deserializer())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
struct NumberFieldDeserializer;
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
impl<'de> Deserializer<'de> for NumberFieldDeserializer {
|
||||
type Error = Error;
|
||||
|
||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
match self.n {
|
||||
N::PosInt(i) => visitor.visit_u64(i),
|
||||
N::NegInt(i) => visitor.visit_i64(i),
|
||||
N::Float(f) => visitor.visit_f64(f),
|
||||
}
|
||||
visitor.visit_borrowed_str(SERDE_STRUCT_FIELD_NAME)
|
||||
}
|
||||
|
||||
forward_to_deserialize_any! {
|
||||
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
|
||||
byte_buf option unit unit_struct newtype_struct seq tuple
|
||||
tuple_struct map struct enum identifier ignored_any
|
||||
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
|
||||
bytes byte_buf map struct option unit newtype_struct
|
||||
ignored_any unit_struct tuple_struct tuple enum identifier
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! from_signed {
|
||||
($($signed_ty:ident)*) => {
|
||||
impl FromStr for Number {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
super::de::Deserializer::from_str(s).parse_any_signed_number().map(|n| n.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<super::de::Number> for Number {
|
||||
fn from(value: super::de::Number) -> Self {
|
||||
let n = match value {
|
||||
super::de::Number::F64(f) => {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
{ N::Float(f) }
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
{ f.to_string() }
|
||||
},
|
||||
super::de::Number::U64(u) => {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
{ N::PosInt(u) }
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
{ u.to_string() }
|
||||
},
|
||||
super::de::Number::I64(i) => {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
{ N::NegInt(i) }
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
{ i.to_string() }
|
||||
},
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
super::de::Number::String(s) => s,
|
||||
};
|
||||
Number { n: n }
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_from_unsigned {
|
||||
(
|
||||
$($ty:ty),*
|
||||
) => {
|
||||
$(
|
||||
impl From<$signed_ty> for Number {
|
||||
impl From<$ty> for Number {
|
||||
#[inline]
|
||||
fn from(i: $signed_ty) -> Self {
|
||||
if i < 0 {
|
||||
Number { n: N::NegInt(i as i64) }
|
||||
} else {
|
||||
Number { n: N::PosInt(i as u64) }
|
||||
}
|
||||
fn from(u: $ty) -> Self {
|
||||
let n = {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
{ N::PosInt(u as u64) }
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
{
|
||||
let mut buf = Vec::new();
|
||||
itoa::write(&mut buf, u).unwrap();
|
||||
String::from_utf8(buf).unwrap()
|
||||
}
|
||||
};
|
||||
Number { n: n }
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! from_unsigned {
|
||||
($($unsigned_ty:ident)*) => {
|
||||
macro_rules! impl_from_signed {
|
||||
(
|
||||
$($ty:ty),*
|
||||
) => {
|
||||
$(
|
||||
impl From<$unsigned_ty> for Number {
|
||||
impl From<$ty> for Number {
|
||||
#[inline]
|
||||
fn from(u: $unsigned_ty) -> Self {
|
||||
Number { n: N::PosInt(u as u64) }
|
||||
fn from(i: $ty) -> Self {
|
||||
let n = {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
{
|
||||
if i < 0 {
|
||||
N::NegInt(i as i64)
|
||||
} else {
|
||||
N::PosInt(i as u64)
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
{
|
||||
let mut buf = Vec::new();
|
||||
itoa::write(&mut buf, i).unwrap();
|
||||
String::from_utf8(buf).unwrap()
|
||||
}
|
||||
};
|
||||
Number { n: n }
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
from_signed!(i8 i16 i32 i64 isize);
|
||||
from_unsigned!(u8 u16 u32 u64 usize);
|
||||
impl_from_unsigned!(u8, u16, u32, u64, usize);
|
||||
impl_from_signed!(i8, i16, i32, i64, isize);
|
||||
|
||||
impl Number {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
// Not public API. Should be pub(crate).
|
||||
#[doc(hidden)]
|
||||
pub fn unexpected(&self) -> Unexpected {
|
||||
@ -385,4 +747,11 @@ impl Number {
|
||||
N::Float(f) => Unexpected::Float(f),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
// Not public API. Should be pub(crate).
|
||||
#[doc(hidden)]
|
||||
pub fn unexpected(&self) -> Unexpected {
|
||||
Unexpected::Other("number")
|
||||
}
|
||||
}
|
||||
|
503
src/ser.rs
503
src/ser.rs
@ -19,6 +19,12 @@ use super::error::{Error, ErrorCode, Result};
|
||||
use itoa;
|
||||
use dtoa;
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
use serde::{Serialize};
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
use number::{SERDE_STRUCT_NAME, SERDE_STRUCT_FIELD_NAME};
|
||||
|
||||
/// A structure for serializing Rust values into JSON.
|
||||
pub struct Serializer<W, F = CompactFormatter> {
|
||||
writer: W,
|
||||
@ -347,10 +353,10 @@ where
|
||||
.map_err(Error::io)
|
||||
);
|
||||
Ok(
|
||||
Compound {
|
||||
Compound::Map {
|
||||
ser: self,
|
||||
state: State::Empty,
|
||||
},
|
||||
}
|
||||
)
|
||||
} else {
|
||||
try!(
|
||||
@ -359,10 +365,10 @@ where
|
||||
.map_err(Error::io)
|
||||
);
|
||||
Ok(
|
||||
Compound {
|
||||
Compound::Map {
|
||||
ser: self,
|
||||
state: State::First,
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -427,10 +433,10 @@ where
|
||||
.map_err(Error::io)
|
||||
);
|
||||
Ok(
|
||||
Compound {
|
||||
Compound::Map {
|
||||
ser: self,
|
||||
state: State::Empty,
|
||||
},
|
||||
}
|
||||
)
|
||||
} else {
|
||||
try!(
|
||||
@ -439,19 +445,30 @@ where
|
||||
.map_err(Error::io)
|
||||
);
|
||||
Ok(
|
||||
Compound {
|
||||
Compound::Map {
|
||||
ser: self,
|
||||
state: State::First,
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
#[inline]
|
||||
fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
|
||||
self.serialize_map(Some(len))
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
#[inline]
|
||||
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
|
||||
if name == SERDE_STRUCT_NAME {
|
||||
Ok(Compound::Number { ser: self })
|
||||
} else {
|
||||
self.serialize_map(Some(len))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_struct_variant(
|
||||
self,
|
||||
@ -540,18 +557,26 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Eq, PartialEq)]
|
||||
/// Not public API. Should be pub(crate).
|
||||
#[doc(hidden)]
|
||||
pub enum State {
|
||||
Empty,
|
||||
First,
|
||||
Rest,
|
||||
}
|
||||
|
||||
/// Not public API. Should be pub(crate).
|
||||
#[doc(hidden)]
|
||||
pub struct Compound<'a, W: 'a, F: 'a> {
|
||||
ser: &'a mut Serializer<W, F>,
|
||||
state: State,
|
||||
pub enum Compound<'a, W: 'a, F: 'a> {
|
||||
Map {
|
||||
ser: &'a mut Serializer<W, F>,
|
||||
state: State,
|
||||
},
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
Number {
|
||||
ser: &'a mut Serializer<W, F>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a, W, F> ser::SerializeSeq for Compound<'a, W, F>
|
||||
@ -567,37 +592,46 @@ where
|
||||
where
|
||||
T: ser::Serialize,
|
||||
{
|
||||
try!(
|
||||
self.ser
|
||||
.formatter
|
||||
.begin_array_value(&mut self.ser.writer, self.state == State::First)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
self.state = State::Rest;
|
||||
try!(value.serialize(&mut *self.ser));
|
||||
try!(
|
||||
self.ser
|
||||
.formatter
|
||||
.end_array_value(&mut self.ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
Ok(())
|
||||
match *self {
|
||||
Compound::Map { ref mut ser, ref mut state } => {
|
||||
try!(
|
||||
ser.formatter
|
||||
.begin_array_value(&mut ser.writer, *state == State::First)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
*state = State::Rest;
|
||||
try!(value.serialize(&mut **ser));
|
||||
try!(
|
||||
ser.formatter
|
||||
.end_array_value(&mut ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
Ok(())
|
||||
},
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
Compound::Number { .. } => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn end(self) -> Result<()> {
|
||||
match self.state {
|
||||
State::Empty => {}
|
||||
_ => {
|
||||
try!(
|
||||
self.ser
|
||||
.formatter
|
||||
.end_array(&mut self.ser.writer)
|
||||
.map_err(Error::io)
|
||||
)
|
||||
}
|
||||
match self {
|
||||
Compound::Map { ser, state } => {
|
||||
match state {
|
||||
State::Empty => {}
|
||||
_ => {
|
||||
try!(
|
||||
ser.formatter
|
||||
.end_array(&mut ser.writer)
|
||||
.map_err(Error::io)
|
||||
)
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
Compound::Number { .. } => unreachable!(),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -663,30 +697,33 @@ where
|
||||
|
||||
#[inline]
|
||||
fn end(self) -> Result<()> {
|
||||
match self.state {
|
||||
State::Empty => {}
|
||||
_ => {
|
||||
match self {
|
||||
Compound::Map { ser, state } => {
|
||||
match state {
|
||||
State::Empty => {}
|
||||
_ => {
|
||||
try!(
|
||||
ser.formatter
|
||||
.end_array(&mut ser.writer)
|
||||
.map_err(Error::io)
|
||||
)
|
||||
}
|
||||
}
|
||||
try!(
|
||||
self.ser
|
||||
.formatter
|
||||
.end_array(&mut self.ser.writer)
|
||||
.map_err(Error::io)
|
||||
)
|
||||
}
|
||||
ser.formatter
|
||||
.end_object_value(&mut ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
try!(
|
||||
ser.formatter
|
||||
.end_object(&mut ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
Ok(())
|
||||
},
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
Compound::Number { .. } => unreachable!(),
|
||||
}
|
||||
try!(
|
||||
self.ser
|
||||
.formatter
|
||||
.end_object_value(&mut self.ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
try!(
|
||||
self.ser
|
||||
.formatter
|
||||
.end_object(&mut self.ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -703,23 +740,27 @@ where
|
||||
where
|
||||
T: ser::Serialize,
|
||||
{
|
||||
try!(
|
||||
self.ser
|
||||
.formatter
|
||||
.begin_object_key(&mut self.ser.writer, self.state == State::First)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
self.state = State::Rest;
|
||||
match *self {
|
||||
Compound::Map { ref mut ser, ref mut state } => {
|
||||
try!(
|
||||
ser.formatter
|
||||
.begin_object_key(&mut ser.writer, *state == State::First)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
*state = State::Rest;
|
||||
|
||||
try!(key.serialize(MapKeySerializer { ser: self.ser }));
|
||||
try!(key.serialize(MapKeySerializer { ser: *ser }));
|
||||
|
||||
try!(
|
||||
self.ser
|
||||
.formatter
|
||||
.end_object_key(&mut self.ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
Ok(())
|
||||
try!(
|
||||
ser.formatter
|
||||
.end_object_key(&mut ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
Ok(())
|
||||
},
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
Compound::Number { .. } => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -727,36 +768,45 @@ where
|
||||
where
|
||||
T: ser::Serialize,
|
||||
{
|
||||
try!(
|
||||
self.ser
|
||||
.formatter
|
||||
.begin_object_value(&mut self.ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
try!(value.serialize(&mut *self.ser));
|
||||
try!(
|
||||
self.ser
|
||||
.formatter
|
||||
.end_object_value(&mut self.ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
Ok(())
|
||||
match *self {
|
||||
Compound::Map { ref mut ser, .. } => {
|
||||
try!(
|
||||
ser.formatter
|
||||
.begin_object_value(&mut ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
try!(value.serialize(&mut **ser));
|
||||
try!(
|
||||
ser.formatter
|
||||
.end_object_value(&mut ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
Ok(())
|
||||
},
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
Compound::Number { .. } => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn end(self) -> Result<()> {
|
||||
match self.state {
|
||||
State::Empty => {}
|
||||
_ => {
|
||||
try!(
|
||||
self.ser
|
||||
.formatter
|
||||
.end_object(&mut self.ser.writer)
|
||||
.map_err(Error::io)
|
||||
)
|
||||
}
|
||||
match self {
|
||||
Compound::Map { ser, state } => {
|
||||
match state {
|
||||
State::Empty => {}
|
||||
_ => {
|
||||
try!(
|
||||
ser.formatter
|
||||
.end_object(&mut ser.writer)
|
||||
.map_err(Error::io)
|
||||
)
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
Compound::Number { .. } => unreachable!(),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -773,13 +823,30 @@ where
|
||||
where
|
||||
T: ser::Serialize,
|
||||
{
|
||||
try!(ser::SerializeMap::serialize_key(self, key));
|
||||
ser::SerializeMap::serialize_value(self, value)
|
||||
match *self {
|
||||
Compound::Map { .. } => {
|
||||
try!(ser::SerializeMap::serialize_key(self, key));
|
||||
ser::SerializeMap::serialize_value(self, value)
|
||||
},
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
Compound::Number { ref mut ser, .. } => {
|
||||
if key == SERDE_STRUCT_FIELD_NAME {
|
||||
try!(value.serialize(NumberStrEmitter(&mut *ser)));
|
||||
Ok(())
|
||||
} else {
|
||||
Err(invalid_number())
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn end(self) -> Result<()> {
|
||||
ser::SerializeMap::end(self)
|
||||
match self {
|
||||
Compound::Map { .. } => ser::SerializeMap::end(self),
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
Compound::Number { .. } => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -796,35 +863,42 @@ where
|
||||
where
|
||||
T: ser::Serialize,
|
||||
{
|
||||
ser::SerializeStruct::serialize_field(self, key, value)
|
||||
match *self {
|
||||
Compound::Map { .. } => ser::SerializeStruct::serialize_field(self, key, value),
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
Compound::Number { .. } => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn end(self) -> Result<()> {
|
||||
match self.state {
|
||||
State::Empty => {}
|
||||
_ => {
|
||||
match self {
|
||||
Compound::Map { ser, state } => {
|
||||
match state {
|
||||
State::Empty => {}
|
||||
_ => {
|
||||
try!(
|
||||
ser.formatter
|
||||
.end_object(&mut ser.writer)
|
||||
.map_err(Error::io)
|
||||
)
|
||||
}
|
||||
}
|
||||
try!(
|
||||
self.ser
|
||||
.formatter
|
||||
.end_object(&mut self.ser.writer)
|
||||
.map_err(Error::io)
|
||||
)
|
||||
}
|
||||
ser.formatter
|
||||
.end_object_value(&mut ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
try!(
|
||||
ser.formatter
|
||||
.end_object(&mut ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
Ok(())
|
||||
},
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
Compound::Number { .. } => unreachable!(),
|
||||
}
|
||||
try!(
|
||||
self.ser
|
||||
.formatter
|
||||
.end_object_value(&mut self.ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
try!(
|
||||
self.ser
|
||||
.formatter
|
||||
.end_object(&mut self.ser.writer)
|
||||
.map_err(Error::io)
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -832,6 +906,11 @@ struct MapKeySerializer<'a, W: 'a, F: 'a> {
|
||||
ser: &'a mut Serializer<W, F>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn invalid_number() -> Error {
|
||||
Error::syntax(ErrorCode::InvalidNumber, 0, 0)
|
||||
}
|
||||
|
||||
fn key_must_be_a_string() -> Error {
|
||||
Error::syntax(ErrorCode::KeyMustBeAString, 0, 0)
|
||||
}
|
||||
@ -1148,6 +1227,170 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
struct NumberStrEmitter<'a, W: 'a + io::Write, F: 'a + Formatter>(&'a mut Serializer<W, F>);
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
impl<'a, W: io::Write, F: Formatter> ser::Serializer for NumberStrEmitter<'a, W, F> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
type SerializeSeq = Impossible<(), Error>;
|
||||
type SerializeTuple = Impossible<(), Error>;
|
||||
type SerializeTupleStruct = Impossible<(), Error>;
|
||||
type SerializeTupleVariant = Impossible<(), Error>;
|
||||
type SerializeMap = Impossible<(), Error>;
|
||||
type SerializeStruct = Impossible<(), Error>;
|
||||
type SerializeStructVariant = Impossible<(), Error>;
|
||||
|
||||
fn serialize_bool(self, _v: bool) -> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_i8(self, _v: i8) -> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_i16(self, _v: i16) -> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_i32(self, _v: i32) -> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_i64(self, _v: i64) -> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_u8(self, _v: u8) -> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_u16(self, _v: u16) -> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_u32(self, _v: u32) -> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_u64(self, _v: u64) -> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_f32(self, _v: f32) -> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_f64(self, _v: f64) -> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_char(self, _v: char) -> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_str(self, value: &str) -> Result<Self::Ok> {
|
||||
let NumberStrEmitter(serializer) = self;
|
||||
serializer.formatter.write_number_str(&mut serializer.writer, value)
|
||||
.map_err(Error::io)
|
||||
}
|
||||
|
||||
fn serialize_bytes(self, _value: &[u8]) -> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_none(self) -> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok>
|
||||
where T: Serialize
|
||||
{
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_unit(self) -> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self,
|
||||
_name: &'static str)
|
||||
-> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(self,
|
||||
_name: &'static str,
|
||||
_variant_index: u32,
|
||||
_variant: &'static str)
|
||||
-> Result<Self::Ok> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, _value: &T)
|
||||
-> Result<Self::Ok>
|
||||
where T: Serialize,
|
||||
{
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(self,
|
||||
_name: &'static str,
|
||||
_variant_index: u32,
|
||||
_variant: &'static str,
|
||||
_value: &T)
|
||||
-> Result<Self::Ok>
|
||||
where T: Serialize,
|
||||
{
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_seq(self, _len: Option<usize>)
|
||||
-> Result<Self::SerializeSeq> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_tuple(self, _len: usize)
|
||||
-> Result<Self::SerializeTuple> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(self, _name: &'static str, _len: usize)
|
||||
-> Result<Self::SerializeTupleStruct> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(self,
|
||||
_name: &'static str,
|
||||
_variant_index: u32,
|
||||
_variant: &'static str,
|
||||
_len: usize)
|
||||
-> Result<Self::SerializeTupleVariant> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_map(self, _len: Option<usize>)
|
||||
-> Result<Self::SerializeMap> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_struct(self, _name: &'static str, _len: usize)
|
||||
-> Result<Self::SerializeStruct> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_struct_variant(self,
|
||||
_name: &'static str,
|
||||
_variant_index: u32,
|
||||
_variant: &'static str,
|
||||
_len: usize)
|
||||
-> Result<Self::SerializeStructVariant> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a character escape code in a type-safe manner.
|
||||
pub enum CharEscape {
|
||||
/// An escaped quote `"`
|
||||
@ -1304,6 +1547,14 @@ pub trait Formatter {
|
||||
dtoa::write(writer, value).map(|_| ())
|
||||
}
|
||||
|
||||
/// Writes a number that has already been rendered to a string.
|
||||
#[inline]
|
||||
fn write_number_str<W: ?Sized>(&mut self, writer: &mut W, value: &str) -> io::Result<()>
|
||||
where W: io::Write
|
||||
{
|
||||
writer.write_all(value.as_bytes())
|
||||
}
|
||||
|
||||
/// Called before each series of `write_string_fragment` and
|
||||
/// `write_char_escape`. Writes a `"` to the specified writer.
|
||||
#[inline]
|
||||
|
167
src/value/de.rs
167
src/value/de.rs
@ -32,6 +32,12 @@ use map::Map;
|
||||
use number::Number;
|
||||
use value::Value;
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
use serde::de;
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
use number::{NumberFromString, SERDE_STRUCT_FIELD_NAME};
|
||||
|
||||
impl<'de> Deserialize<'de> for Value {
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: D) -> Result<Value, D::Error>
|
||||
@ -112,6 +118,7 @@ impl<'de> Deserialize<'de> for Value {
|
||||
Ok(Value::Array(vec))
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
fn visit_map<V>(self, mut visitor: V) -> Result<Value, V::Error>
|
||||
where
|
||||
V: MapAccess<'de>,
|
||||
@ -124,6 +131,34 @@ impl<'de> Deserialize<'de> for Value {
|
||||
|
||||
Ok(Value::Object(values))
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn visit_map<V>(self, mut visitor: V) -> Result<Value, V::Error>
|
||||
where
|
||||
V: MapAccess<'de>,
|
||||
{
|
||||
let mut key = String::new();
|
||||
let number = visitor.next_key_seed(NumberOrObject {
|
||||
key: &mut key,
|
||||
})?;
|
||||
match number {
|
||||
Some(true) => {
|
||||
let number: NumberFromString = visitor.next_value()?;
|
||||
return Ok(Value::Number(number.value))
|
||||
}
|
||||
None => return Ok(Value::Object(Map::new())),
|
||||
Some(false) => {}
|
||||
}
|
||||
|
||||
let mut values = Map::new();
|
||||
|
||||
values.insert(key, try!(visitor.next_value()));
|
||||
while let Some((key, value)) = try!(visitor.next_entry()) {
|
||||
values.insert(key, value);
|
||||
}
|
||||
|
||||
Ok(Value::Object(values))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(ValueVisitor)
|
||||
@ -199,6 +234,29 @@ impl str::FromStr for Value {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! deserialize_prim_number {
|
||||
($method:ident) => {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
fn $method<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.deserialize_any(visitor)
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn $method<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self {
|
||||
Value::Number(n) => n.$method(visitor),
|
||||
_ => self.deserialize_any(visitor),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::Deserializer<'de> for Value {
|
||||
type Error = Error;
|
||||
|
||||
@ -237,6 +295,17 @@ impl<'de> serde::Deserializer<'de> for Value {
|
||||
}
|
||||
}
|
||||
|
||||
deserialize_prim_number!(deserialize_i8);
|
||||
deserialize_prim_number!(deserialize_i16);
|
||||
deserialize_prim_number!(deserialize_i32);
|
||||
deserialize_prim_number!(deserialize_i64);
|
||||
deserialize_prim_number!(deserialize_u8);
|
||||
deserialize_prim_number!(deserialize_u16);
|
||||
deserialize_prim_number!(deserialize_u32);
|
||||
deserialize_prim_number!(deserialize_u64);
|
||||
deserialize_prim_number!(deserialize_f32);
|
||||
deserialize_prim_number!(deserialize_f64);
|
||||
|
||||
#[inline]
|
||||
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where
|
||||
@ -305,9 +374,8 @@ impl<'de> serde::Deserializer<'de> for Value {
|
||||
}
|
||||
|
||||
forward_to_deserialize_any! {
|
||||
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
|
||||
byte_buf unit unit_struct seq tuple tuple_struct map struct identifier
|
||||
ignored_any
|
||||
bool char str string bytes byte_buf unit unit_struct seq tuple
|
||||
tuple_struct map struct identifier ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
@ -512,6 +580,29 @@ impl<'de> serde::Deserializer<'de> for MapDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! deserialize_value_ref_number {
|
||||
($method:ident) => {
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
fn $method<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.deserialize_any(visitor)
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn $method<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match *self {
|
||||
Value::Number(ref n) => n.$method(visitor),
|
||||
_ => self.deserialize_any(visitor),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::Deserializer<'de> for &'de Value {
|
||||
type Error = Error;
|
||||
|
||||
@ -549,6 +640,17 @@ impl<'de> serde::Deserializer<'de> for &'de Value {
|
||||
}
|
||||
}
|
||||
|
||||
deserialize_value_ref_number!(deserialize_i8);
|
||||
deserialize_value_ref_number!(deserialize_i16);
|
||||
deserialize_value_ref_number!(deserialize_i32);
|
||||
deserialize_value_ref_number!(deserialize_i64);
|
||||
deserialize_value_ref_number!(deserialize_u8);
|
||||
deserialize_value_ref_number!(deserialize_u16);
|
||||
deserialize_value_ref_number!(deserialize_u32);
|
||||
deserialize_value_ref_number!(deserialize_u64);
|
||||
deserialize_value_ref_number!(deserialize_f32);
|
||||
deserialize_value_ref_number!(deserialize_f64);
|
||||
|
||||
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
@ -615,9 +717,8 @@ impl<'de> serde::Deserializer<'de> for &'de Value {
|
||||
}
|
||||
|
||||
forward_to_deserialize_any! {
|
||||
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
|
||||
byte_buf unit unit_struct seq tuple tuple_struct map struct identifier
|
||||
ignored_any
|
||||
bool char str string bytes byte_buf unit unit_struct seq tuple
|
||||
tuple_struct map struct identifier ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
@ -827,8 +928,8 @@ struct MapKeyDeserializer<'de> {
|
||||
}
|
||||
|
||||
macro_rules! deserialize_integer_key {
|
||||
($deserialize:ident => $visit:ident) => {
|
||||
fn $deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
($method:ident => $visit:ident) => {
|
||||
fn $method<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
@ -895,6 +996,56 @@ impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
struct NumberOrObject<'a> {
|
||||
key: &'a mut String,
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
impl<'a, 'de> DeserializeSeed<'de> for NumberOrObject<'a> {
|
||||
type Value = bool;
|
||||
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>
|
||||
{
|
||||
deserializer.deserialize_any(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
impl<'a, 'de> Visitor<'de> for NumberOrObject<'a> {
|
||||
type Value = bool;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a string key")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> Result<bool, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
if s == SERDE_STRUCT_FIELD_NAME {
|
||||
Ok(true)
|
||||
} else {
|
||||
self.key.push_str(s);
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_string<E>(self, s: String) -> Result<bool, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
if s == SERDE_STRUCT_FIELD_NAME {
|
||||
Ok(true)
|
||||
} else {
|
||||
*self.key = s;
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
fn unexpected(&self) -> Unexpected {
|
||||
match *self {
|
||||
|
458
src/value/ser.rs
458
src/value/ser.rs
@ -7,12 +7,19 @@
|
||||
// except according to those terms.
|
||||
|
||||
use serde::{self, Serialize};
|
||||
use serde::ser::{Impossible};
|
||||
|
||||
use error::{Error, ErrorCode};
|
||||
use map::Map;
|
||||
use number::Number;
|
||||
use value::{Value, to_value};
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
use serde::ser;
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
use number::{SERDE_STRUCT_NAME, SERDE_STRUCT_FIELD_NAME};
|
||||
|
||||
impl Serialize for Value {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@ -216,13 +223,14 @@ impl serde::Serializer for Serializer {
|
||||
|
||||
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Error> {
|
||||
Ok(
|
||||
SerializeMap {
|
||||
SerializeMap::Map {
|
||||
map: Map::new(),
|
||||
next_key: None,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
fn serialize_struct(
|
||||
self,
|
||||
_name: &'static str,
|
||||
@ -231,6 +239,19 @@ impl serde::Serializer for Serializer {
|
||||
self.serialize_map(Some(len))
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn serialize_struct(
|
||||
self,
|
||||
name: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeStruct, Error> {
|
||||
if name == SERDE_STRUCT_NAME {
|
||||
Ok(SerializeMap::Number { out_value: None })
|
||||
} else {
|
||||
self.serialize_map(Some(len))
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_struct_variant(
|
||||
self,
|
||||
_name: &'static str,
|
||||
@ -247,24 +268,26 @@ impl serde::Serializer for Serializer {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct SerializeVec {
|
||||
vec: Vec<Value>,
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct SerializeTupleVariant {
|
||||
name: String,
|
||||
vec: Vec<Value>,
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct SerializeMap {
|
||||
map: Map<String, Value>,
|
||||
next_key: Option<String>,
|
||||
pub enum SerializeMap {
|
||||
Map {
|
||||
map: Map<String, Value>,
|
||||
next_key: Option<String>,
|
||||
},
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
Number {
|
||||
out_value: Option<Value>
|
||||
},
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct SerializeStructVariant {
|
||||
name: String,
|
||||
map: Map<String, Value>,
|
||||
@ -348,34 +371,221 @@ impl serde::ser::SerializeMap for SerializeMap {
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
match try!(to_value(&key)) {
|
||||
Value::String(s) => self.next_key = Some(s),
|
||||
Value::Number(n) => {
|
||||
if n.is_u64() || n.is_i64() {
|
||||
self.next_key = Some(n.to_string())
|
||||
} else {
|
||||
return Err(Error::syntax(ErrorCode::KeyMustBeAString, 0, 0));
|
||||
}
|
||||
}
|
||||
_ => return Err(Error::syntax(ErrorCode::KeyMustBeAString, 0, 0)),
|
||||
};
|
||||
Ok(())
|
||||
match *self {
|
||||
SerializeMap::Map { ref mut next_key, .. } => {
|
||||
*next_key = Some(try!(key.serialize(MapKeySerializer)));
|
||||
Ok(())
|
||||
},
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
SerializeMap::Number { .. } => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let key = self.next_key.take();
|
||||
// Panic because this indicates a bug in the program rather than an
|
||||
// expected failure.
|
||||
let key = key.expect("serialize_value called before serialize_key");
|
||||
self.map.insert(key, try!(to_value(&value)));
|
||||
Ok(())
|
||||
match *self {
|
||||
SerializeMap::Map { ref mut map, ref mut next_key } => {
|
||||
let key = next_key.take();
|
||||
// Panic because this indicates a bug in the program rather than an
|
||||
// expected failure.
|
||||
let key = key.expect("serialize_value called before serialize_key");
|
||||
map.insert(key, try!(to_value(&value)));
|
||||
Ok(())
|
||||
},
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
SerializeMap::Number { .. } => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Value, Error> {
|
||||
Ok(Value::Object(self.map))
|
||||
match self {
|
||||
SerializeMap::Map { map, .. } => Ok(Value::Object(map)),
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
SerializeMap::Number { .. } => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct MapKeySerializer;
|
||||
|
||||
fn key_must_be_a_string() -> Error {
|
||||
Error::syntax(ErrorCode::KeyMustBeAString, 0, 0)
|
||||
}
|
||||
|
||||
impl serde::Serializer for MapKeySerializer {
|
||||
type Ok = String;
|
||||
type Error = Error;
|
||||
|
||||
type SerializeSeq = Impossible<String, Error>;
|
||||
type SerializeTuple = Impossible<String, Error>;
|
||||
type SerializeTupleStruct = Impossible<String, Error>;
|
||||
type SerializeTupleVariant = Impossible<String, Error>;
|
||||
type SerializeMap = Impossible<String, Error>;
|
||||
type SerializeStruct = Impossible<String, Error>;
|
||||
type SerializeStructVariant = Impossible<String, Error>;
|
||||
|
||||
#[inline]
|
||||
fn serialize_unit_variant(
|
||||
self,
|
||||
_name: &'static str,
|
||||
_variant_index: u32,
|
||||
variant: &'static str
|
||||
) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(variant.to_owned())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_newtype_struct<T: ?Sized>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
value: &T
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where T: Serialize,
|
||||
{
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
fn serialize_bool(self, _value: bool) -> Result<Self::Ok, Self::Error> {
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
|
||||
fn serialize_i8(self, value: i8) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(value.to_string())
|
||||
}
|
||||
|
||||
fn serialize_i16(self, value: i16) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(value.to_string())
|
||||
}
|
||||
|
||||
fn serialize_i32(self, value: i32) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(value.to_string())
|
||||
}
|
||||
|
||||
fn serialize_i64(self, value: i64) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(value.to_string())
|
||||
}
|
||||
|
||||
fn serialize_u8(self, value: u8) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(value.to_string())
|
||||
}
|
||||
|
||||
fn serialize_u16(self, value: u16) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(value.to_string())
|
||||
}
|
||||
|
||||
fn serialize_u32(self, value: u32) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(value.to_string())
|
||||
}
|
||||
|
||||
fn serialize_u64(self, value: u64) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(value.to_string())
|
||||
}
|
||||
|
||||
fn serialize_f32(self, _value: f32) -> Result<Self::Ok, Self::Error> {
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
|
||||
fn serialize_f64(self, _value: f64) -> Result<Self::Ok, Self::Error> {
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_char(self, value: char) -> Result<Self::Ok, Self::Error> {
|
||||
Ok({
|
||||
let mut s = String::new();
|
||||
s.push(value);
|
||||
s
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(value.to_owned())
|
||||
}
|
||||
|
||||
fn serialize_bytes(self, _value: &[u8]) -> Result<Self::Ok, Self::Error> {
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
|
||||
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
_variant_index: u32,
|
||||
_variant: &'static str,
|
||||
_value: &T
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where T: Serialize,
|
||||
{
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
|
||||
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
|
||||
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
|
||||
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(
|
||||
self,
|
||||
_name: &'static str,
|
||||
_len: usize
|
||||
) -> Result<Self::SerializeTupleStruct, Self::Error> {
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(
|
||||
self,
|
||||
_name: &'static str,
|
||||
_variant_index: u32,
|
||||
_variant: &'static str,
|
||||
_len: usize
|
||||
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
|
||||
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
|
||||
fn serialize_struct(
|
||||
self,
|
||||
_name: &'static str,
|
||||
_len: usize
|
||||
) -> Result<Self::SerializeStruct, Self::Error> {
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
|
||||
fn serialize_struct_variant(
|
||||
self,
|
||||
_name: &'static str,
|
||||
_variant_index: u32,
|
||||
_variant: &'static str,
|
||||
_len: usize
|
||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
Err(key_must_be_a_string())
|
||||
}
|
||||
}
|
||||
|
||||
@ -387,12 +597,29 @@ impl serde::ser::SerializeStruct for SerializeMap {
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
try!(serde::ser::SerializeMap::serialize_key(self, key));
|
||||
serde::ser::SerializeMap::serialize_value(self, value)
|
||||
match *self {
|
||||
SerializeMap::Map { .. } => {
|
||||
try!(serde::ser::SerializeMap::serialize_key(self, key));
|
||||
serde::ser::SerializeMap::serialize_value(self, value)
|
||||
},
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
SerializeMap::Number { ref mut out_value } => {
|
||||
if key == SERDE_STRUCT_FIELD_NAME {
|
||||
*out_value = Some(value.serialize(NumberValueEmitter)?);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(invalid_number())
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Value, Error> {
|
||||
serde::ser::SerializeMap::end(self)
|
||||
match self {
|
||||
SerializeMap::Map { .. } => serde::ser::SerializeMap::end(self),
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
SerializeMap::Number { out_value, .. } => Ok(out_value.expect("number value was not emitted")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -417,3 +644,174 @@ impl serde::ser::SerializeStructVariant for SerializeStructVariant {
|
||||
Ok(Value::Object(object))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
struct NumberValueEmitter;
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
fn invalid_number() -> Error {
|
||||
Error::syntax(ErrorCode::InvalidNumber, 0, 0)
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
impl ser::Serializer for NumberValueEmitter {
|
||||
type Ok = Value;
|
||||
type Error = Error;
|
||||
|
||||
type SerializeSeq = Impossible<Value, Error>;
|
||||
type SerializeTuple = Impossible<Value, Error>;
|
||||
type SerializeTupleStruct = Impossible<Value, Error>;
|
||||
type SerializeTupleVariant = Impossible<Value, Error>;
|
||||
type SerializeMap = Impossible<Value, Error>;
|
||||
type SerializeStruct = Impossible<Value, Error>;
|
||||
type SerializeStructVariant = Impossible<Value, Error>;
|
||||
|
||||
fn serialize_bool(self, _v: bool) -> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_i8(self, _v: i8) -> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_i16(self, _v: i16) -> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_i32(self, _v: i32) -> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_i64(self, _v: i64) -> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
|
||||
let n = try!(value.to_owned().parse());
|
||||
Ok(Value::Number(n))
|
||||
}
|
||||
|
||||
fn serialize_bytes(self, _value: &[u8]) -> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self,
|
||||
_name: &'static str)
|
||||
-> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(self,
|
||||
_name: &'static str,
|
||||
_variant_index: u32,
|
||||
_variant: &'static str)
|
||||
-> Result<Self::Ok, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, _value: &T)
|
||||
-> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(self,
|
||||
_name: &'static str,
|
||||
_variant_index: u32,
|
||||
_variant: &'static str,
|
||||
_value: &T)
|
||||
-> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_seq(self, _len: Option<usize>)
|
||||
-> Result<Self::SerializeSeq, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_tuple(self, _len: usize)
|
||||
-> Result<Self::SerializeTuple, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(self, _name: &'static str, _len: usize)
|
||||
-> Result<Self::SerializeTupleStruct, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(self,
|
||||
_name: &'static str,
|
||||
_variant_index: u32,
|
||||
_variant: &'static str,
|
||||
_len: usize)
|
||||
-> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_map(self, _len: Option<usize>)
|
||||
-> Result<Self::SerializeMap, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_struct(self, _name: &'static str, _len: usize)
|
||||
-> Result<Self::SerializeStruct, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
|
||||
fn serialize_struct_variant(self,
|
||||
_name: &'static str,
|
||||
_variant_index: u32,
|
||||
_variant: &'static str,
|
||||
_len: usize)
|
||||
-> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
Err(invalid_number())
|
||||
}
|
||||
}
|
||||
|
@ -6,5 +6,8 @@ publish = false
|
||||
|
||||
[workspace]
|
||||
|
||||
[features]
|
||||
arbitrary_precision = ["serde_json/arbitrary_precision"]
|
||||
|
||||
[dependencies]
|
||||
serde_json = { path = "../.." }
|
||||
|
114
tests/test.rs
114
tests/test.rs
@ -32,6 +32,8 @@ use std::{i8, i16, i32, i64};
|
||||
use std::io;
|
||||
use std::iter;
|
||||
use std::marker::PhantomData;
|
||||
use std::str::FromStr;
|
||||
use std::string::ToString;
|
||||
use std::{u8, u16, u32, u64};
|
||||
|
||||
use serde::de::{self, Deserialize, IgnoredAny};
|
||||
@ -39,8 +41,9 @@ use serde::ser::{self, Serialize, Serializer};
|
||||
|
||||
use serde_bytes::{ByteBuf, Bytes};
|
||||
|
||||
use serde_json::{Deserializer, Value, from_reader, from_slice, from_str, from_value,
|
||||
to_string, to_string_pretty, to_value, to_vec, to_writer};
|
||||
use serde_json::{Deserializer, Number, Value, from_reader, from_slice, from_str,
|
||||
from_value, to_string, to_string_pretty, to_value, to_vec,
|
||||
to_writer};
|
||||
|
||||
macro_rules! treemap {
|
||||
() => {
|
||||
@ -568,6 +571,17 @@ fn test_write_newtype_struct() {
|
||||
test_encode_ok(&[(outer, r#"{"outer":{"inner":123}}"#)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_number_to_untagged_enum() {
|
||||
#[derive(Eq, PartialEq, Deserialize, Debug)]
|
||||
#[serde(untagged)]
|
||||
enum E {
|
||||
N(i64),
|
||||
}
|
||||
|
||||
assert_eq!(E::N(0), E::deserialize(Number::from(0)).unwrap());
|
||||
}
|
||||
|
||||
fn test_parse_ok<T>(tests: Vec<(&str, T)>)
|
||||
where
|
||||
T: Clone + Debug + PartialEq + ser::Serialize + de::DeserializeOwned,
|
||||
@ -644,6 +658,16 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn test_fromstr_parse_err<T>(errors: &[(&str, &'static str)])
|
||||
where
|
||||
T: Debug + PartialEq + FromStr, <T as FromStr>::Err: ToString
|
||||
{
|
||||
for &(s, err) in errors {
|
||||
let actual = s.parse::<T>().unwrap_err().to_string();
|
||||
assert_eq!(actual, err, "unexpected parsing error");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_null() {
|
||||
test_parse_err::<()>(
|
||||
@ -689,7 +713,11 @@ fn test_parse_char() {
|
||||
test_parse_err::<char>(
|
||||
&[
|
||||
("\"ab\"", "invalid value: string \"ab\", expected a character at line 1 column 4"),
|
||||
("10", "invalid type: integer `10`, expected a character at line 1 column 2"),
|
||||
("10", if cfg!(feature = "arbitrary_precision") {
|
||||
"invalid type: number, expected a character at line 1 column 2"
|
||||
} else {
|
||||
"invalid type: integer `10`, expected a character at line 1 column 2"
|
||||
}),
|
||||
],
|
||||
);
|
||||
|
||||
@ -795,14 +823,19 @@ fn test_parse_negative_zero() {
|
||||
|
||||
#[test]
|
||||
fn test_parse_f64() {
|
||||
test_parse_ok(
|
||||
vec![
|
||||
test_parse_ok(vec![
|
||||
("0.0", 0.0f64),
|
||||
("3.0", 3.0f64),
|
||||
("3.00", 3.0f64),
|
||||
("3.1", 3.1),
|
||||
("-1.2", -1.2),
|
||||
("0.4", 0.4),
|
||||
]);
|
||||
|
||||
#[cfg(not(feature = "arbitrary_precision"))]
|
||||
test_parse_ok(vec![
|
||||
// With arbitrary-precision enabled, this parses as Number{"3.00"}
|
||||
// but the float is Number{"3.0"}
|
||||
("3.00", 3.0f64),
|
||||
("0.4e5", 0.4e5),
|
||||
("0.4e+5", 0.4e5),
|
||||
("0.4e15", 0.4e15),
|
||||
@ -814,9 +847,9 @@ fn test_parse_f64() {
|
||||
("0.00e00", 0.0),
|
||||
("0.00e+00", 0.0),
|
||||
("0.00e-00", 0.0),
|
||||
(&format!("{:?}", (i64::MIN as f64) - 1.0), (i64::MIN as f64) - 1.0),
|
||||
(&format!("{:?}", (u64::MAX as f64) + 1.0), (u64::MAX as f64) + 1.0),
|
||||
(&format!("{:?}", f64::EPSILON), f64::EPSILON),
|
||||
(&format!("{}", (i64::MIN as f64) - 1.0), (i64::MIN as f64) - 1.0),
|
||||
(&format!("{}", (u64::MAX as f64) + 1.0), (u64::MAX as f64) + 1.0),
|
||||
(&format!("{}", f64::EPSILON), f64::EPSILON),
|
||||
("0.0000000000000000000000000000000000000000000000000123e50", 1.23),
|
||||
("100e-777777777777777777777777777", 0.0),
|
||||
("1010101010101010101010101010101010101010", 10101010101010101010e20),
|
||||
@ -846,8 +879,60 @@ fn test_parse_f64() {
|
||||
000000000000000000000000000000000000000000000000000000000000\
|
||||
000000000000000000000000000000000000000000000000000000000000\
|
||||
000000000000000000e-10", 1e308),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_char() {
|
||||
let value = json!(({
|
||||
let mut map = BTreeMap::new();
|
||||
map.insert('c', ());
|
||||
map
|
||||
}));
|
||||
assert_eq!(&Value::Null, value.get("c").unwrap());
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
#[test]
|
||||
fn test_malicious_number() {
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename = "$__serde_private_Number")]
|
||||
struct S {
|
||||
#[serde(rename = "$__serde_private_number")]
|
||||
f: &'static str,
|
||||
}
|
||||
|
||||
let actual = serde_json::to_value(&S { f: "not a number" }).unwrap_err().to_string();
|
||||
assert_eq!(actual, "invalid number at line 1 column 1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_number() {
|
||||
test_parse_ok(vec![
|
||||
("0.0", Number::from_f64(0.0f64).unwrap()),
|
||||
("3.0", Number::from_f64(3.0f64).unwrap()),
|
||||
("3.1", Number::from_f64(3.1).unwrap()),
|
||||
("-1.2", Number::from_f64(-1.2).unwrap()),
|
||||
("0.4", Number::from_f64(0.4).unwrap()),
|
||||
]);
|
||||
|
||||
test_fromstr_parse_err::<Number>(
|
||||
&[
|
||||
(" 1.0", "invalid number at line 1 column 1"),
|
||||
("1.0 ", "invalid number at line 1 column 4"),
|
||||
("\t1.0", "invalid number at line 1 column 1"),
|
||||
("1.0\t", "invalid number at line 1 column 4"),
|
||||
]
|
||||
);
|
||||
|
||||
#[cfg(feature = "arbitrary_precision")]
|
||||
test_parse_ok(vec![
|
||||
("1e999", Number::from_string_unchecked("1e999".to_owned())),
|
||||
("-1e999", Number::from_string_unchecked("-1e999".to_owned())),
|
||||
("1e-999", Number::from_string_unchecked("1e-999".to_owned())),
|
||||
("2.3e999", Number::from_string_unchecked("2.3e999".to_owned())),
|
||||
("-2.3e999", Number::from_string_unchecked("-2.3e999".to_owned())),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1020,7 +1105,11 @@ fn test_parse_object() {
|
||||
fn test_parse_struct() {
|
||||
test_parse_err::<Outer>(
|
||||
&[
|
||||
("5", "invalid type: integer `5`, expected struct Outer at line 1 column 1"),
|
||||
("5", if cfg!(feature = "arbitrary_precision") {
|
||||
"invalid type: number, expected struct Outer at line 1 column 1"
|
||||
} else {
|
||||
"invalid type: integer `5`, expected struct Outer at line 1 column 1"
|
||||
}),
|
||||
("\"hello\"", "invalid type: string \"hello\", expected struct Outer at line 1 column 7"),
|
||||
("{\"inner\": true}",
|
||||
"invalid type: boolean `true`, expected a sequence at line 1 column 14"),
|
||||
@ -1060,8 +1149,7 @@ fn test_parse_struct() {
|
||||
[ null, 2, [\"abc\", \"xyz\"] ]
|
||||
]
|
||||
]",
|
||||
)
|
||||
.unwrap();
|
||||
).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
v,
|
||||
|
@ -36,10 +36,12 @@ else
|
||||
(cd "$DIR/tests/deps" && channel build)
|
||||
channel test
|
||||
channel test --features preserve_order
|
||||
channel test --features arbitrary_precision
|
||||
|
||||
for CHANNEL in stable 1.15.0 beta; do
|
||||
channel clean
|
||||
channel build
|
||||
channel build --features preserve_order
|
||||
channel build --features arbitrary_precision
|
||||
done
|
||||
fi
|
||||
|
Loading…
x
Reference in New Issue
Block a user