From 6d38232a2c75e90372af33fea493aa401cfa7b04 Mon Sep 17 00:00:00 2001 From: Sam Rijs Date: Fri, 14 Sep 2018 20:11:44 +1000 Subject: [PATCH 01/17] Implement RawValue type fixes #355 --- src/de.rs | 23 +++++- src/lib.rs | 3 +- src/raw.rs | 93 +++++++++++++++++++++ src/read.rs | 54 ++++++++++++- src/ser.rs | 204 +++++++++++++++++++++++++++++++++++++++++++++-- src/value/de.rs | 6 +- src/value/mod.rs | 1 + src/value/ser.rs | 194 ++++++++++++++++++++++++++++++++++++++++++-- tests/test.rs | 51 +++++++++++- 9 files changed, 612 insertions(+), 17 deletions(-) create mode 100644 src/raw.rs diff --git a/src/de.rs b/src/de.rs index f1c5c3cff..0ad91a2a8 100644 --- a/src/de.rs +++ b/src/de.rs @@ -8,6 +8,7 @@ //! Deserialize JSON data to a Rust data structure. +use std::borrow::Cow; use std::io; use std::marker::PhantomData; use std::result; @@ -946,6 +947,22 @@ impl<'de, R: Read<'de>> Deserializer { } } } + + fn deserialize_raw_value(&mut self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + if let None = try!(self.parse_whitespace()) { + return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); + } + + self.read.toggle_raw_buffering(); + de::Deserializer::deserialize_any(&mut *self, de::IgnoredAny)?; + match self.read.toggle_raw_buffering().unwrap() { + Cow::Owned(byte_buf) => visitor.visit_byte_buf(byte_buf), + Cow::Borrowed(bytes) => visitor.visit_borrowed_bytes(bytes), + } + } } impl FromStr for Number { @@ -1412,10 +1429,14 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { /// Parses a newtype struct as the underlying value. #[inline] - fn deserialize_newtype_struct(self, _name: &str, visitor: V) -> Result + fn deserialize_newtype_struct(self, name: &str, visitor: V) -> Result where V: de::Visitor<'de>, { + if name == ::raw::SERDE_STRUCT_NAME { + return self.deserialize_raw_value(visitor); + } + visitor.visit_newtype_struct(self) } diff --git a/src/lib.rs b/src/lib.rs index d9b79175e..e0b7a0b77 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -364,7 +364,7 @@ pub use self::ser::{ to_string, to_string_pretty, to_vec, to_vec_pretty, to_writer, to_writer_pretty, Serializer, }; #[doc(inline)] -pub use self::value::{from_value, to_value, Map, Number, Value}; +pub use self::value::{from_value, to_value, Map, Number, RawValue, Value}; // We only use our own error type; no need for From conversions provided by the // standard library's try! macro. This reduces lines of LLVM IR by 4%. @@ -388,4 +388,5 @@ pub mod value; mod iter; mod number; +mod raw; mod read; diff --git a/src/raw.rs b/src/raw.rs new file mode 100644 index 000000000..74d2c7a00 --- /dev/null +++ b/src/raw.rs @@ -0,0 +1,93 @@ +use std::borrow::Cow; +use std::fmt; + +use serde::de::Visitor; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +/// Represents any valid JSON value as a series of raw bytes. +/// +/// This type can be used to defer parsing parts of a payload until later, +/// or to embed it verbatim into another JSON payload. +/// +/// When serializing, a value of this type will retain its original formatting +/// and will not be minified or pretty-printed. +/// +/// When deserializing, this type can not be used with the `#[serde(flatten)]` attribute, +/// as it relies on the original input buffer. + +#[derive(Debug, Clone, PartialEq)] +pub struct RawValue<'a>(Cow<'a, str>); + +impl<'a> AsRef for RawValue<'a> { + fn as_ref(&self) -> &str { + &self.0 + } +} + +impl<'a> fmt::Display for RawValue<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(&self.0) + } +} + +/// Not public API. Should be pub(crate). +#[doc(hidden)] +pub const SERDE_STRUCT_NAME: &'static str = "$__serde_private_RawValue"; + +impl<'a> Serialize for RawValue<'a> { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_newtype_struct(SERDE_STRUCT_NAME, &self.0) + } +} + +impl<'a, 'de> Deserialize<'de> for RawValue<'a> +where + 'de: 'a, +{ + #[inline] + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct RawValueVisitor; + + impl<'de> Visitor<'de> for RawValueVisitor { + type Value = RawValue<'de>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "a deserializable RawValue") + } + + fn visit_string(self, s: String) -> Result + where + E: ::serde::de::Error, + { + Ok(RawValue(Cow::Owned(s))) + } + + fn visit_byte_buf(self, b: Vec) -> Result + where + E: ::serde::de::Error, + { + String::from_utf8(b) + .map(|s| RawValue(Cow::Owned(s))) + .map_err(|err| ::serde::de::Error::custom(err)) + } + + fn visit_borrowed_bytes(self, b: &'de [u8]) -> Result + where + E: ::serde::de::Error, + { + ::std::str::from_utf8(b) + .map(|s| RawValue(Cow::Borrowed(s))) + .map_err(|err| ::serde::de::Error::custom(err)) + } + } + + deserializer.deserialize_newtype_struct(SERDE_STRUCT_NAME, RawValueVisitor) + } +} diff --git a/src/read.rs b/src/read.rs index f2cc9f93b..8084f40ba 100644 --- a/src/read.rs +++ b/src/read.rs @@ -6,6 +6,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::borrow::Cow; use std::ops::Deref; use std::{char, cmp, io, str}; @@ -76,6 +77,13 @@ pub trait Read<'de>: private::Sealed { /// string until the next quotation mark but discards the data. #[doc(hidden)] fn ignore_str(&mut self) -> Result<()>; + + /// Switch raw buffering mode on/off. When switching off, returns a copy-on-write + /// buffer with the captured data. + /// + /// This is used to deserialize `RawValue`. + #[doc(hidden)] + fn toggle_raw_buffering(&mut self) -> Option>; } pub struct Position { @@ -107,6 +115,7 @@ where iter: LineColIterator>, /// Temporary storage of peeked byte. ch: Option, + raw_buffer: Option>, } /// JSON input source that reads from a slice of bytes. @@ -117,6 +126,7 @@ pub struct SliceRead<'a> { slice: &'a [u8], /// Index of the *next* byte that will be returned by next() or peek(). index: usize, + raw_buffering_start_index: Option, } /// JSON input source that reads from a UTF-8 string. @@ -142,6 +152,7 @@ where IoRead { iter: LineColIterator::new(reader.bytes()), ch: None, + raw_buffer: None, } } } @@ -193,10 +204,20 @@ where #[inline] fn next(&mut self) -> io::Result> { match self.ch.take() { - Some(ch) => Ok(Some(ch)), + Some(ch) => { + if let Some(ref mut buf) = self.raw_buffer { + buf.push(ch); + } + Ok(Some(ch)) + } None => match self.iter.next() { Some(Err(err)) => Err(err), - Some(Ok(ch)) => Ok(Some(ch)), + Some(Ok(ch)) => { + if let Some(ref mut buf) = self.raw_buffer { + buf.push(ch); + } + Ok(Some(ch)) + } None => Ok(None), }, } @@ -219,7 +240,11 @@ where #[inline] fn discard(&mut self) { - self.ch = None; + if let Some(ch) = self.ch.take() { + if let Some(ref mut buf) = self.raw_buffer { + buf.push(ch); + } + } } fn position(&self) -> Position { @@ -274,6 +299,15 @@ where } } } + + fn toggle_raw_buffering(&mut self) -> Option> { + if let Some(buffer) = self.raw_buffer.take() { + Some(Cow::Owned(buffer)) + } else { + self.raw_buffer = Some(Vec::new()); + None + } + } } ////////////////////////////////////////////////////////////////////////////// @@ -284,6 +318,7 @@ impl<'a> SliceRead<'a> { SliceRead { slice: slice, index: 0, + raw_buffering_start_index: None, } } @@ -437,6 +472,15 @@ impl<'a> Read<'a> for SliceRead<'a> { } } } + + fn toggle_raw_buffering(&mut self) -> Option> { + if let Some(start_index) = self.raw_buffering_start_index.take() { + Some(Cow::Borrowed(&self.slice[start_index..self.index])) + } else { + self.raw_buffering_start_index = Some(self.index); + None + } + } } ////////////////////////////////////////////////////////////////////////////// @@ -498,6 +542,10 @@ impl<'a> Read<'a> for StrRead<'a> { fn ignore_str(&mut self) -> Result<()> { self.delegate.ignore_str() } + + fn toggle_raw_buffering(&mut self) -> Option> { + self.delegate.toggle_raw_buffering() + } } ////////////////////////////////////////////////////////////////////////////// diff --git a/src/ser.rs b/src/ser.rs index ca9b637ee..af53c8cae 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -14,14 +14,11 @@ use std::num::FpCategory; use std::str; use super::error::{Error, ErrorCode, Result}; -use serde::ser::{self, Impossible}; +use serde::ser::{self, Impossible, Serialize}; use itoa; use ryu; -#[cfg(feature = "arbitrary_precision")] -use serde::Serialize; - /// A structure for serializing Rust values into JSON. pub struct Serializer { writer: W, @@ -286,10 +283,14 @@ where /// Serialize newtypes without an object wrapper. #[inline] - fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result<()> + fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result<()> where T: ser::Serialize, { + if name == ::raw::SERDE_STRUCT_NAME { + return value.serialize(RawValueStrEmitter(self)); + } + value.serialize(self) } @@ -1400,6 +1401,189 @@ impl<'a, W: io::Write, F: Formatter> ser::Serializer for NumberStrEmitter<'a, W, } } +struct RawValueStrEmitter<'a, W: 'a + io::Write, F: 'a + Formatter>(&'a mut Serializer); + +impl<'a, W: io::Write, F: Formatter> ser::Serializer for RawValueStrEmitter<'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 { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_i8(self, _v: i8) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_i16(self, _v: i16) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_i32(self, _v: i32) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_i64(self, _v: i64) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + serde_if_integer128! { + fn serialize_i128(self, _v: i128) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + } + + fn serialize_u8(self, _v: u8) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_u16(self, _v: u16) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_u32(self, _v: u32) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_u64(self, _v: u64) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + serde_if_integer128! { + fn serialize_u128(self, _v: u128) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + } + + fn serialize_f32(self, _v: f32) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_f64(self, _v: f64) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_char(self, _v: char) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_str(self, value: &str) -> Result { + let RawValueStrEmitter(serializer) = self; + serializer + .formatter + .write_raw_fragment(&mut serializer.writer, value) + .map_err(Error::io) + } + + fn serialize_bytes(self, _value: &[u8]) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_none(self) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_some(self, _value: &T) -> Result + where + T: Serialize, + { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_unit(self) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + ) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_newtype_struct( + self, + _name: &'static str, + _value: &T, + ) -> Result + where + T: Serialize, + { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result + where + T: Serialize, + { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_seq(self, _len: Option) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_tuple(self, _len: usize) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_map(self, _len: Option) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(ser::Error::custom("expected RawValue")) + } +} + /// Represents a character escape code in a type-safe manner. pub enum CharEscape { /// An escaped quote `"` @@ -1743,6 +1927,16 @@ pub trait Formatter { { Ok(()) } + + /// Writes a raw json fragment that doesn't need any escaping to the + /// specified writer. + #[inline] + fn write_raw_fragment(&mut self, writer: &mut W, fragment: &str) -> io::Result<()> + where + W: io::Write, + { + writer.write_all(fragment.as_bytes()) + } } /// This structure compacts a JSON value with no extra whitespace. diff --git a/src/value/de.rs b/src/value/de.rs index dc8dbc6be..73dfb8bce 100644 --- a/src/value/de.rs +++ b/src/value/de.rs @@ -300,12 +300,16 @@ impl<'de> serde::Deserializer<'de> for Value { #[inline] fn deserialize_newtype_struct( self, - _name: &'static str, + name: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { + if name == ::raw::SERDE_STRUCT_NAME { + return visitor.visit_string(self.to_string()); + } + visitor.visit_newtype_struct(self) } diff --git a/src/value/mod.rs b/src/value/mod.rs index f5e33b457..155874a9c 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -118,6 +118,7 @@ use serde::ser::Serialize; use error::Error; pub use map::Map; pub use number::Number; +pub use raw::RawValue; pub use self::index::Index; diff --git a/src/value/ser.rs b/src/value/ser.rs index d3f71b373..54ce18db8 100644 --- a/src/value/ser.rs +++ b/src/value/ser.rs @@ -6,7 +6,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use serde::ser::Impossible; +use serde::ser::{self, Impossible}; use serde::{self, Serialize}; use error::{Error, ErrorCode}; @@ -14,9 +14,6 @@ use map::Map; use number::Number; use value::{to_value, Value}; -#[cfg(feature = "arbitrary_precision")] -use serde::ser; - impl Serialize for Value { #[inline] fn serialize(&self, serializer: S) -> Result @@ -150,12 +147,16 @@ impl serde::Serializer for Serializer { #[inline] fn serialize_newtype_struct( self, - _name: &'static str, + name: &'static str, value: &T, ) -> Result where T: Serialize, { + if name == ::raw::SERDE_STRUCT_NAME { + return value.serialize(RawValueEmitter); + } + value.serialize(self) } @@ -812,3 +813,186 @@ impl ser::Serializer for NumberValueEmitter { Err(invalid_number()) } } + +struct RawValueEmitter; + +impl ser::Serializer for RawValueEmitter { + type Ok = Value; + type Error = Error; + + type SerializeSeq = Impossible; + type SerializeTuple = Impossible; + type SerializeTupleStruct = Impossible; + type SerializeTupleVariant = Impossible; + type SerializeMap = Impossible; + type SerializeStruct = Impossible; + type SerializeStructVariant = Impossible; + + fn serialize_bool(self, _v: bool) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_i8(self, _v: i8) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_i16(self, _v: i16) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_i32(self, _v: i32) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_i64(self, _v: i64) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + serde_if_integer128! { + fn serialize_i128(self, _v: i128) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + } + + fn serialize_u8(self, _v: u8) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_u16(self, _v: u16) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_u32(self, _v: u32) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_u64(self, _v: u64) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + serde_if_integer128! { + fn serialize_u128(self, _v: u128) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + } + + fn serialize_f32(self, _v: f32) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_f64(self, _v: f64) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_char(self, _v: char) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_str(self, value: &str) -> Result { + ::from_str(value) + } + + fn serialize_bytes(self, _value: &[u8]) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_none(self) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_some(self, _value: &T) -> Result + where + T: Serialize, + { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_unit(self) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + ) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_newtype_struct( + self, + _name: &'static str, + _value: &T, + ) -> Result + where + T: Serialize, + { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result + where + T: Serialize, + { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_seq(self, _len: Option) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_tuple(self, _len: usize) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_map(self, _len: Option) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(ser::Error::custom("expected RawValue")) + } +} diff --git a/tests/test.rs b/tests/test.rs index 08d038837..09c51a62d 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -44,7 +44,7 @@ use serde_bytes::{ByteBuf, Bytes}; use serde_json::{ from_reader, from_slice, from_str, from_value, to_string, to_string_pretty, to_value, to_vec, - to_writer, Deserializer, Number, Value, + to_writer, Deserializer, Number, RawValue, Value, }; macro_rules! treemap { @@ -2039,3 +2039,52 @@ fn test_integer128() { ), ]); } + +#[test] +fn test_raw_value() { + #[derive(Serialize, Deserialize)] + struct Wrapper<'a> { + a: i8, + #[serde(borrow)] + b: RawValue<'a>, + c: i8, + }; + + let wrapper_from_str = + serde_json::from_str::(r#"{"a": 1, "b": {"foo": 2}, "c": 3}"#).unwrap(); + assert_eq!(r#"{"foo": 2}"#, wrapper_from_str.b.as_ref()); + + let wrapper_from_reader = serde_json::from_reader::<_, Wrapper<'static>>( + br#"{"a": 1, "b": {"foo": 2}, "c": 3}"#.as_ref(), + ).unwrap(); + assert_eq!(r#"{"foo": 2}"#, wrapper_from_reader.b.as_ref()); + + let wrapper_from_value = + serde_json::from_value::>(json!({"a": 1, "b": {"foo": 2}, "c": 3})) + .unwrap(); + assert_eq!(r#"{"foo":2}"#, wrapper_from_value.b.as_ref()); + + let wrapper_to_string = serde_json::to_string(&wrapper_from_str).unwrap(); + assert_eq!(r#"{"a":1,"b":{"foo": 2},"c":3}"#, wrapper_to_string); + + let wrapper_to_value = serde_json::to_value(&wrapper_from_str).unwrap(); + assert_eq!(json!({"a": 1, "b": {"foo": 2}, "c": 3}), wrapper_to_value); + + let array_from_str = + serde_json::from_str::>(r#"["a", 42, {"foo": "bar"}, null]"#).unwrap(); + assert_eq!(r#""a""#, array_from_str[0].as_ref()); + assert_eq!(r#"42"#, array_from_str[1].as_ref()); + assert_eq!(r#"{"foo": "bar"}"#, array_from_str[2].as_ref()); + assert_eq!(r#"null"#, array_from_str[3].as_ref()); + + let array_from_reader = serde_json::from_reader::<_, Vec>>( + br#"["a", 42, {"foo": "bar"}, null]"#.as_ref(), + ).unwrap(); + assert_eq!(r#""a""#, array_from_reader[0].as_ref()); + assert_eq!(r#"42"#, array_from_reader[1].as_ref()); + assert_eq!(r#"{"foo": "bar"}"#, array_from_reader[2].as_ref()); + assert_eq!(r#"null"#, array_from_reader[3].as_ref()); + + let array_to_string = serde_json::to_string(&array_from_str).unwrap(); + assert_eq!(r#"["a",42,{"foo": "bar"},null]"#, array_to_string); +} From 3956ba4d460a1ad9515062d571c0de6916b53e79 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 16 Sep 2018 11:16:17 -0700 Subject: [PATCH 02/17] Simplify raw buffer toggle --- src/de.rs | 15 ++++-------- src/read.rs | 66 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 47 insertions(+), 34 deletions(-) diff --git a/src/de.rs b/src/de.rs index 0ad91a2a8..0e8fbe584 100644 --- a/src/de.rs +++ b/src/de.rs @@ -8,7 +8,6 @@ //! Deserialize JSON data to a Rust data structure. -use std::borrow::Cow; use std::io; use std::marker::PhantomData; use std::result; @@ -952,16 +951,10 @@ impl<'de, R: Read<'de>> Deserializer { where V: de::Visitor<'de>, { - if let None = try!(self.parse_whitespace()) { - return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); - } - - self.read.toggle_raw_buffering(); - de::Deserializer::deserialize_any(&mut *self, de::IgnoredAny)?; - match self.read.toggle_raw_buffering().unwrap() { - Cow::Owned(byte_buf) => visitor.visit_byte_buf(byte_buf), - Cow::Borrowed(bytes) => visitor.visit_borrowed_bytes(bytes), - } + self.parse_whitespace()?; + self.read.begin_raw_buffering(); + self.ignore_value()?; + self.read.end_raw_buffering(visitor) } } diff --git a/src/read.rs b/src/read.rs index 8084f40ba..cd9242657 100644 --- a/src/read.rs +++ b/src/read.rs @@ -6,10 +6,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::borrow::Cow; use std::ops::Deref; use std::{char, cmp, io, str}; +use serde::de::Visitor; + use iter::LineColIterator; use super::error::{Error, ErrorCode, Result}; @@ -78,12 +79,18 @@ pub trait Read<'de>: private::Sealed { #[doc(hidden)] fn ignore_str(&mut self) -> Result<()>; - /// Switch raw buffering mode on/off. When switching off, returns a copy-on-write - /// buffer with the captured data. + /// Switch raw buffering mode on. /// - /// This is used to deserialize `RawValue`. + /// This is used when deserializing `RawValue`. + #[doc(hidden)] + fn begin_raw_buffering(&mut self); + + /// Switch raw buffering mode off and provides the raw buffered data to the + /// given visitor. #[doc(hidden)] - fn toggle_raw_buffering(&mut self) -> Option>; + fn end_raw_buffering(&mut self, visitor: V) -> Result + where + V: Visitor<'de>; } pub struct Position { @@ -126,7 +133,7 @@ pub struct SliceRead<'a> { slice: &'a [u8], /// Index of the *next* byte that will be returned by next() or peek(). index: usize, - raw_buffering_start_index: Option, + raw_buffering_start_index: usize, } /// JSON input source that reads from a UTF-8 string. @@ -300,13 +307,16 @@ where } } - fn toggle_raw_buffering(&mut self) -> Option> { - if let Some(buffer) = self.raw_buffer.take() { - Some(Cow::Owned(buffer)) - } else { - self.raw_buffer = Some(Vec::new()); - None - } + fn begin_raw_buffering(&mut self) { + self.raw_buffer = Some(Vec::new()); + } + + fn end_raw_buffering(&mut self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let raw = self.raw_buffer.take().unwrap(); + visitor.visit_byte_buf(raw) } } @@ -318,7 +328,7 @@ impl<'a> SliceRead<'a> { SliceRead { slice: slice, index: 0, - raw_buffering_start_index: None, + raw_buffering_start_index: 0, } } @@ -473,13 +483,16 @@ impl<'a> Read<'a> for SliceRead<'a> { } } - fn toggle_raw_buffering(&mut self) -> Option> { - if let Some(start_index) = self.raw_buffering_start_index.take() { - Some(Cow::Borrowed(&self.slice[start_index..self.index])) - } else { - self.raw_buffering_start_index = Some(self.index); - None - } + fn begin_raw_buffering(&mut self) { + self.raw_buffering_start_index = self.index; + } + + fn end_raw_buffering(&mut self, visitor: V) -> Result + where + V: Visitor<'a>, + { + let raw = &self.slice[self.raw_buffering_start_index..self.index]; + visitor.visit_borrowed_bytes(raw) } } @@ -543,8 +556,15 @@ impl<'a> Read<'a> for StrRead<'a> { self.delegate.ignore_str() } - fn toggle_raw_buffering(&mut self) -> Option> { - self.delegate.toggle_raw_buffering() + fn begin_raw_buffering(&mut self) { + self.delegate.begin_raw_buffering() + } + + fn end_raw_buffering(&mut self, visitor: V) -> Result + where + V: Visitor<'a>, + { + self.delegate.end_raw_buffering(visitor) } } From 92970d02709ace0f9315ffcd1f192dfc4b6d219b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 16 Sep 2018 11:31:53 -0700 Subject: [PATCH 03/17] Pass data to RawValue as a string This avoids a redundant UTF-8 check in the case of StrRead. --- src/raw.rs | 19 ++++--------------- src/read.rs | 11 ++++++++--- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/raw.rs b/src/raw.rs index 74d2c7a00..780c095a5 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -62,29 +62,18 @@ where write!(formatter, "a deserializable RawValue") } - fn visit_string(self, s: String) -> Result + fn visit_borrowed_str(self, s: &'de str) -> Result where E: ::serde::de::Error, { - Ok(RawValue(Cow::Owned(s))) + Ok(RawValue(Cow::Borrowed(s))) } - fn visit_byte_buf(self, b: Vec) -> Result - where - E: ::serde::de::Error, - { - String::from_utf8(b) - .map(|s| RawValue(Cow::Owned(s))) - .map_err(|err| ::serde::de::Error::custom(err)) - } - - fn visit_borrowed_bytes(self, b: &'de [u8]) -> Result + fn visit_string(self, s: String) -> Result where E: ::serde::de::Error, { - ::std::str::from_utf8(b) - .map(|s| RawValue(Cow::Borrowed(s))) - .map_err(|err| ::serde::de::Error::custom(err)) + Ok(RawValue(Cow::Owned(s))) } } diff --git a/src/read.rs b/src/read.rs index cd9242657..c94f984b8 100644 --- a/src/read.rs +++ b/src/read.rs @@ -141,6 +141,7 @@ pub struct SliceRead<'a> { // Able to elide UTF-8 checks by assuming that the input is valid UTF-8. pub struct StrRead<'a> { delegate: SliceRead<'a>, + data: &'a str, } // Prevent users from implementing the Read trait. @@ -316,7 +317,8 @@ where V: Visitor<'de>, { let raw = self.raw_buffer.take().unwrap(); - visitor.visit_byte_buf(raw) + let raw = String::from_utf8(raw).unwrap(); + visitor.visit_string(raw) } } @@ -492,7 +494,8 @@ impl<'a> Read<'a> for SliceRead<'a> { V: Visitor<'a>, { let raw = &self.slice[self.raw_buffering_start_index..self.index]; - visitor.visit_borrowed_bytes(raw) + let raw = str::from_utf8(raw).unwrap(); + visitor.visit_borrowed_str(raw) } } @@ -503,6 +506,7 @@ impl<'a> StrRead<'a> { pub fn new(s: &'a str) -> Self { StrRead { delegate: SliceRead::new(s.as_bytes()), + data: s, } } } @@ -564,7 +568,8 @@ impl<'a> Read<'a> for StrRead<'a> { where V: Visitor<'a>, { - self.delegate.end_raw_buffering(visitor) + let raw = &self.data[self.delegate.raw_buffering_start_index..self.delegate.index]; + visitor.visit_borrowed_str(raw) } } From 7e373b6125ee6f19bb9a9538c51c92bf51be1f90 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 16 Sep 2018 20:03:38 -0700 Subject: [PATCH 04/17] Change mapping of RawValue to a struct with one key This is what serde_json::Number does in arbitrary precision mode. It is more robust because it fails fast in formats that are not JSON. In the previous implementation, it was too easy when mixing different data formats to end up with a RawValue holding something that is not valid JSON data: extern crate serde; extern crate serde_json; use serde::de::{Deserialize, IntoDeserializer, value::Error}; use serde_json::RawValue; fn main() -> Result<(), Error> { let bad = RawValue::deserialize("~~~".to_owned().into_deserializer())?; println!("{}", bad); Ok(()) } The new implementation detects in this case that we are not deserializing from a deserializer that speaks the language of serde_json::RawValue and will fail fast rather than producing an illegal RawValue. --- src/raw.rs | 171 ++++++++++++++++++++++++++++++++++++++++++----- src/read.rs | 9 +-- src/ser.rs | 31 +++++++-- src/value/de.rs | 21 +++++- src/value/ser.rs | 92 +++++++++++++------------ 5 files changed, 249 insertions(+), 75 deletions(-) diff --git a/src/raw.rs b/src/raw.rs index 780c095a5..068d3fe3e 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -1,8 +1,11 @@ use std::borrow::Cow; use std::fmt; -use serde::de::Visitor; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde::ser::{Serialize, Serializer, SerializeStruct}; +use serde::de::{self, Deserialize, Deserializer, DeserializeSeed, IntoDeserializer, MapAccess, Unexpected, Visitor}; +use serde::de::value::BorrowedStrDeserializer; + +use error::Error; /// Represents any valid JSON value as a series of raw bytes. /// @@ -30,9 +33,8 @@ impl<'a> fmt::Display for RawValue<'a> { } } -/// Not public API. Should be pub(crate). -#[doc(hidden)] -pub const SERDE_STRUCT_NAME: &'static str = "$__serde_private_RawValue"; +pub const SERDE_STRUCT_NAME: &'static str = "$serde_json::RawValue"; +pub const SERDE_STRUCT_FIELD_NAME: &'static str = "$serde_json::RawValue::id"; impl<'a> Serialize for RawValue<'a> { #[inline] @@ -40,14 +42,13 @@ impl<'a> Serialize for RawValue<'a> { where S: Serializer, { - serializer.serialize_newtype_struct(SERDE_STRUCT_NAME, &self.0) + let mut s = serializer.serialize_struct(SERDE_STRUCT_NAME, 1)?; + s.serialize_field(SERDE_STRUCT_FIELD_NAME, &self.0)?; + s.end() } } -impl<'a, 'de> Deserialize<'de> for RawValue<'a> -where - 'de: 'a, -{ +impl<'a, 'de: 'a> Deserialize<'de> for RawValue<'a> { #[inline] fn deserialize(deserializer: D) -> Result where @@ -59,24 +60,158 @@ where type Value = RawValue<'de>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a deserializable RawValue") + write!(formatter, "any valid JSON value") } - fn visit_borrowed_str(self, s: &'de str) -> Result + fn visit_map(self, mut visitor: V) -> Result where - E: ::serde::de::Error, + V: MapAccess<'de>, { - Ok(RawValue(Cow::Borrowed(s))) + let value = visitor.next_key::()?; + if value.is_none() { + return Err(de::Error::invalid_type(Unexpected::Map, &self)); + } + visitor.next_value_seed(RawValueFromString) + } + } + + deserializer.deserialize_newtype_struct(SERDE_STRUCT_NAME, RawValueVisitor) + } +} + +struct RawKey; + +impl<'de> Deserialize<'de> for RawKey { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct FieldVisitor; + + impl<'de> Visitor<'de> for FieldVisitor { + type Value = (); + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("raw value") } - fn visit_string(self, s: String) -> Result + fn visit_str(self, s: &str) -> Result<(), E> where - E: ::serde::de::Error, + E: de::Error, { - Ok(RawValue(Cow::Owned(s))) + if s == SERDE_STRUCT_FIELD_NAME { + Ok(()) + } else { + Err(de::Error::custom("unexpected raw value")) + } } } - deserializer.deserialize_newtype_struct(SERDE_STRUCT_NAME, RawValueVisitor) + deserializer.deserialize_identifier(FieldVisitor)?; + Ok(RawKey) + } +} + +pub struct RawValueFromString; + +impl<'de> DeserializeSeed<'de> for RawValueFromString { + type Value = RawValue<'de>; + + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(self) + } +} + +impl<'de> Visitor<'de> for RawValueFromString { + type Value = RawValue<'de>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("raw value") + } + + fn visit_borrowed_str(self, s: &'de str) -> Result + where + E: de::Error, + { + Ok(RawValue(Cow::Borrowed(s))) + } + + fn visit_string(self, s: String) -> Result + where + E: de::Error, + { + Ok(RawValue(Cow::Owned(s))) + } +} + +struct RawKeyDeserializer; + +impl<'de> Deserializer<'de> for RawKeyDeserializer { + type Error = Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_borrowed_str(SERDE_STRUCT_FIELD_NAME) + } + + forward_to_deserialize_any! { + bool u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 char str string seq + bytes byte_buf map struct option unit newtype_struct ignored_any + unit_struct tuple_struct tuple enum identifier + } +} + +pub struct OwnedRawDeserializer { + pub raw_value: Option, +} + +impl<'de> MapAccess<'de> for OwnedRawDeserializer { + type Error = Error; + + fn next_key_seed(&mut self, seed: K) -> Result, Error> + where + K: de::DeserializeSeed<'de>, + { + if self.raw_value.is_none() { + return Ok(None); + } + seed.deserialize(RawKeyDeserializer).map(Some) + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: de::DeserializeSeed<'de>, + { + seed.deserialize(self.raw_value.take().unwrap().into_deserializer()) + } +} + +pub struct BorrowedRawDeserializer<'de> { + pub raw_value: Option<&'de str>, +} + +impl<'de> MapAccess<'de> for BorrowedRawDeserializer<'de> { + type Error = Error; + + fn next_key_seed(&mut self, seed: K) -> Result, Error> + where + K: de::DeserializeSeed<'de>, + { + if self.raw_value.is_none() { + return Ok(None); + } + seed.deserialize(RawKeyDeserializer).map(Some) + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: de::DeserializeSeed<'de>, + { + seed.deserialize(BorrowedStrDeserializer::new(self.raw_value.take().unwrap())) } } diff --git a/src/read.rs b/src/read.rs index c94f984b8..9b1efa193 100644 --- a/src/read.rs +++ b/src/read.rs @@ -13,7 +13,8 @@ use serde::de::Visitor; use iter::LineColIterator; -use super::error::{Error, ErrorCode, Result}; +use error::{Error, ErrorCode, Result}; +use raw::{BorrowedRawDeserializer, OwnedRawDeserializer}; /// Trait used by the deserializer for iterating over input. This is manually /// "specialized" for iterating over &[u8]. Once feature(specialization) is @@ -318,7 +319,7 @@ where { let raw = self.raw_buffer.take().unwrap(); let raw = String::from_utf8(raw).unwrap(); - visitor.visit_string(raw) + visitor.visit_map(OwnedRawDeserializer { raw_value: Some(raw) }) } } @@ -495,7 +496,7 @@ impl<'a> Read<'a> for SliceRead<'a> { { let raw = &self.slice[self.raw_buffering_start_index..self.index]; let raw = str::from_utf8(raw).unwrap(); - visitor.visit_borrowed_str(raw) + visitor.visit_map(BorrowedRawDeserializer { raw_value: Some(raw) }) } } @@ -569,7 +570,7 @@ impl<'a> Read<'a> for StrRead<'a> { V: Visitor<'a>, { let raw = &self.data[self.delegate.raw_buffering_start_index..self.delegate.index]; - visitor.visit_borrowed_str(raw) + visitor.visit_map(BorrowedRawDeserializer { raw_value: Some(raw) }) } } diff --git a/src/ser.rs b/src/ser.rs index af53c8cae..7994eb001 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -283,14 +283,10 @@ where /// Serialize newtypes without an object wrapper. #[inline] - fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result<()> + fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result<()> where T: ser::Serialize, { - if name == ::raw::SERDE_STRUCT_NAME { - return value.serialize(RawValueStrEmitter(self)); - } - value.serialize(self) } @@ -464,6 +460,7 @@ where match name { #[cfg(feature = "arbitrary_precision")] ::number::SERDE_STRUCT_NAME => Ok(Compound::Number { ser: self }), + ::raw::SERDE_STRUCT_NAME => Ok(Compound::RawValue { ser: self }), _ => self.serialize_map(Some(len)), } } @@ -574,6 +571,7 @@ pub enum Compound<'a, W: 'a, F: 'a> { }, #[cfg(feature = "arbitrary_precision")] Number { ser: &'a mut Serializer }, + RawValue { ser: &'a mut Serializer }, } impl<'a, W, F> ser::SerializeSeq for Compound<'a, W, F> @@ -610,6 +608,7 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + Compound::RawValue { .. } => unreachable!(), } } @@ -625,6 +624,7 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + Compound::RawValue { .. } => unreachable!(), } } } @@ -707,6 +707,7 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + Compound::RawValue { .. } => unreachable!(), } } } @@ -747,6 +748,7 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + Compound::RawValue { .. } => unreachable!(), } } @@ -772,6 +774,7 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + Compound::RawValue { .. } => unreachable!(), } } @@ -787,6 +790,7 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + Compound::RawValue { .. } => unreachable!(), } } } @@ -818,6 +822,14 @@ where Err(invalid_number()) } } + Compound::RawValue { ref mut ser, .. } => { + if key == ::raw::SERDE_STRUCT_FIELD_NAME { + try!(value.serialize(RawValueStrEmitter(&mut *ser))); + Ok(()) + } else { + Err(invalid_raw_value()) + } + } } } @@ -827,6 +839,7 @@ where Compound::Map { .. } => ser::SerializeMap::end(self), #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => Ok(()), + Compound::RawValue { .. } => Ok(()), } } } @@ -848,6 +861,7 @@ where Compound::Map { .. } => ser::SerializeStruct::serialize_field(self, key, value), #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + Compound::RawValue { .. } => unreachable!(), } } @@ -869,6 +883,7 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + Compound::RawValue { .. } => unreachable!(), } } } @@ -882,6 +897,10 @@ fn invalid_number() -> Error { Error::syntax(ErrorCode::InvalidNumber, 0, 0) } +fn invalid_raw_value() -> Error { + Error::syntax(ErrorCode::ExpectedSomeValue, 0, 0) +} + fn key_must_be_a_string() -> Error { Error::syntax(ErrorCode::KeyMustBeAString, 0, 0) } @@ -1928,7 +1947,7 @@ pub trait Formatter { Ok(()) } - /// Writes a raw json fragment that doesn't need any escaping to the + /// Writes a raw JSON fragment that doesn't need any escaping to the /// specified writer. #[inline] fn write_raw_fragment(&mut self, writer: &mut W, fragment: &str) -> io::Result<()> diff --git a/src/value/de.rs b/src/value/de.rs index 73dfb8bce..cff31b552 100644 --- a/src/value/de.rs +++ b/src/value/de.rs @@ -116,7 +116,11 @@ impl<'de> Deserialize<'de> for Value { #[cfg(feature = "arbitrary_precision")] Some(KeyClass::Number) => { let number: NumberFromString = visitor.next_value()?; - return Ok(Value::Number(number.value)); + Ok(Value::Number(number.value)) + } + Some(KeyClass::RawValue) => { + let value = visitor.next_value_seed(::raw::RawValueFromString)?; + ::from_str(value.as_ref()).map_err(de::Error::custom) } Some(KeyClass::Map(first_key)) => { let mut values = Map::new(); @@ -307,7 +311,9 @@ impl<'de> serde::Deserializer<'de> for Value { V: Visitor<'de>, { if name == ::raw::SERDE_STRUCT_NAME { - return visitor.visit_string(self.to_string()); + return visitor.visit_map(::raw::OwnedRawDeserializer { + raw_value: Some(self.to_string()), + }); } visitor.visit_newtype_struct(self) @@ -833,12 +839,18 @@ impl<'de> serde::Deserializer<'de> for &'de Value { #[inline] fn deserialize_newtype_struct( self, - _name: &'static str, + name: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { + if name == ::raw::SERDE_STRUCT_NAME { + return visitor.visit_map(::raw::OwnedRawDeserializer { + raw_value: Some(self.to_string()), + }); + } + visitor.visit_newtype_struct(self) } @@ -1296,6 +1308,7 @@ enum KeyClass { Map(String), #[cfg(feature = "arbitrary_precision")] Number, + RawValue, } impl<'de> DeserializeSeed<'de> for KeyClassifier { @@ -1323,6 +1336,7 @@ impl<'de> Visitor<'de> for KeyClassifier { match s { #[cfg(feature = "arbitrary_precision")] ::number::SERDE_STRUCT_FIELD_NAME => Ok(KeyClass::Number), + ::raw::SERDE_STRUCT_FIELD_NAME => Ok(KeyClass::RawValue), _ => Ok(KeyClass::Map(s.to_owned())), } } @@ -1334,6 +1348,7 @@ impl<'de> Visitor<'de> for KeyClassifier { match s.as_str() { #[cfg(feature = "arbitrary_precision")] ::number::SERDE_STRUCT_FIELD_NAME => Ok(KeyClass::Number), + ::raw::SERDE_STRUCT_FIELD_NAME => Ok(KeyClass::RawValue), _ => Ok(KeyClass::Map(s)), } } diff --git a/src/value/ser.rs b/src/value/ser.rs index 54ce18db8..d120e6deb 100644 --- a/src/value/ser.rs +++ b/src/value/ser.rs @@ -147,16 +147,12 @@ impl serde::Serializer for Serializer { #[inline] fn serialize_newtype_struct( self, - name: &'static str, + _name: &'static str, value: &T, ) -> Result where T: Serialize, { - if name == ::raw::SERDE_STRUCT_NAME { - return value.serialize(RawValueEmitter); - } - value.serialize(self) } @@ -234,6 +230,7 @@ impl serde::Serializer for Serializer { match name { #[cfg(feature = "arbitrary_precision")] ::number::SERDE_STRUCT_NAME => Ok(SerializeMap::Number { out_value: None }), + ::raw::SERDE_STRUCT_NAME => Ok(SerializeMap::RawValue { out_value: None }), _ => self.serialize_map(Some(len)), } } @@ -268,6 +265,7 @@ pub enum SerializeMap { }, #[cfg(feature = "arbitrary_precision")] Number { out_value: Option }, + RawValue { out_value: Option }, } pub struct SerializeStructVariant { @@ -362,6 +360,7 @@ impl serde::ser::SerializeMap for SerializeMap { } #[cfg(feature = "arbitrary_precision")] SerializeMap::Number { .. } => unreachable!(), + SerializeMap::RawValue { .. } => unreachable!(), } } @@ -383,6 +382,7 @@ impl serde::ser::SerializeMap for SerializeMap { } #[cfg(feature = "arbitrary_precision")] SerializeMap::Number { .. } => unreachable!(), + SerializeMap::RawValue { .. } => unreachable!(), } } @@ -391,6 +391,7 @@ impl serde::ser::SerializeMap for SerializeMap { SerializeMap::Map { map, .. } => Ok(Value::Object(map)), #[cfg(feature = "arbitrary_precision")] SerializeMap::Number { .. } => unreachable!(), + SerializeMap::RawValue { .. } => unreachable!(), } } } @@ -600,6 +601,14 @@ impl serde::ser::SerializeStruct for SerializeMap { Err(invalid_number()) } } + SerializeMap::RawValue { ref mut out_value } => { + if key == ::raw::SERDE_STRUCT_FIELD_NAME { + *out_value = Some(value.serialize(RawValueEmitter)?); + Ok(()) + } else { + Err(invalid_raw_value()) + } + } } } @@ -610,6 +619,9 @@ impl serde::ser::SerializeStruct for SerializeMap { SerializeMap::Number { out_value, .. } => { Ok(out_value.expect("number value was not emitted")) } + SerializeMap::RawValue { out_value, .. } => { + Ok(out_value.expect("raw value was not emitted")) + } } } } @@ -816,6 +828,10 @@ impl ser::Serializer for NumberValueEmitter { struct RawValueEmitter; +fn invalid_raw_value() -> Error { + Error::syntax(ErrorCode::ExpectedSomeValue, 0, 0) +} + impl ser::Serializer for RawValueEmitter { type Ok = Value; type Error = Error; @@ -829,63 +845,51 @@ impl ser::Serializer for RawValueEmitter { type SerializeStructVariant = Impossible; fn serialize_bool(self, _v: bool) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_i8(self, _v: i8) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_i16(self, _v: i16) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_i32(self, _v: i32) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_i64(self, _v: i64) -> Result { - Err(ser::Error::custom("expected RawValue")) - } - - serde_if_integer128! { - fn serialize_i128(self, _v: i128) -> Result { - Err(ser::Error::custom("expected RawValue")) - } + Err(invalid_raw_value()) } fn serialize_u8(self, _v: u8) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_u16(self, _v: u16) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_u32(self, _v: u32) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_u64(self, _v: u64) -> Result { - Err(ser::Error::custom("expected RawValue")) - } - - serde_if_integer128! { - fn serialize_u128(self, _v: u128) -> Result { - Err(ser::Error::custom("expected RawValue")) - } + Err(invalid_raw_value()) } fn serialize_f32(self, _v: f32) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_f64(self, _v: f64) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_char(self, _v: char) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_str(self, value: &str) -> Result { @@ -893,26 +897,26 @@ impl ser::Serializer for RawValueEmitter { } fn serialize_bytes(self, _value: &[u8]) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_none(self) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_some(self, _value: &T) -> Result where T: Serialize, { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_unit(self) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_unit_struct(self, _name: &'static str) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_unit_variant( @@ -921,7 +925,7 @@ impl ser::Serializer for RawValueEmitter { _variant_index: u32, _variant: &'static str, ) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_newtype_struct( @@ -932,7 +936,7 @@ impl ser::Serializer for RawValueEmitter { where T: Serialize, { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_newtype_variant( @@ -945,15 +949,15 @@ impl ser::Serializer for RawValueEmitter { where T: Serialize, { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_seq(self, _len: Option) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_tuple(self, _len: usize) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_tuple_struct( @@ -961,7 +965,7 @@ impl ser::Serializer for RawValueEmitter { _name: &'static str, _len: usize, ) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_tuple_variant( @@ -971,11 +975,11 @@ impl ser::Serializer for RawValueEmitter { _variant: &'static str, _len: usize, ) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_map(self, _len: Option) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_struct( @@ -983,7 +987,7 @@ impl ser::Serializer for RawValueEmitter { _name: &'static str, _len: usize, ) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } fn serialize_struct_variant( @@ -993,6 +997,6 @@ impl ser::Serializer for RawValueEmitter { _variant: &'static str, _len: usize, ) -> Result { - Err(ser::Error::custom("expected RawValue")) + Err(invalid_raw_value()) } } From f96b59d6b341cac9aa580fdfe7fee6bcc0c1bd11 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 16 Sep 2018 20:28:42 -0700 Subject: [PATCH 05/17] Cfg gate everything having to do with RawValue --- Cargo.toml | 3 +++ src/de.rs | 9 +++++++-- src/lib.rs | 10 ++++++++-- src/read.rs | 37 +++++++++++++++++++++++++++++++++---- src/ser.rs | 15 +++++++++++++++ src/value/de.rs | 28 ++++++++++++++++++++-------- src/value/mod.rs | 2 ++ src/value/ser.rs | 10 ++++++++++ tests/test.rs | 5 ++++- 9 files changed, 102 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2f8ebe5ca..8135c15e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,3 +41,6 @@ preserve_order = ["indexmap"] # allows JSON numbers of arbitrary size/precision to be read into a Number and # written back to a JSON string without loss of precision. arbitrary_precision = [] + +# Provide a RawValue type that can hold unprocessed JSON during deserialization. +raw_value = [] diff --git a/src/de.rs b/src/de.rs index 0e8fbe584..fa4454714 100644 --- a/src/de.rs +++ b/src/de.rs @@ -947,6 +947,7 @@ impl<'de, R: Read<'de>> Deserializer { } } + #[cfg(feature = "raw_value")] fn deserialize_raw_value(&mut self, visitor: V) -> Result where V: de::Visitor<'de>, @@ -1426,10 +1427,14 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { where V: de::Visitor<'de>, { - if name == ::raw::SERDE_STRUCT_NAME { - return self.deserialize_raw_value(visitor); + #[cfg(feature = "raw_value")] + { + if name == ::raw::SERDE_STRUCT_NAME { + return self.deserialize_raw_value(visitor); + } } + let _ = name; visitor.visit_newtype_struct(self) } diff --git a/src/lib.rs b/src/lib.rs index e0b7a0b77..001109495 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -364,7 +364,11 @@ pub use self::ser::{ to_string, to_string_pretty, to_vec, to_vec_pretty, to_writer, to_writer_pretty, Serializer, }; #[doc(inline)] -pub use self::value::{from_value, to_value, Map, Number, RawValue, Value}; +pub use self::value::{from_value, to_value, Map, Number, Value}; + +#[cfg(feature = "raw_value")] +#[doc(inline)] +pub use self::value::RawValue; // We only use our own error type; no need for From conversions provided by the // standard library's try! macro. This reduces lines of LLVM IR by 4%. @@ -388,5 +392,7 @@ pub mod value; mod iter; mod number; -mod raw; mod read; + +#[cfg(feature = "raw_value")] +mod raw; diff --git a/src/read.rs b/src/read.rs index 9b1efa193..bd181e8de 100644 --- a/src/read.rs +++ b/src/read.rs @@ -9,11 +9,14 @@ use std::ops::Deref; use std::{char, cmp, io, str}; +#[cfg(feature = "raw_value")] use serde::de::Visitor; use iter::LineColIterator; use error::{Error, ErrorCode, Result}; + +#[cfg(feature = "raw_value")] use raw::{BorrowedRawDeserializer, OwnedRawDeserializer}; /// Trait used by the deserializer for iterating over input. This is manually @@ -83,11 +86,13 @@ pub trait Read<'de>: private::Sealed { /// Switch raw buffering mode on. /// /// This is used when deserializing `RawValue`. + #[cfg(feature = "raw_value")] #[doc(hidden)] fn begin_raw_buffering(&mut self); /// Switch raw buffering mode off and provides the raw buffered data to the /// given visitor. + #[cfg(feature = "raw_value")] #[doc(hidden)] fn end_raw_buffering(&mut self, visitor: V) -> Result where @@ -123,6 +128,7 @@ where iter: LineColIterator>, /// Temporary storage of peeked byte. ch: Option, + #[cfg(feature = "raw_value")] raw_buffer: Option>, } @@ -134,6 +140,7 @@ pub struct SliceRead<'a> { slice: &'a [u8], /// Index of the *next* byte that will be returned by next() or peek(). index: usize, + #[cfg(feature = "raw_value")] raw_buffering_start_index: usize, } @@ -142,6 +149,7 @@ pub struct SliceRead<'a> { // Able to elide UTF-8 checks by assuming that the input is valid UTF-8. pub struct StrRead<'a> { delegate: SliceRead<'a>, + #[cfg(feature = "raw_value")] data: &'a str, } @@ -161,6 +169,7 @@ where IoRead { iter: LineColIterator::new(reader.bytes()), ch: None, + #[cfg(feature = "raw_value")] raw_buffer: None, } } @@ -214,16 +223,22 @@ where fn next(&mut self) -> io::Result> { match self.ch.take() { Some(ch) => { - if let Some(ref mut buf) = self.raw_buffer { - buf.push(ch); + #[cfg(feature = "raw_value")] + { + if let Some(ref mut buf) = self.raw_buffer { + buf.push(ch); + } } Ok(Some(ch)) } None => match self.iter.next() { Some(Err(err)) => Err(err), Some(Ok(ch)) => { - if let Some(ref mut buf) = self.raw_buffer { - buf.push(ch); + #[cfg(feature = "raw_value")] + { + if let Some(ref mut buf) = self.raw_buffer { + buf.push(ch); + } } Ok(Some(ch)) } @@ -247,7 +262,13 @@ where } } + #[cfg(not(feature = "raw_value"))] #[inline] + fn discard(&mut self) { + self.ch = None; + } + + #[cfg(feature = "raw_value")] fn discard(&mut self) { if let Some(ch) = self.ch.take() { if let Some(ref mut buf) = self.raw_buffer { @@ -309,10 +330,12 @@ where } } + #[cfg(feature = "raw_value")] fn begin_raw_buffering(&mut self) { self.raw_buffer = Some(Vec::new()); } + #[cfg(feature = "raw_value")] fn end_raw_buffering(&mut self, visitor: V) -> Result where V: Visitor<'de>, @@ -331,6 +354,7 @@ impl<'a> SliceRead<'a> { SliceRead { slice: slice, index: 0, + #[cfg(feature = "raw_value")] raw_buffering_start_index: 0, } } @@ -486,10 +510,12 @@ impl<'a> Read<'a> for SliceRead<'a> { } } + #[cfg(feature = "raw_value")] fn begin_raw_buffering(&mut self) { self.raw_buffering_start_index = self.index; } + #[cfg(feature = "raw_value")] fn end_raw_buffering(&mut self, visitor: V) -> Result where V: Visitor<'a>, @@ -507,6 +533,7 @@ impl<'a> StrRead<'a> { pub fn new(s: &'a str) -> Self { StrRead { delegate: SliceRead::new(s.as_bytes()), + #[cfg(feature = "raw_value")] data: s, } } @@ -561,10 +588,12 @@ impl<'a> Read<'a> for StrRead<'a> { self.delegate.ignore_str() } + #[cfg(feature = "raw_value")] fn begin_raw_buffering(&mut self) { self.delegate.begin_raw_buffering() } + #[cfg(feature = "raw_value")] fn end_raw_buffering(&mut self, visitor: V) -> Result where V: Visitor<'a>, diff --git a/src/ser.rs b/src/ser.rs index 7994eb001..fdf30d287 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -460,6 +460,7 @@ where match name { #[cfg(feature = "arbitrary_precision")] ::number::SERDE_STRUCT_NAME => Ok(Compound::Number { ser: self }), + #[cfg(feature = "raw_value")] ::raw::SERDE_STRUCT_NAME => Ok(Compound::RawValue { ser: self }), _ => self.serialize_map(Some(len)), } @@ -571,6 +572,7 @@ pub enum Compound<'a, W: 'a, F: 'a> { }, #[cfg(feature = "arbitrary_precision")] Number { ser: &'a mut Serializer }, + #[cfg(feature = "raw_value")] RawValue { ser: &'a mut Serializer }, } @@ -608,6 +610,7 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] Compound::RawValue { .. } => unreachable!(), } } @@ -624,6 +627,7 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] Compound::RawValue { .. } => unreachable!(), } } @@ -707,6 +711,7 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] Compound::RawValue { .. } => unreachable!(), } } @@ -748,6 +753,7 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] Compound::RawValue { .. } => unreachable!(), } } @@ -774,6 +780,7 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] Compound::RawValue { .. } => unreachable!(), } } @@ -790,6 +797,7 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] Compound::RawValue { .. } => unreachable!(), } } @@ -822,6 +830,7 @@ where Err(invalid_number()) } } + #[cfg(feature = "raw_value")] Compound::RawValue { ref mut ser, .. } => { if key == ::raw::SERDE_STRUCT_FIELD_NAME { try!(value.serialize(RawValueStrEmitter(&mut *ser))); @@ -839,6 +848,7 @@ where Compound::Map { .. } => ser::SerializeMap::end(self), #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => Ok(()), + #[cfg(feature = "raw_value")] Compound::RawValue { .. } => Ok(()), } } @@ -861,6 +871,7 @@ where Compound::Map { .. } => ser::SerializeStruct::serialize_field(self, key, value), #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] Compound::RawValue { .. } => unreachable!(), } } @@ -883,6 +894,7 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] Compound::RawValue { .. } => unreachable!(), } } @@ -897,6 +909,7 @@ fn invalid_number() -> Error { Error::syntax(ErrorCode::InvalidNumber, 0, 0) } +#[cfg(feature = "raw_value")] fn invalid_raw_value() -> Error { Error::syntax(ErrorCode::ExpectedSomeValue, 0, 0) } @@ -1420,8 +1433,10 @@ impl<'a, W: io::Write, F: Formatter> ser::Serializer for NumberStrEmitter<'a, W, } } +#[cfg(feature = "raw_value")] struct RawValueStrEmitter<'a, W: 'a + io::Write, F: 'a + Formatter>(&'a mut Serializer); +#[cfg(feature = "raw_value")] impl<'a, W: io::Write, F: Formatter> ser::Serializer for RawValueStrEmitter<'a, W, F> { type Ok = (); type Error = Error; diff --git a/src/value/de.rs b/src/value/de.rs index cff31b552..6f5d2a060 100644 --- a/src/value/de.rs +++ b/src/value/de.rs @@ -118,6 +118,7 @@ impl<'de> Deserialize<'de> for Value { let number: NumberFromString = visitor.next_value()?; Ok(Value::Number(number.value)) } + #[cfg(feature = "raw_value")] Some(KeyClass::RawValue) => { let value = visitor.next_value_seed(::raw::RawValueFromString)?; ::from_str(value.as_ref()).map_err(de::Error::custom) @@ -310,12 +311,16 @@ impl<'de> serde::Deserializer<'de> for Value { where V: Visitor<'de>, { - if name == ::raw::SERDE_STRUCT_NAME { - return visitor.visit_map(::raw::OwnedRawDeserializer { - raw_value: Some(self.to_string()), - }); + #[cfg(feature = "raw_value")] + { + if name == ::raw::SERDE_STRUCT_NAME { + return visitor.visit_map(::raw::OwnedRawDeserializer { + raw_value: Some(self.to_string()), + }); + } } + let _ = name; visitor.visit_newtype_struct(self) } @@ -845,12 +850,16 @@ impl<'de> serde::Deserializer<'de> for &'de Value { where V: Visitor<'de>, { - if name == ::raw::SERDE_STRUCT_NAME { - return visitor.visit_map(::raw::OwnedRawDeserializer { - raw_value: Some(self.to_string()), - }); + #[cfg(feature = "raw_value")] + { + if name == ::raw::SERDE_STRUCT_NAME { + return visitor.visit_map(::raw::OwnedRawDeserializer { + raw_value: Some(self.to_string()), + }); + } } + let _ = name; visitor.visit_newtype_struct(self) } @@ -1308,6 +1317,7 @@ enum KeyClass { Map(String), #[cfg(feature = "arbitrary_precision")] Number, + #[cfg(feature = "raw_value")] RawValue, } @@ -1336,6 +1346,7 @@ impl<'de> Visitor<'de> for KeyClassifier { match s { #[cfg(feature = "arbitrary_precision")] ::number::SERDE_STRUCT_FIELD_NAME => Ok(KeyClass::Number), + #[cfg(feature = "raw_value")] ::raw::SERDE_STRUCT_FIELD_NAME => Ok(KeyClass::RawValue), _ => Ok(KeyClass::Map(s.to_owned())), } @@ -1348,6 +1359,7 @@ impl<'de> Visitor<'de> for KeyClassifier { match s.as_str() { #[cfg(feature = "arbitrary_precision")] ::number::SERDE_STRUCT_FIELD_NAME => Ok(KeyClass::Number), + #[cfg(feature = "raw_value")] ::raw::SERDE_STRUCT_FIELD_NAME => Ok(KeyClass::RawValue), _ => Ok(KeyClass::Map(s)), } diff --git a/src/value/mod.rs b/src/value/mod.rs index 155874a9c..c976af501 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -118,6 +118,8 @@ use serde::ser::Serialize; use error::Error; pub use map::Map; pub use number::Number; + +#[cfg(feature = "raw_value")] pub use raw::RawValue; pub use self::index::Index; diff --git a/src/value/ser.rs b/src/value/ser.rs index d120e6deb..f18a5cc0d 100644 --- a/src/value/ser.rs +++ b/src/value/ser.rs @@ -230,6 +230,7 @@ impl serde::Serializer for Serializer { match name { #[cfg(feature = "arbitrary_precision")] ::number::SERDE_STRUCT_NAME => Ok(SerializeMap::Number { out_value: None }), + #[cfg(feature = "raw_value")] ::raw::SERDE_STRUCT_NAME => Ok(SerializeMap::RawValue { out_value: None }), _ => self.serialize_map(Some(len)), } @@ -265,6 +266,7 @@ pub enum SerializeMap { }, #[cfg(feature = "arbitrary_precision")] Number { out_value: Option }, + #[cfg(feature = "raw_value")] RawValue { out_value: Option }, } @@ -360,6 +362,7 @@ impl serde::ser::SerializeMap for SerializeMap { } #[cfg(feature = "arbitrary_precision")] SerializeMap::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] SerializeMap::RawValue { .. } => unreachable!(), } } @@ -382,6 +385,7 @@ impl serde::ser::SerializeMap for SerializeMap { } #[cfg(feature = "arbitrary_precision")] SerializeMap::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] SerializeMap::RawValue { .. } => unreachable!(), } } @@ -391,6 +395,7 @@ impl serde::ser::SerializeMap for SerializeMap { SerializeMap::Map { map, .. } => Ok(Value::Object(map)), #[cfg(feature = "arbitrary_precision")] SerializeMap::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] SerializeMap::RawValue { .. } => unreachable!(), } } @@ -601,6 +606,7 @@ impl serde::ser::SerializeStruct for SerializeMap { Err(invalid_number()) } } + #[cfg(feature = "raw_value")] SerializeMap::RawValue { ref mut out_value } => { if key == ::raw::SERDE_STRUCT_FIELD_NAME { *out_value = Some(value.serialize(RawValueEmitter)?); @@ -619,6 +625,7 @@ impl serde::ser::SerializeStruct for SerializeMap { SerializeMap::Number { out_value, .. } => { Ok(out_value.expect("number value was not emitted")) } + #[cfg(feature = "raw_value")] SerializeMap::RawValue { out_value, .. } => { Ok(out_value.expect("raw value was not emitted")) } @@ -826,12 +833,15 @@ impl ser::Serializer for NumberValueEmitter { } } +#[cfg(feature = "raw_value")] struct RawValueEmitter; +#[cfg(feature = "raw_value")] fn invalid_raw_value() -> Error { Error::syntax(ErrorCode::ExpectedSomeValue, 0, 0) } +#[cfg(feature = "raw_value")] impl ser::Serializer for RawValueEmitter { type Ok = Value; type Error = Error; diff --git a/tests/test.rs b/tests/test.rs index 09c51a62d..cc2c206c6 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -44,7 +44,7 @@ use serde_bytes::{ByteBuf, Bytes}; use serde_json::{ from_reader, from_slice, from_str, from_value, to_string, to_string_pretty, to_value, to_vec, - to_writer, Deserializer, Number, RawValue, Value, + to_writer, Deserializer, Number, Value, }; macro_rules! treemap { @@ -2040,8 +2040,11 @@ fn test_integer128() { ]); } +#[cfg(feature = "raw_value")] #[test] fn test_raw_value() { + use serde_json::RawValue; + #[derive(Serialize, Deserialize)] struct Wrapper<'a> { a: i8, From 9d5fd8f31c9f979c62a6d62cd15daec725c049a3 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 16 Sep 2018 20:40:14 -0700 Subject: [PATCH 06/17] Fix up some unused import warnings --- src/ser.rs | 40 ++++++++++++++++++++-------------------- src/value/ser.rs | 6 +++--- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/ser.rs b/src/ser.rs index fdf30d287..04eeddb08 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -285,7 +285,7 @@ where #[inline] fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { value.serialize(self) } @@ -299,7 +299,7 @@ where value: &T, ) -> Result<()> where - T: ser::Serialize, + T: Serialize, { try!( self.formatter @@ -344,7 +344,7 @@ where #[inline] fn serialize_some(self, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { value.serialize(self) } @@ -587,7 +587,7 @@ where #[inline] fn serialize_element(&mut self, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { match *self { Compound::Map { @@ -644,7 +644,7 @@ where #[inline] fn serialize_element(&mut self, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { ser::SerializeSeq::serialize_element(self, value) } @@ -666,7 +666,7 @@ where #[inline] fn serialize_field(&mut self, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { ser::SerializeSeq::serialize_element(self, value) } @@ -688,7 +688,7 @@ where #[inline] fn serialize_field(&mut self, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { ser::SerializeSeq::serialize_element(self, value) } @@ -728,7 +728,7 @@ where #[inline] fn serialize_key(&mut self, key: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { match *self { Compound::Map { @@ -761,7 +761,7 @@ where #[inline] fn serialize_value(&mut self, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { match *self { Compound::Map { ref mut ser, .. } => { @@ -814,7 +814,7 @@ where #[inline] fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { match *self { Compound::Map { .. } => { @@ -865,7 +865,7 @@ where #[inline] fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { match *self { Compound::Map { .. } => ser::SerializeStruct::serialize_field(self, key, value), @@ -944,7 +944,7 @@ where #[inline] fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { value.serialize(self) } @@ -1187,7 +1187,7 @@ where _value: &T, ) -> Result<()> where - T: ser::Serialize, + T: Serialize, { Err(key_must_be_a_string()) } @@ -1198,7 +1198,7 @@ where fn serialize_some(self, _value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { Err(key_must_be_a_string()) } @@ -2207,7 +2207,7 @@ static ESCAPE: [u8; 256] = [ pub fn to_writer(writer: W, value: &T) -> Result<()> where W: io::Write, - T: ser::Serialize, + T: Serialize, { let mut ser = Serializer::new(writer); try!(value.serialize(&mut ser)); @@ -2225,7 +2225,7 @@ where pub fn to_writer_pretty(writer: W, value: &T) -> Result<()> where W: io::Write, - T: ser::Serialize, + T: Serialize, { let mut ser = Serializer::pretty(writer); try!(value.serialize(&mut ser)); @@ -2241,7 +2241,7 @@ where #[inline] pub fn to_vec(value: &T) -> Result> where - T: ser::Serialize, + T: Serialize, { let mut writer = Vec::with_capacity(128); try!(to_writer(&mut writer, value)); @@ -2257,7 +2257,7 @@ where #[inline] pub fn to_vec_pretty(value: &T) -> Result> where - T: ser::Serialize, + T: Serialize, { let mut writer = Vec::with_capacity(128); try!(to_writer_pretty(&mut writer, value)); @@ -2273,7 +2273,7 @@ where #[inline] pub fn to_string(value: &T) -> Result where - T: ser::Serialize, + T: Serialize, { let vec = try!(to_vec(value)); let string = unsafe { @@ -2292,7 +2292,7 @@ where #[inline] pub fn to_string_pretty(value: &T) -> Result where - T: ser::Serialize, + T: Serialize, { let vec = try!(to_vec_pretty(value)); let string = unsafe { diff --git a/src/value/ser.rs b/src/value/ser.rs index f18a5cc0d..48dbafeae 100644 --- a/src/value/ser.rs +++ b/src/value/ser.rs @@ -6,7 +6,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use serde::ser::{self, Impossible}; +use serde::ser::Impossible; use serde::{self, Serialize}; use error::{Error, ErrorCode}; @@ -663,7 +663,7 @@ fn invalid_number() -> Error { } #[cfg(feature = "arbitrary_precision")] -impl ser::Serializer for NumberValueEmitter { +impl serde::ser::Serializer for NumberValueEmitter { type Ok = Value; type Error = Error; @@ -842,7 +842,7 @@ fn invalid_raw_value() -> Error { } #[cfg(feature = "raw_value")] -impl ser::Serializer for RawValueEmitter { +impl serde::ser::Serializer for RawValueEmitter { type Ok = Value; type Error = Error; From ce10d5e49440acd91900284fef45f39f261e0cf5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 16 Sep 2018 20:44:06 -0700 Subject: [PATCH 07/17] Remove PartialEq from RawValue Unclear in what situations comparing RawValues for equality would be meaningful. --- src/raw.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raw.rs b/src/raw.rs index 068d3fe3e..87e06be1f 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -18,7 +18,7 @@ use error::Error; /// When deserializing, this type can not be used with the `#[serde(flatten)]` attribute, /// as it relies on the original input buffer. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone)] pub struct RawValue<'a>(Cow<'a, str>); impl<'a> AsRef for RawValue<'a> { From c736bd7707545a8c2df522f576b3494629678843 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 16 Sep 2018 20:48:36 -0700 Subject: [PATCH 08/17] Handwrite Debug for RawValue to minimize escaping Before: RawValue("{\"k\":\"v\"}") After: RawValue({"k":"v"}) --- src/raw.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/raw.rs b/src/raw.rs index 87e06be1f..4f7a489f1 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -1,5 +1,5 @@ use std::borrow::Cow; -use std::fmt; +use std::fmt::{self, Debug}; use serde::ser::{Serialize, Serializer, SerializeStruct}; use serde::de::{self, Deserialize, Deserializer, DeserializeSeed, IntoDeserializer, MapAccess, Unexpected, Visitor}; @@ -18,9 +18,18 @@ use error::Error; /// When deserializing, this type can not be used with the `#[serde(flatten)]` attribute, /// as it relies on the original input buffer. -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct RawValue<'a>(Cow<'a, str>); +impl<'a> Debug for RawValue<'a> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter + .debug_tuple("RawValue") + .field(&format_args!("{}", self.0)) + .finish() + } +} + impl<'a> AsRef for RawValue<'a> { fn as_ref(&self) -> &str { &self.0 From 0a811b8fae882e12f8cadc65829f817f10bac532 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 16 Sep 2018 20:51:27 -0700 Subject: [PATCH 09/17] Name the RawValue private field --- src/raw.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/raw.rs b/src/raw.rs index 4f7a489f1..66fe1aa70 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -19,26 +19,28 @@ use error::Error; /// as it relies on the original input buffer. #[derive(Clone)] -pub struct RawValue<'a>(Cow<'a, str>); +pub struct RawValue<'a> { + cow: Cow<'a, str>, +} impl<'a> Debug for RawValue<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter .debug_tuple("RawValue") - .field(&format_args!("{}", self.0)) + .field(&format_args!("{}", self.cow)) .finish() } } impl<'a> AsRef for RawValue<'a> { fn as_ref(&self) -> &str { - &self.0 + &self.cow } } impl<'a> fmt::Display for RawValue<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(&self.0) + f.write_str(&self.cow) } } @@ -52,7 +54,7 @@ impl<'a> Serialize for RawValue<'a> { S: Serializer, { let mut s = serializer.serialize_struct(SERDE_STRUCT_NAME, 1)?; - s.serialize_field(SERDE_STRUCT_FIELD_NAME, &self.0)?; + s.serialize_field(SERDE_STRUCT_FIELD_NAME, &self.cow)?; s.end() } } @@ -145,14 +147,14 @@ impl<'de> Visitor<'de> for RawValueFromString { where E: de::Error, { - Ok(RawValue(Cow::Borrowed(s))) + Ok(RawValue { cow: Cow::Borrowed(s) }) } fn visit_string(self, s: String) -> Result where E: de::Error, { - Ok(RawValue(Cow::Owned(s))) + Ok(RawValue { cow: Cow::Owned(s) }) } } From 533b6320e2a111089a674afd9e3a1b54bf9876ac Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 16 Sep 2018 20:55:16 -0700 Subject: [PATCH 10/17] Simplify naming of private tokens --- src/de.rs | 2 +- src/number.rs | 15 +++++---------- src/raw.rs | 13 ++++++------- src/ser.rs | 8 ++++---- src/value/de.rs | 12 ++++++------ src/value/ser.rs | 8 ++++---- 6 files changed, 26 insertions(+), 32 deletions(-) diff --git a/src/de.rs b/src/de.rs index fa4454714..7e44968e2 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1429,7 +1429,7 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { { #[cfg(feature = "raw_value")] { - if name == ::raw::SERDE_STRUCT_NAME { + if name == ::raw::TOKEN { return self.deserialize_raw_value(visitor); } } diff --git a/src/number.rs b/src/number.rs index cc6bccb6c..fcf98ee78 100644 --- a/src/number.rs +++ b/src/number.rs @@ -26,12 +26,7 @@ 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"; +pub const TOKEN: &'static str = "$serde_json::private::Number"; /// Represents a JSON number, whether integer or floating point. #[derive(Clone, PartialEq)] @@ -346,8 +341,8 @@ impl Serialize for Number { { use serde::ser::SerializeStruct; - let mut s = serializer.serialize_struct(SERDE_STRUCT_NAME, 1)?; - s.serialize_field(SERDE_STRUCT_FIELD_NAME, &self.n)?; + let mut s = serializer.serialize_struct(TOKEN, 1)?; + s.serialize_field(TOKEN, &self.n)?; s.end() } } @@ -426,7 +421,7 @@ impl<'de> de::Deserialize<'de> for NumberKey { where E: de::Error, { - if s == SERDE_STRUCT_FIELD_NAME { + if s == TOKEN { Ok(()) } else { Err(de::Error::custom("expected field with custom name")) @@ -638,7 +633,7 @@ impl<'de> Deserializer<'de> for NumberFieldDeserializer { where V: de::Visitor<'de>, { - visitor.visit_borrowed_str(SERDE_STRUCT_FIELD_NAME) + visitor.visit_borrowed_str(TOKEN) } forward_to_deserialize_any! { diff --git a/src/raw.rs b/src/raw.rs index 66fe1aa70..f2774e502 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -44,8 +44,7 @@ impl<'a> fmt::Display for RawValue<'a> { } } -pub const SERDE_STRUCT_NAME: &'static str = "$serde_json::RawValue"; -pub const SERDE_STRUCT_FIELD_NAME: &'static str = "$serde_json::RawValue::id"; +pub const TOKEN: &'static str = "$serde_json::private::RawValue"; impl<'a> Serialize for RawValue<'a> { #[inline] @@ -53,8 +52,8 @@ impl<'a> Serialize for RawValue<'a> { where S: Serializer, { - let mut s = serializer.serialize_struct(SERDE_STRUCT_NAME, 1)?; - s.serialize_field(SERDE_STRUCT_FIELD_NAME, &self.cow)?; + let mut s = serializer.serialize_struct(TOKEN, 1)?; + s.serialize_field(TOKEN, &self.cow)?; s.end() } } @@ -86,7 +85,7 @@ impl<'a, 'de: 'a> Deserialize<'de> for RawValue<'a> { } } - deserializer.deserialize_newtype_struct(SERDE_STRUCT_NAME, RawValueVisitor) + deserializer.deserialize_newtype_struct(TOKEN, RawValueVisitor) } } @@ -110,7 +109,7 @@ impl<'de> Deserialize<'de> for RawKey { where E: de::Error, { - if s == SERDE_STRUCT_FIELD_NAME { + if s == TOKEN { Ok(()) } else { Err(de::Error::custom("unexpected raw value")) @@ -167,7 +166,7 @@ impl<'de> Deserializer<'de> for RawKeyDeserializer { where V: de::Visitor<'de>, { - visitor.visit_borrowed_str(SERDE_STRUCT_FIELD_NAME) + visitor.visit_borrowed_str(TOKEN) } forward_to_deserialize_any! { diff --git a/src/ser.rs b/src/ser.rs index 04eeddb08..eceb4e6b4 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -459,9 +459,9 @@ where fn serialize_struct(self, name: &'static str, len: usize) -> Result { match name { #[cfg(feature = "arbitrary_precision")] - ::number::SERDE_STRUCT_NAME => Ok(Compound::Number { ser: self }), + ::number::TOKEN => Ok(Compound::Number { ser: self }), #[cfg(feature = "raw_value")] - ::raw::SERDE_STRUCT_NAME => Ok(Compound::RawValue { ser: self }), + ::raw::TOKEN => Ok(Compound::RawValue { ser: self }), _ => self.serialize_map(Some(len)), } } @@ -823,7 +823,7 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { ref mut ser, .. } => { - if key == ::number::SERDE_STRUCT_FIELD_NAME { + if key == ::number::TOKEN { try!(value.serialize(NumberStrEmitter(&mut *ser))); Ok(()) } else { @@ -832,7 +832,7 @@ where } #[cfg(feature = "raw_value")] Compound::RawValue { ref mut ser, .. } => { - if key == ::raw::SERDE_STRUCT_FIELD_NAME { + if key == ::raw::TOKEN { try!(value.serialize(RawValueStrEmitter(&mut *ser))); Ok(()) } else { diff --git a/src/value/de.rs b/src/value/de.rs index 6f5d2a060..1429713db 100644 --- a/src/value/de.rs +++ b/src/value/de.rs @@ -313,7 +313,7 @@ impl<'de> serde::Deserializer<'de> for Value { { #[cfg(feature = "raw_value")] { - if name == ::raw::SERDE_STRUCT_NAME { + if name == ::raw::TOKEN { return visitor.visit_map(::raw::OwnedRawDeserializer { raw_value: Some(self.to_string()), }); @@ -852,7 +852,7 @@ impl<'de> serde::Deserializer<'de> for &'de Value { { #[cfg(feature = "raw_value")] { - if name == ::raw::SERDE_STRUCT_NAME { + if name == ::raw::TOKEN { return visitor.visit_map(::raw::OwnedRawDeserializer { raw_value: Some(self.to_string()), }); @@ -1345,9 +1345,9 @@ impl<'de> Visitor<'de> for KeyClassifier { { match s { #[cfg(feature = "arbitrary_precision")] - ::number::SERDE_STRUCT_FIELD_NAME => Ok(KeyClass::Number), + ::number::TOKEN => Ok(KeyClass::Number), #[cfg(feature = "raw_value")] - ::raw::SERDE_STRUCT_FIELD_NAME => Ok(KeyClass::RawValue), + ::raw::TOKEN => Ok(KeyClass::RawValue), _ => Ok(KeyClass::Map(s.to_owned())), } } @@ -1358,9 +1358,9 @@ impl<'de> Visitor<'de> for KeyClassifier { { match s.as_str() { #[cfg(feature = "arbitrary_precision")] - ::number::SERDE_STRUCT_FIELD_NAME => Ok(KeyClass::Number), + ::number::TOKEN => Ok(KeyClass::Number), #[cfg(feature = "raw_value")] - ::raw::SERDE_STRUCT_FIELD_NAME => Ok(KeyClass::RawValue), + ::raw::TOKEN => Ok(KeyClass::RawValue), _ => Ok(KeyClass::Map(s)), } } diff --git a/src/value/ser.rs b/src/value/ser.rs index 48dbafeae..172784cce 100644 --- a/src/value/ser.rs +++ b/src/value/ser.rs @@ -229,9 +229,9 @@ impl serde::Serializer for Serializer { ) -> Result { match name { #[cfg(feature = "arbitrary_precision")] - ::number::SERDE_STRUCT_NAME => Ok(SerializeMap::Number { out_value: None }), + ::number::TOKEN => Ok(SerializeMap::Number { out_value: None }), #[cfg(feature = "raw_value")] - ::raw::SERDE_STRUCT_NAME => Ok(SerializeMap::RawValue { out_value: None }), + ::raw::TOKEN => Ok(SerializeMap::RawValue { out_value: None }), _ => self.serialize_map(Some(len)), } } @@ -599,7 +599,7 @@ impl serde::ser::SerializeStruct for SerializeMap { } #[cfg(feature = "arbitrary_precision")] SerializeMap::Number { ref mut out_value } => { - if key == ::number::SERDE_STRUCT_FIELD_NAME { + if key == ::number::TOKEN { *out_value = Some(value.serialize(NumberValueEmitter)?); Ok(()) } else { @@ -608,7 +608,7 @@ impl serde::ser::SerializeStruct for SerializeMap { } #[cfg(feature = "raw_value")] SerializeMap::RawValue { ref mut out_value } => { - if key == ::raw::SERDE_STRUCT_FIELD_NAME { + if key == ::raw::TOKEN { *out_value = Some(value.serialize(RawValueEmitter)?); Ok(()) } else { From 9c60f196f216e13c8253552d6f844df4d154fefe Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 17 Sep 2018 09:23:28 -0700 Subject: [PATCH 11/17] Split RawSlice and RawValue --- src/lib.rs | 4 -- src/raw.rs | 175 ++++++++++++++++++++++++++++++++++++++++------- src/value/mod.rs | 2 +- tests/test.rs | 55 ++++++++++++--- 4 files changed, 197 insertions(+), 39 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 001109495..79513b320 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -366,10 +366,6 @@ pub use self::ser::{ #[doc(inline)] pub use self::value::{from_value, to_value, Map, Number, Value}; -#[cfg(feature = "raw_value")] -#[doc(inline)] -pub use self::value::RawValue; - // We only use our own error type; no need for From conversions provided by the // standard library's try! macro. This reduces lines of LLVM IR by 4%. macro_rules! try { diff --git a/src/raw.rs b/src/raw.rs index f2774e502..149131639 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -1,5 +1,7 @@ -use std::borrow::Cow; -use std::fmt::{self, Debug}; +use std::borrow::Borrow; +use std::fmt::{self, Debug, Display}; +use std::mem; +use std::ops::Deref; use serde::ser::{Serialize, Serializer, SerializeStruct}; use serde::de::{self, Deserialize, Deserializer, DeserializeSeed, IntoDeserializer, MapAccess, Unexpected, Visitor}; @@ -17,49 +19,148 @@ use error::Error; /// /// When deserializing, this type can not be used with the `#[serde(flatten)]` attribute, /// as it relies on the original input buffer. +#[repr(C)] +pub struct RawSlice { + borrowed: str, +} + +/// +pub struct RawValue { + owned: Box, +} + +impl RawSlice { + fn from_inner(borrowed: &str) -> &Self { + unsafe { mem::transmute::<&str, &RawSlice>(borrowed) } + } +} + +impl RawValue { + fn from_inner(owned: Box) -> Self { + RawValue { + owned: unsafe { mem::transmute::, Box>(owned) }, + } + } +} + +impl Clone for RawValue { + fn clone(&self) -> Self { + self.owned.to_owned() + } +} + +impl Deref for RawValue { + type Target = RawSlice; + + fn deref(&self) -> &Self::Target { + &self.owned + } +} + +impl Borrow for RawValue { + fn borrow(&self) -> &RawSlice { + &self.owned + } +} + +impl ToOwned for RawSlice { + type Owned = RawValue; -#[derive(Clone)] -pub struct RawValue<'a> { - cow: Cow<'a, str>, + fn to_owned(&self) -> Self::Owned { + RawValue::from_inner(self.borrowed.to_owned().into_boxed_str()) + } } -impl<'a> Debug for RawValue<'a> { +impl Debug for RawSlice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter + .debug_tuple("RawSlice") + .field(&format_args!("{}", &self.borrowed)) + .finish() + } +} + +impl Debug for RawValue { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter .debug_tuple("RawValue") - .field(&format_args!("{}", self.cow)) + .field(&format_args!("{}", &self.owned.borrowed)) .finish() } } -impl<'a> AsRef for RawValue<'a> { - fn as_ref(&self) -> &str { - &self.cow +impl RawSlice { + /// + pub fn as_ref(&self) -> &str { + &self.borrowed + } +} + +impl Display for RawSlice { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(&self.borrowed) } } -impl<'a> fmt::Display for RawValue<'a> { +impl Display for RawValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(&self.cow) + Display::fmt(&**self, f) } } pub const TOKEN: &'static str = "$serde_json::private::RawValue"; -impl<'a> Serialize for RawValue<'a> { - #[inline] +impl Serialize for RawSlice { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut s = serializer.serialize_struct(TOKEN, 1)?; - s.serialize_field(TOKEN, &self.cow)?; + s.serialize_field(TOKEN, &self.borrowed)?; s.end() } } -impl<'a, 'de: 'a> Deserialize<'de> for RawValue<'a> { - #[inline] +impl Serialize for RawValue { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + (**self).serialize(serializer) + } +} + +impl<'de: 'a, 'a> Deserialize<'de> for &'a RawSlice { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct RawSliceVisitor; + + impl<'de> Visitor<'de> for RawSliceVisitor { + type Value = &'de RawSlice; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "any valid JSON value") + } + + fn visit_map(self, mut visitor: V) -> Result + where + V: MapAccess<'de>, + { + let value = visitor.next_key::()?; + if value.is_none() { + return Err(de::Error::invalid_type(Unexpected::Map, &self)); + } + visitor.next_value_seed(RawSliceFromString) + } + } + + deserializer.deserialize_newtype_struct(TOKEN, RawSliceVisitor) + } +} + +impl<'de> Deserialize<'de> for RawValue { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, @@ -67,7 +168,7 @@ impl<'a, 'de: 'a> Deserialize<'de> for RawValue<'a> { struct RawValueVisitor; impl<'de> Visitor<'de> for RawValueVisitor { - type Value = RawValue<'de>; + type Value = RawValue; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "any valid JSON value") @@ -122,10 +223,38 @@ impl<'de> Deserialize<'de> for RawKey { } } +pub struct RawSliceFromString; + +impl<'de> DeserializeSeed<'de> for RawSliceFromString { + type Value = &'de RawSlice; + + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(self) + } +} + +impl<'de> Visitor<'de> for RawSliceFromString { + type Value = &'de RawSlice; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("raw value") + } + + fn visit_borrowed_str(self, s: &'de str) -> Result + where + E: de::Error, + { + Ok(RawSlice::from_inner(s)) + } +} + pub struct RawValueFromString; impl<'de> DeserializeSeed<'de> for RawValueFromString { - type Value = RawValue<'de>; + type Value = RawValue; fn deserialize(self, deserializer: D) -> Result where @@ -136,24 +265,24 @@ impl<'de> DeserializeSeed<'de> for RawValueFromString { } impl<'de> Visitor<'de> for RawValueFromString { - type Value = RawValue<'de>; + type Value = RawValue; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("raw value") } - fn visit_borrowed_str(self, s: &'de str) -> Result + fn visit_str(self, s: &str) -> Result where E: de::Error, { - Ok(RawValue { cow: Cow::Borrowed(s) }) + self.visit_string(s.to_owned()) } fn visit_string(self, s: String) -> Result where E: de::Error, { - Ok(RawValue { cow: Cow::Owned(s) }) + Ok(RawValue::from_inner(s.into_boxed_str())) } } diff --git a/src/value/mod.rs b/src/value/mod.rs index c976af501..600a28ab9 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -120,7 +120,7 @@ pub use map::Map; pub use number::Number; #[cfg(feature = "raw_value")] -pub use raw::RawValue; +pub use raw::{RawSlice, RawValue}; pub use self::index::Index; diff --git a/tests/test.rs b/tests/test.rs index cc2c206c6..66d488512 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -2042,28 +2042,61 @@ fn test_integer128() { #[cfg(feature = "raw_value")] #[test] -fn test_raw_value() { - use serde_json::RawValue; +fn test_raw_slice() { + use serde_json::value::RawSlice; #[derive(Serialize, Deserialize)] struct Wrapper<'a> { a: i8, #[serde(borrow)] - b: RawValue<'a>, + b: &'a RawSlice, + c: i8, + }; + + let wrapper_from_str: Wrapper = + serde_json::from_str(r#"{"a": 1, "b": {"foo": 2}, "c": 3}"#).unwrap(); + assert_eq!(r#"{"foo": 2}"#, wrapper_from_str.b.as_ref()); + + let wrapper_to_string = serde_json::to_string(&wrapper_from_str).unwrap(); + assert_eq!(r#"{"a":1,"b":{"foo": 2},"c":3}"#, wrapper_to_string); + + let wrapper_to_value = serde_json::to_value(&wrapper_from_str).unwrap(); + assert_eq!(json!({"a": 1, "b": {"foo": 2}, "c": 3}), wrapper_to_value); + + let array_from_str: Vec<&RawSlice> = + serde_json::from_str(r#"["a", 42, {"foo": "bar"}, null]"#).unwrap(); + assert_eq!(r#""a""#, array_from_str[0].as_ref()); + assert_eq!(r#"42"#, array_from_str[1].as_ref()); + assert_eq!(r#"{"foo": "bar"}"#, array_from_str[2].as_ref()); + assert_eq!(r#"null"#, array_from_str[3].as_ref()); + + let array_to_string = serde_json::to_string(&array_from_str).unwrap(); + assert_eq!(r#"["a",42,{"foo": "bar"},null]"#, array_to_string); +} + +#[cfg(feature = "raw_value")] +#[test] +fn test_raw_value() { + use serde_json::value::RawValue; + + #[derive(Serialize, Deserialize)] + struct Wrapper { + a: i8, + b: RawValue, c: i8, }; - let wrapper_from_str = - serde_json::from_str::(r#"{"a": 1, "b": {"foo": 2}, "c": 3}"#).unwrap(); + let wrapper_from_str: Wrapper = + serde_json::from_str(r#"{"a": 1, "b": {"foo": 2}, "c": 3}"#).unwrap(); assert_eq!(r#"{"foo": 2}"#, wrapper_from_str.b.as_ref()); - let wrapper_from_reader = serde_json::from_reader::<_, Wrapper<'static>>( + let wrapper_from_reader: Wrapper = serde_json::from_reader( br#"{"a": 1, "b": {"foo": 2}, "c": 3}"#.as_ref(), ).unwrap(); assert_eq!(r#"{"foo": 2}"#, wrapper_from_reader.b.as_ref()); - let wrapper_from_value = - serde_json::from_value::>(json!({"a": 1, "b": {"foo": 2}, "c": 3})) + let wrapper_from_value: Wrapper = + serde_json::from_value(json!({"a": 1, "b": {"foo": 2}, "c": 3})) .unwrap(); assert_eq!(r#"{"foo":2}"#, wrapper_from_value.b.as_ref()); @@ -2073,14 +2106,14 @@ fn test_raw_value() { let wrapper_to_value = serde_json::to_value(&wrapper_from_str).unwrap(); assert_eq!(json!({"a": 1, "b": {"foo": 2}, "c": 3}), wrapper_to_value); - let array_from_str = - serde_json::from_str::>(r#"["a", 42, {"foo": "bar"}, null]"#).unwrap(); + let array_from_str: Vec = + serde_json::from_str(r#"["a", 42, {"foo": "bar"}, null]"#).unwrap(); assert_eq!(r#""a""#, array_from_str[0].as_ref()); assert_eq!(r#"42"#, array_from_str[1].as_ref()); assert_eq!(r#"{"foo": "bar"}"#, array_from_str[2].as_ref()); assert_eq!(r#"null"#, array_from_str[3].as_ref()); - let array_from_reader = serde_json::from_reader::<_, Vec>>( + let array_from_reader: Vec = serde_json::from_reader( br#"["a", 42, {"foo": "bar"}, null]"#.as_ref(), ).unwrap(); assert_eq!(r#""a""#, array_from_reader[0].as_ref()); From 119b8bf6c1a2c8c2551c20537a931695efe80460 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 20 Sep 2018 01:00:54 -0700 Subject: [PATCH 12/17] Document RawSlice --- src/raw.rs | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 96 insertions(+), 5 deletions(-) diff --git a/src/raw.rs b/src/raw.rs index 149131639..66a7c77c8 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -9,16 +9,72 @@ use serde::de::value::BorrowedStrDeserializer; use error::Error; -/// Represents any valid JSON value as a series of raw bytes. +/// Reference to a range of bytes encompassing a single valid JSON value in the +/// input data. /// -/// This type can be used to defer parsing parts of a payload until later, -/// or to embed it verbatim into another JSON payload. +/// A `RawSlice` can be used to defer parsing parts of a payload until later, +/// or to avoid parsing it at all in the case that part of the payload just +/// needs to be transferred verbatim into a different output object. /// /// When serializing, a value of this type will retain its original formatting /// and will not be minified or pretty-printed. /// -/// When deserializing, this type can not be used with the `#[serde(flatten)]` attribute, -/// as it relies on the original input buffer. +/// # Example +/// +/// ``` +/// #[macro_use] +/// extern crate serde_derive; +/// extern crate serde_json; +/// +/// use serde_json::{Result, value::RawSlice}; +/// +/// #[derive(Deserialize)] +/// struct Input<'a> { +/// code: u32, +/// #[serde(borrow)] +/// payload: &'a RawSlice, +/// } +/// +/// #[derive(Serialize)] +/// struct Output<'a> { +/// info: (u32, &'a RawSlice), +/// } +/// +/// // Efficiently rearrange JSON input containing separate "code" and "payload" +/// // keys into a single "info" key holding an array of code and payload. +/// // +/// // This could be done equivalently using serde_json::Value as the type for +/// // payload, but &RawSlice will perform netter because it does not require +/// // memory allocation. The correct range of bytes is borrowed from the input +/// // data and pasted verbatim into the output. +/// fn rearrange(input: &str) -> Result { +/// let input: Input = serde_json::from_str(input)?; +/// +/// let output = Output { +/// info: (input.code, input.payload), +/// }; +/// +/// serde_json::to_string(&output) +/// } +/// +/// fn main() -> Result<()> { +/// let out = rearrange(r#" {"code": 200, "payload": {}} "#)?; +/// +/// assert_eq!(out, r#"{"info":[200,{}]}"#); +/// +/// Ok(()) +/// } +/// ``` +/// +/// # Note +/// +/// `RawSlice` is only available if serde\_json is built with the `"raw_value"` +/// feature. +/// +/// ```toml +/// [dependencies] +/// serde_json = { version = "1.0", features = ["raw_value"] } +/// ``` #[repr(C)] pub struct RawSlice { borrowed: str, @@ -90,7 +146,42 @@ impl Debug for RawValue { } impl RawSlice { + /// Access the JSON text underlying a raw value. + /// + /// # Example + /// + /// ``` + /// #[macro_use] + /// extern crate serde_derive; + /// extern crate serde_json; + /// + /// use serde_json::{Result, value::RawSlice}; + /// + /// #[derive(Deserialize)] + /// struct Response<'a> { + /// code: u32, + /// #[serde(borrow)] + /// payload: &'a RawSlice, + /// } + /// + /// fn process(input: &str) -> Result<()> { + /// let response: Response = serde_json::from_str(input)?; + /// + /// let payload = response.payload.as_ref(); + /// if payload.starts_with('{') { + /// // handle a payload which is a JSON map + /// } else { + /// // handle any other type + /// } + /// + /// Ok(()) + /// } /// + /// fn main() -> Result<()> { + /// process(r#" {"code": 200, "payload": {}} "#)?; + /// Ok(()) + /// } + /// ``` pub fn as_ref(&self) -> &str { &self.borrowed } From 37f8515e9fab912dea94f8c9110dd83a97a8997a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 20 Sep 2018 01:01:03 -0700 Subject: [PATCH 13/17] Enable raw_value feature in docs.rs and playground --- Cargo.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 8135c15e8..0ccec383a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,12 @@ compiletest_rs = "0.3" serde_bytes = "0.10" serde_derive = "1.0" +[package.metadata.docs.rs] +features = ["raw_value"] + +[package.metadata.playground] +features = ["raw_value"] + ### FEATURES ################################################################# From 82abb08f903d3b57e1df24dca80868519b7634a5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 20 Sep 2018 01:18:12 -0700 Subject: [PATCH 14/17] Use Box as the owned raw value --- src/raw.rs | 159 ++++++++++++++++------------------------------- src/value/de.rs | 4 +- src/value/mod.rs | 2 +- tests/test.rs | 48 +++++++------- 4 files changed, 82 insertions(+), 131 deletions(-) diff --git a/src/raw.rs b/src/raw.rs index 66a7c77c8..25921106e 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -1,7 +1,5 @@ -use std::borrow::Borrow; use std::fmt::{self, Debug, Display}; use std::mem; -use std::ops::Deref; use serde::ser::{Serialize, Serializer, SerializeStruct}; use serde::de::{self, Deserialize, Deserializer, DeserializeSeed, IntoDeserializer, MapAccess, Unexpected, Visitor}; @@ -12,7 +10,7 @@ use error::Error; /// Reference to a range of bytes encompassing a single valid JSON value in the /// input data. /// -/// A `RawSlice` can be used to defer parsing parts of a payload until later, +/// A `RawValue` can be used to defer parsing parts of a payload until later, /// or to avoid parsing it at all in the case that part of the payload just /// needs to be transferred verbatim into a different output object. /// @@ -26,25 +24,25 @@ use error::Error; /// extern crate serde_derive; /// extern crate serde_json; /// -/// use serde_json::{Result, value::RawSlice}; +/// use serde_json::{Result, value::RawValue}; /// /// #[derive(Deserialize)] /// struct Input<'a> { /// code: u32, /// #[serde(borrow)] -/// payload: &'a RawSlice, +/// payload: &'a RawValue, /// } /// /// #[derive(Serialize)] /// struct Output<'a> { -/// info: (u32, &'a RawSlice), +/// info: (u32, &'a RawValue), /// } /// /// // Efficiently rearrange JSON input containing separate "code" and "payload" /// // keys into a single "info" key holding an array of code and payload. /// // /// // This could be done equivalently using serde_json::Value as the type for -/// // payload, but &RawSlice will perform netter because it does not require +/// // payload, but &RawValue will perform netter because it does not require /// // memory allocation. The correct range of bytes is borrowed from the input /// // data and pasted verbatim into the output. /// fn rearrange(input: &str) -> Result { @@ -68,7 +66,7 @@ use error::Error; /// /// # Note /// -/// `RawSlice` is only available if serde\_json is built with the `"raw_value"` +/// `RawValue` is only available if serde\_json is built with the `"raw_value"` /// feature. /// /// ```toml @@ -76,76 +74,50 @@ use error::Error; /// serde_json = { version = "1.0", features = ["raw_value"] } /// ``` #[repr(C)] -pub struct RawSlice { - borrowed: str, -} - -/// pub struct RawValue { - owned: Box, -} - -impl RawSlice { - fn from_inner(borrowed: &str) -> &Self { - unsafe { mem::transmute::<&str, &RawSlice>(borrowed) } - } + json: str, } impl RawValue { - fn from_inner(owned: Box) -> Self { - RawValue { - owned: unsafe { mem::transmute::, Box>(owned) }, - } + fn from_borrowed(json: &str) -> &Self { + unsafe { mem::transmute::<&str, &RawValue>(json) } } -} -impl Clone for RawValue { - fn clone(&self) -> Self { - self.owned.to_owned() + fn from_owned(json: Box) -> Box { + unsafe { mem::transmute::, Box>(json) } } } -impl Deref for RawValue { - type Target = RawSlice; - - fn deref(&self) -> &Self::Target { - &self.owned - } -} - -impl Borrow for RawValue { - fn borrow(&self) -> &RawSlice { - &self.owned +impl Clone for Box { + fn clone(&self) -> Self { + (**self).to_owned() } } -impl ToOwned for RawSlice { - type Owned = RawValue; +impl ToOwned for RawValue { + type Owned = Box; fn to_owned(&self) -> Self::Owned { - RawValue::from_inner(self.borrowed.to_owned().into_boxed_str()) + RawValue::from_owned(self.json.to_owned().into_boxed_str()) } } -impl Debug for RawSlice { +impl Debug for RawValue { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter - .debug_tuple("RawSlice") - .field(&format_args!("{}", &self.borrowed)) + .debug_tuple("RawValue") + .field(&format_args!("{}", &self.json)) .finish() } } -impl Debug for RawValue { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter - .debug_tuple("RawValue") - .field(&format_args!("{}", &self.owned.borrowed)) - .finish() +impl Display for RawValue { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(&self.json) } } -impl RawSlice { +impl RawValue { /// Access the JSON text underlying a raw value. /// /// # Example @@ -155,19 +127,19 @@ impl RawSlice { /// extern crate serde_derive; /// extern crate serde_json; /// - /// use serde_json::{Result, value::RawSlice}; + /// use serde_json::{Result, value::RawValue}; /// /// #[derive(Deserialize)] /// struct Response<'a> { /// code: u32, /// #[serde(borrow)] - /// payload: &'a RawSlice, + /// payload: &'a RawValue, /// } /// /// fn process(input: &str) -> Result<()> { /// let response: Response = serde_json::from_str(input)?; /// - /// let payload = response.payload.as_ref(); + /// let payload = response.payload.get(); /// if payload.starts_with('{') { /// // handle a payload which is a JSON map /// } else { @@ -182,54 +154,33 @@ impl RawSlice { /// Ok(()) /// } /// ``` - pub fn as_ref(&self) -> &str { - &self.borrowed - } -} - -impl Display for RawSlice { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(&self.borrowed) - } -} - -impl Display for RawValue { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - Display::fmt(&**self, f) + pub fn get(&self) -> &str { + &self.json } } pub const TOKEN: &'static str = "$serde_json::private::RawValue"; -impl Serialize for RawSlice { +impl Serialize for RawValue { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut s = serializer.serialize_struct(TOKEN, 1)?; - s.serialize_field(TOKEN, &self.borrowed)?; + s.serialize_field(TOKEN, &self.json)?; s.end() } } -impl Serialize for RawValue { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - (**self).serialize(serializer) - } -} - -impl<'de: 'a, 'a> Deserialize<'de> for &'a RawSlice { +impl<'de: 'a, 'a> Deserialize<'de> for &'a RawValue { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { - struct RawSliceVisitor; + struct ReferenceVisitor; - impl<'de> Visitor<'de> for RawSliceVisitor { - type Value = &'de RawSlice; + impl<'de> Visitor<'de> for ReferenceVisitor { + type Value = &'de RawValue; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "any valid JSON value") @@ -243,23 +194,23 @@ impl<'de: 'a, 'a> Deserialize<'de> for &'a RawSlice { if value.is_none() { return Err(de::Error::invalid_type(Unexpected::Map, &self)); } - visitor.next_value_seed(RawSliceFromString) + visitor.next_value_seed(ReferenceFromString) } } - deserializer.deserialize_newtype_struct(TOKEN, RawSliceVisitor) + deserializer.deserialize_newtype_struct(TOKEN, ReferenceVisitor) } } -impl<'de> Deserialize<'de> for RawValue { +impl<'de> Deserialize<'de> for Box { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { - struct RawValueVisitor; + struct BoxedVisitor; - impl<'de> Visitor<'de> for RawValueVisitor { - type Value = RawValue; + impl<'de> Visitor<'de> for BoxedVisitor { + type Value = Box; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "any valid JSON value") @@ -273,11 +224,11 @@ impl<'de> Deserialize<'de> for RawValue { if value.is_none() { return Err(de::Error::invalid_type(Unexpected::Map, &self)); } - visitor.next_value_seed(RawValueFromString) + visitor.next_value_seed(BoxedFromString) } } - deserializer.deserialize_newtype_struct(TOKEN, RawValueVisitor) + deserializer.deserialize_newtype_struct(TOKEN, BoxedVisitor) } } @@ -314,10 +265,10 @@ impl<'de> Deserialize<'de> for RawKey { } } -pub struct RawSliceFromString; +pub struct ReferenceFromString; -impl<'de> DeserializeSeed<'de> for RawSliceFromString { - type Value = &'de RawSlice; +impl<'de> DeserializeSeed<'de> for ReferenceFromString { + type Value = &'de RawValue; fn deserialize(self, deserializer: D) -> Result where @@ -327,8 +278,8 @@ impl<'de> DeserializeSeed<'de> for RawSliceFromString { } } -impl<'de> Visitor<'de> for RawSliceFromString { - type Value = &'de RawSlice; +impl<'de> Visitor<'de> for ReferenceFromString { + type Value = &'de RawValue; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("raw value") @@ -338,14 +289,14 @@ impl<'de> Visitor<'de> for RawSliceFromString { where E: de::Error, { - Ok(RawSlice::from_inner(s)) + Ok(RawValue::from_borrowed(s)) } } -pub struct RawValueFromString; +pub struct BoxedFromString; -impl<'de> DeserializeSeed<'de> for RawValueFromString { - type Value = RawValue; +impl<'de> DeserializeSeed<'de> for BoxedFromString { + type Value = Box; fn deserialize(self, deserializer: D) -> Result where @@ -355,8 +306,8 @@ impl<'de> DeserializeSeed<'de> for RawValueFromString { } } -impl<'de> Visitor<'de> for RawValueFromString { - type Value = RawValue; +impl<'de> Visitor<'de> for BoxedFromString { + type Value = Box; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("raw value") @@ -373,7 +324,7 @@ impl<'de> Visitor<'de> for RawValueFromString { where E: de::Error, { - Ok(RawValue::from_inner(s.into_boxed_str())) + Ok(RawValue::from_owned(s.into_boxed_str())) } } diff --git a/src/value/de.rs b/src/value/de.rs index 1429713db..ba99840c5 100644 --- a/src/value/de.rs +++ b/src/value/de.rs @@ -120,8 +120,8 @@ impl<'de> Deserialize<'de> for Value { } #[cfg(feature = "raw_value")] Some(KeyClass::RawValue) => { - let value = visitor.next_value_seed(::raw::RawValueFromString)?; - ::from_str(value.as_ref()).map_err(de::Error::custom) + let value = visitor.next_value_seed(::raw::BoxedFromString)?; + ::from_str(value.get()).map_err(de::Error::custom) } Some(KeyClass::Map(first_key)) => { let mut values = Map::new(); diff --git a/src/value/mod.rs b/src/value/mod.rs index 600a28ab9..c976af501 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -120,7 +120,7 @@ pub use map::Map; pub use number::Number; #[cfg(feature = "raw_value")] -pub use raw::{RawSlice, RawValue}; +pub use raw::RawValue; pub use self::index::Index; diff --git a/tests/test.rs b/tests/test.rs index 66d488512..9a4eb3884 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -2042,20 +2042,20 @@ fn test_integer128() { #[cfg(feature = "raw_value")] #[test] -fn test_raw_slice() { - use serde_json::value::RawSlice; +fn test_borrowed_raw_value() { + use serde_json::value::RawValue; #[derive(Serialize, Deserialize)] struct Wrapper<'a> { a: i8, #[serde(borrow)] - b: &'a RawSlice, + b: &'a RawValue, c: i8, }; let wrapper_from_str: Wrapper = serde_json::from_str(r#"{"a": 1, "b": {"foo": 2}, "c": 3}"#).unwrap(); - assert_eq!(r#"{"foo": 2}"#, wrapper_from_str.b.as_ref()); + assert_eq!(r#"{"foo": 2}"#, wrapper_from_str.b.get()); let wrapper_to_string = serde_json::to_string(&wrapper_from_str).unwrap(); assert_eq!(r#"{"a":1,"b":{"foo": 2},"c":3}"#, wrapper_to_string); @@ -2063,12 +2063,12 @@ fn test_raw_slice() { let wrapper_to_value = serde_json::to_value(&wrapper_from_str).unwrap(); assert_eq!(json!({"a": 1, "b": {"foo": 2}, "c": 3}), wrapper_to_value); - let array_from_str: Vec<&RawSlice> = + let array_from_str: Vec<&RawValue> = serde_json::from_str(r#"["a", 42, {"foo": "bar"}, null]"#).unwrap(); - assert_eq!(r#""a""#, array_from_str[0].as_ref()); - assert_eq!(r#"42"#, array_from_str[1].as_ref()); - assert_eq!(r#"{"foo": "bar"}"#, array_from_str[2].as_ref()); - assert_eq!(r#"null"#, array_from_str[3].as_ref()); + assert_eq!(r#""a""#, array_from_str[0].get()); + assert_eq!(r#"42"#, array_from_str[1].get()); + assert_eq!(r#"{"foo": "bar"}"#, array_from_str[2].get()); + assert_eq!(r#"null"#, array_from_str[3].get()); let array_to_string = serde_json::to_string(&array_from_str).unwrap(); assert_eq!(r#"["a",42,{"foo": "bar"},null]"#, array_to_string); @@ -2076,29 +2076,29 @@ fn test_raw_slice() { #[cfg(feature = "raw_value")] #[test] -fn test_raw_value() { +fn test_boxed_raw_value() { use serde_json::value::RawValue; #[derive(Serialize, Deserialize)] struct Wrapper { a: i8, - b: RawValue, + b: Box, c: i8, }; let wrapper_from_str: Wrapper = serde_json::from_str(r#"{"a": 1, "b": {"foo": 2}, "c": 3}"#).unwrap(); - assert_eq!(r#"{"foo": 2}"#, wrapper_from_str.b.as_ref()); + assert_eq!(r#"{"foo": 2}"#, wrapper_from_str.b.get()); let wrapper_from_reader: Wrapper = serde_json::from_reader( br#"{"a": 1, "b": {"foo": 2}, "c": 3}"#.as_ref(), ).unwrap(); - assert_eq!(r#"{"foo": 2}"#, wrapper_from_reader.b.as_ref()); + assert_eq!(r#"{"foo": 2}"#, wrapper_from_reader.b.get()); let wrapper_from_value: Wrapper = serde_json::from_value(json!({"a": 1, "b": {"foo": 2}, "c": 3})) .unwrap(); - assert_eq!(r#"{"foo":2}"#, wrapper_from_value.b.as_ref()); + assert_eq!(r#"{"foo":2}"#, wrapper_from_value.b.get()); let wrapper_to_string = serde_json::to_string(&wrapper_from_str).unwrap(); assert_eq!(r#"{"a":1,"b":{"foo": 2},"c":3}"#, wrapper_to_string); @@ -2106,20 +2106,20 @@ fn test_raw_value() { let wrapper_to_value = serde_json::to_value(&wrapper_from_str).unwrap(); assert_eq!(json!({"a": 1, "b": {"foo": 2}, "c": 3}), wrapper_to_value); - let array_from_str: Vec = + let array_from_str: Vec> = serde_json::from_str(r#"["a", 42, {"foo": "bar"}, null]"#).unwrap(); - assert_eq!(r#""a""#, array_from_str[0].as_ref()); - assert_eq!(r#"42"#, array_from_str[1].as_ref()); - assert_eq!(r#"{"foo": "bar"}"#, array_from_str[2].as_ref()); - assert_eq!(r#"null"#, array_from_str[3].as_ref()); + assert_eq!(r#""a""#, array_from_str[0].get()); + assert_eq!(r#"42"#, array_from_str[1].get()); + assert_eq!(r#"{"foo": "bar"}"#, array_from_str[2].get()); + assert_eq!(r#"null"#, array_from_str[3].get()); - let array_from_reader: Vec = serde_json::from_reader( + let array_from_reader: Vec> = serde_json::from_reader( br#"["a", 42, {"foo": "bar"}, null]"#.as_ref(), ).unwrap(); - assert_eq!(r#""a""#, array_from_reader[0].as_ref()); - assert_eq!(r#"42"#, array_from_reader[1].as_ref()); - assert_eq!(r#"{"foo": "bar"}"#, array_from_reader[2].as_ref()); - assert_eq!(r#"null"#, array_from_reader[3].as_ref()); + assert_eq!(r#""a""#, array_from_reader[0].get()); + assert_eq!(r#"42"#, array_from_reader[1].get()); + assert_eq!(r#"{"foo": "bar"}"#, array_from_reader[2].get()); + assert_eq!(r#"null"#, array_from_reader[3].get()); let array_to_string = serde_json::to_string(&array_from_str).unwrap(); assert_eq!(r#"["a",42,{"foo": "bar"},null]"#, array_to_string); From e58102f7ca115ad64aa25ae7894002c4d0f62787 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 20 Sep 2018 01:26:45 -0700 Subject: [PATCH 15/17] Document RawValue ownership --- src/raw.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/raw.rs b/src/raw.rs index 25921106e..54b85c79c 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -64,6 +64,53 @@ use error::Error; /// } /// ``` /// +/// # Ownership +/// +/// The typical usage of `RawValue` will be in the borrowed form: +/// +/// ``` +/// # #[macro_use] +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # +/// # use serde_json::value::RawValue; +/// # +/// #[derive(Deserialize)] +/// struct SomeStruct<'a> { +/// #[serde(borrow)] +/// raw_value: &'a RawValue, +/// } +/// # +/// # fn main() {} +/// ``` +/// +/// The borrowed form is suitable when deserializing through +/// [`serde_json::from_str`] and [`serde_json::from_slice`] which support +/// borrowing from the input data without memory allocation. +/// +/// When deserializing through [`serde_json::from_reader`] you will need to use +/// the boxed form of `RawValue` instead. This is almost as efficient but +/// involves buffering the raw value from the I/O stream into memory. +/// +/// [`serde_json::from_str`]: ../fn.from_str.html +/// [`serde_json::from_slice`]: ../fn.from_slice.html +/// [`serde_json::from_reader`]: ../fn.from_reader.html +/// +/// ``` +/// # #[macro_use] +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # +/// # use serde_json::value::RawValue; +/// # +/// #[derive(Deserialize)] +/// struct SomeStruct { +/// raw_value: Box, +/// } +/// # +/// # fn main() {} +/// ``` +/// /// # Note /// /// `RawValue` is only available if serde\_json is built with the `"raw_value"` From 7478753743ff16b5a44bc61f747a86595555df6d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 20 Sep 2018 10:45:33 -0700 Subject: [PATCH 16/17] Fix raw value compilation on rustc older than 1.20 --- src/read.rs | 54 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/read.rs b/src/read.rs index bd181e8de..fba1dd9f9 100644 --- a/src/read.rs +++ b/src/read.rs @@ -166,11 +166,20 @@ where { /// Create a JSON input source to read from a std::io input stream. pub fn new(reader: R) -> Self { - IoRead { - iter: LineColIterator::new(reader.bytes()), - ch: None, - #[cfg(feature = "raw_value")] - raw_buffer: None, + #[cfg(not(feature = "raw_value"))] + { + IoRead { + iter: LineColIterator::new(reader.bytes()), + ch: None, + } + } + #[cfg(feature = "raw_value")] + { + IoRead { + iter: LineColIterator::new(reader.bytes()), + ch: None, + raw_buffer: None, + } } } } @@ -351,11 +360,20 @@ where impl<'a> SliceRead<'a> { /// Create a JSON input source to read from a slice of bytes. pub fn new(slice: &'a [u8]) -> Self { - SliceRead { - slice: slice, - index: 0, - #[cfg(feature = "raw_value")] - raw_buffering_start_index: 0, + #[cfg(not(feature = "raw_value"))] + { + SliceRead { + slice: slice, + index: 0, + } + } + #[cfg(feature = "raw_value")] + { + SliceRead { + slice: slice, + index: 0, + raw_buffering_start_index: 0, + } } } @@ -531,10 +549,18 @@ impl<'a> Read<'a> for SliceRead<'a> { impl<'a> StrRead<'a> { /// Create a JSON input source to read from a UTF-8 string. pub fn new(s: &'a str) -> Self { - StrRead { - delegate: SliceRead::new(s.as_bytes()), - #[cfg(feature = "raw_value")] - data: s, + #[cfg(not(feature = "raw_value"))] + { + StrRead { + delegate: SliceRead::new(s.as_bytes()), + } + } + #[cfg(feature = "raw_value")] + { + StrRead { + delegate: SliceRead::new(s.as_bytes()), + data: s, + } } } } From a45b5c592a871dc936386232bb904324ff559f5f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 20 Sep 2018 10:48:48 -0700 Subject: [PATCH 17/17] Fix malicious arbitrary precision number test --- tests/test.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test.rs b/tests/test.rs index 9a4eb3884..ec2de425e 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -938,9 +938,9 @@ fn test_serialize_char() { #[test] fn test_malicious_number() { #[derive(Serialize)] - #[serde(rename = "$__serde_private_Number")] + #[serde(rename = "$serde_json::private::Number")] struct S { - #[serde(rename = "$__serde_private_number")] + #[serde(rename = "$serde_json::private::Number")] f: &'static str, }