Skip to content

Commit 6d38232

Browse files
committed
Implement RawValue type
fixes #355
1 parent d461263 commit 6d38232

File tree

9 files changed

+612
-17
lines changed

9 files changed

+612
-17
lines changed

src/de.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
//! Deserialize JSON data to a Rust data structure.
1010
11+
use std::borrow::Cow;
1112
use std::io;
1213
use std::marker::PhantomData;
1314
use std::result;
@@ -946,6 +947,22 @@ impl<'de, R: Read<'de>> Deserializer<R> {
946947
}
947948
}
948949
}
950+
951+
fn deserialize_raw_value<V>(&mut self, visitor: V) -> Result<V::Value>
952+
where
953+
V: de::Visitor<'de>,
954+
{
955+
if let None = try!(self.parse_whitespace()) {
956+
return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
957+
}
958+
959+
self.read.toggle_raw_buffering();
960+
de::Deserializer::deserialize_any(&mut *self, de::IgnoredAny)?;
961+
match self.read.toggle_raw_buffering().unwrap() {
962+
Cow::Owned(byte_buf) => visitor.visit_byte_buf(byte_buf),
963+
Cow::Borrowed(bytes) => visitor.visit_borrowed_bytes(bytes),
964+
}
965+
}
949966
}
950967

951968
impl FromStr for Number {
@@ -1412,10 +1429,14 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer<R> {
14121429

14131430
/// Parses a newtype struct as the underlying value.
14141431
#[inline]
1415-
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value>
1432+
fn deserialize_newtype_struct<V>(self, name: &str, visitor: V) -> Result<V::Value>
14161433
where
14171434
V: de::Visitor<'de>,
14181435
{
1436+
if name == ::raw::SERDE_STRUCT_NAME {
1437+
return self.deserialize_raw_value(visitor);
1438+
}
1439+
14191440
visitor.visit_newtype_struct(self)
14201441
}
14211442

src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ pub use self::ser::{
364364
to_string, to_string_pretty, to_vec, to_vec_pretty, to_writer, to_writer_pretty, Serializer,
365365
};
366366
#[doc(inline)]
367-
pub use self::value::{from_value, to_value, Map, Number, Value};
367+
pub use self::value::{from_value, to_value, Map, Number, RawValue, Value};
368368

369369
// We only use our own error type; no need for From conversions provided by the
370370
// standard library's try! macro. This reduces lines of LLVM IR by 4%.
@@ -388,4 +388,5 @@ pub mod value;
388388

389389
mod iter;
390390
mod number;
391+
mod raw;
391392
mod read;

src/raw.rs

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use std::borrow::Cow;
2+
use std::fmt;
3+
4+
use serde::de::Visitor;
5+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
6+
7+
/// Represents any valid JSON value as a series of raw bytes.
8+
///
9+
/// This type can be used to defer parsing parts of a payload until later,
10+
/// or to embed it verbatim into another JSON payload.
11+
///
12+
/// When serializing, a value of this type will retain its original formatting
13+
/// and will not be minified or pretty-printed.
14+
///
15+
/// When deserializing, this type can not be used with the `#[serde(flatten)]` attribute,
16+
/// as it relies on the original input buffer.
17+
18+
#[derive(Debug, Clone, PartialEq)]
19+
pub struct RawValue<'a>(Cow<'a, str>);
20+
21+
impl<'a> AsRef<str> for RawValue<'a> {
22+
fn as_ref(&self) -> &str {
23+
&self.0
24+
}
25+
}
26+
27+
impl<'a> fmt::Display for RawValue<'a> {
28+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
29+
f.write_str(&self.0)
30+
}
31+
}
32+
33+
/// Not public API. Should be pub(crate).
34+
#[doc(hidden)]
35+
pub const SERDE_STRUCT_NAME: &'static str = "$__serde_private_RawValue";
36+
37+
impl<'a> Serialize for RawValue<'a> {
38+
#[inline]
39+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
40+
where
41+
S: Serializer,
42+
{
43+
serializer.serialize_newtype_struct(SERDE_STRUCT_NAME, &self.0)
44+
}
45+
}
46+
47+
impl<'a, 'de> Deserialize<'de> for RawValue<'a>
48+
where
49+
'de: 'a,
50+
{
51+
#[inline]
52+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
53+
where
54+
D: Deserializer<'de>,
55+
{
56+
struct RawValueVisitor;
57+
58+
impl<'de> Visitor<'de> for RawValueVisitor {
59+
type Value = RawValue<'de>;
60+
61+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
62+
write!(formatter, "a deserializable RawValue")
63+
}
64+
65+
fn visit_string<E>(self, s: String) -> Result<Self::Value, E>
66+
where
67+
E: ::serde::de::Error,
68+
{
69+
Ok(RawValue(Cow::Owned(s)))
70+
}
71+
72+
fn visit_byte_buf<E>(self, b: Vec<u8>) -> Result<Self::Value, E>
73+
where
74+
E: ::serde::de::Error,
75+
{
76+
String::from_utf8(b)
77+
.map(|s| RawValue(Cow::Owned(s)))
78+
.map_err(|err| ::serde::de::Error::custom(err))
79+
}
80+
81+
fn visit_borrowed_bytes<E>(self, b: &'de [u8]) -> Result<Self::Value, E>
82+
where
83+
E: ::serde::de::Error,
84+
{
85+
::std::str::from_utf8(b)
86+
.map(|s| RawValue(Cow::Borrowed(s)))
87+
.map_err(|err| ::serde::de::Error::custom(err))
88+
}
89+
}
90+
91+
deserializer.deserialize_newtype_struct(SERDE_STRUCT_NAME, RawValueVisitor)
92+
}
93+
}

