diff --git a/src/de.rs b/src/de.rs index f1c5c3c..0ad91a2 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 d9b7917..e0b7a0b 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 0000000..74d2c7a --- /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 f2cc9f9..8084f40 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 ca9b637..af53c8c 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 dc8dbc6..73dfb8b 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 f5e33b4..155874a 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 d3f71b3..54ce18d 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 08d0388..09c51a6 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); +}