src/read.rs

+51-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9+
use std::borrow::Cow;
910
use std::ops::Deref;
1011
use std::{char, cmp, io, str};
1112

@@ -76,6 +77,13 @@ pub trait Read<'de>: private::Sealed {
7677
/// string until the next quotation mark but discards the data.
7778
#[doc(hidden)]
7879
fn ignore_str(&mut self) -> Result<()>;
80+
81+
/// Switch raw buffering mode on/off. When switching off, returns a copy-on-write
82+
/// buffer with the captured data.
83+
///
84+
/// This is used to deserialize `RawValue`.
85+
#[doc(hidden)]
86+
fn toggle_raw_buffering(&mut self) -> Option<Cow<'de, [u8]>>;
7987
}
8088

8189
pub struct Position {
@@ -107,6 +115,7 @@ where
107115
iter: LineColIterator<io::Bytes<R>>,
108116
/// Temporary storage of peeked byte.
109117
ch: Option<u8>,
118+
raw_buffer: Option<Vec<u8>>,
110119
}
111120

112121
/// JSON input source that reads from a slice of bytes.
@@ -117,6 +126,7 @@ pub struct SliceRead<'a> {
117126
slice: &'a [u8],
118127
/// Index of the *next* byte that will be returned by next() or peek().
119128
index: usize,
129+
raw_buffering_start_index: Option<usize>,
120130
}
121131

122132
/// JSON input source that reads from a UTF-8 string.
@@ -142,6 +152,7 @@ where
142152
IoRead {
143153
iter: LineColIterator::new(reader.bytes()),
144154
ch: None,
155+
raw_buffer: None,
145156
}
146157
}
147158
}
@@ -193,10 +204,20 @@ where
193204
#[inline]
194205
fn next(&mut self) -> io::Result<Option<u8>> {
195206
match self.ch.take() {
196-
Some(ch) => Ok(Some(ch)),
207+
Some(ch) => {
208+
if let Some(ref mut buf) = self.raw_buffer {
209+
buf.push(ch);
210+
}
211+
Ok(Some(ch))
212+
}
197213
None => match self.iter.next() {
198214
Some(Err(err)) => Err(err),
199-
Some(Ok(ch)) => Ok(Some(ch)),
215+
Some(Ok(ch)) => {
216+
if let Some(ref mut buf) = self.raw_buffer {
217+
buf.push(ch);
218+
}
219+
Ok(Some(ch))
220+
}
200221
None => Ok(None),
201222
},
202223
}
@@ -219,7 +240,11 @@ where
219240

220241
#[inline]
221242
fn discard(&mut self) {
222-
self.ch = None;
243+
if let Some(ch) = self.ch.take() {
244+
if let Some(ref mut buf) = self.raw_buffer {
245+
buf.push(ch);
246+
}
247+
}
223248
}
224249

225250
fn position(&self) -> Position {
@@ -274,6 +299,15 @@ where
274299
}
275300
}
276301
}
302+
303+
fn toggle_raw_buffering(&mut self) -> Option<Cow<'de, [u8]>> {
304+
if let Some(buffer) = self.raw_buffer.take() {
305+
Some(Cow::Owned(buffer))
306+
} else {
307+
self.raw_buffer = Some(Vec::new());
308+
None
309+
}
310+
}
277311
}
278312

279313
//////////////////////////////////////////////////////////////////////////////
@@ -284,6 +318,7 @@ impl<'a> SliceRead<'a> {
284318
SliceRead {
285319
slice: slice,
286320
index: 0,
321+
raw_buffering_start_index: None,
287322
}
288323
}
289324

@@ -437,6 +472,15 @@ impl<'a> Read<'a> for SliceRead<'a> {
437472
}
438473
}
439474
}
475+
476+
fn toggle_raw_buffering(&mut self) -> Option<Cow<'a, [u8]>> {
477+
if let Some(start_index) = self.raw_buffering_start_index.take() {
478+
Some(Cow::Borrowed(&self.slice[start_index..self.index]))
479+
} else {
480+
self.raw_buffering_start_index = Some(self.index);
481+
None
482+
}
483+
}
440484
}
441485

442486
//////////////////////////////////////////////////////////////////////////////
@@ -498,6 +542,10 @@ impl<'a> Read<'a> for StrRead<'a> {
498542
fn ignore_str(&mut self) -> Result<()> {
499543
self.delegate.ignore_str()
500544
}
545+
546+
fn toggle_raw_buffering(&mut self) -> Option<Cow<'a, [u8]>> {
547+
self.delegate.toggle_raw_buffering()
548+
}
501549
}
502550

503551
//////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)