Skip to content

Commit

Permalink
Merge pull request #260 from serde-rs/read
Browse files Browse the repository at this point in the history
Expose the various Read implementations
  • Loading branch information
oli-obk committed Feb 21, 2017
2 parents a6effee + 7faa392 commit af7f3f4
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 13 deletions.
50 changes: 41 additions & 9 deletions json/src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use super::error::{Error, ErrorCode, Result};

use read;

pub use read::Read;
pub use read::{Read, IteratorRead, SliceRead, StrRead};

//////////////////////////////////////////////////////////////////////////////

Expand All @@ -21,8 +21,19 @@ pub struct Deserializer<R> {
remaining_depth: u8,
}

impl<R> Deserializer<R> {
fn new(read: R) -> Self {
impl<R> Deserializer<R>
where R: read::Read
{
/// Create a JSON deserializer from one of the possible serde_json input
/// sources.
///
/// Typically it is more convenient to use one of these methods instead:
///
/// - Deserializer::from_str
/// - Deserializer::from_bytes
/// - Deserializer::from_iter
/// - Deserializer::from_reader
pub fn new(read: R) -> Self {
Deserializer {
read: read,
str_buf: Vec::with_capacity(128),
Expand All @@ -34,30 +45,30 @@ impl<R> Deserializer<R> {
impl<I> Deserializer<read::IteratorRead<I>>
where I: Iterator<Item = io::Result<u8>>
{
/// Creates a JSON parser from a `std::iter::Iterator`.
/// Creates a JSON deserializer from a `std::iter::Iterator`.
pub fn from_iter(iter: I) -> Self {
Deserializer::new(read::IteratorRead::new(iter))
}
}

impl<R> Deserializer<read::IteratorRead<io::Bytes<R>>>
impl<R> Deserializer<read::IoRead<R>>
where R: io::Read
{
/// Creates a JSON parser from an `io::Read`.
/// Creates a JSON deserializer from an `io::Read`.
pub fn from_reader(reader: R) -> Self {
Deserializer::new(read::IteratorRead::new(reader.bytes()))
Deserializer::new(read::IoRead::new(reader))
}
}

impl<'a> Deserializer<read::SliceRead<'a>> {
/// Creates a JSON parser from a `&[u8]`.
/// Creates a JSON deserializer from a `&[u8]`.
pub fn from_slice(bytes: &'a [u8]) -> Self {
Deserializer::new(read::SliceRead::new(bytes))
}
}

impl<'a> Deserializer<read::StrRead<'a>> {
/// Creates a JSON parser from a `&str`.
/// Creates a JSON deserializer from a `&str`.
pub fn from_str(s: &'a str) -> Self {
Deserializer::new(read::StrRead::new(s))
}
Expand Down Expand Up @@ -961,6 +972,27 @@ pub struct StreamDeserializer<R, T> {
_marker: PhantomData<T>,
}

impl<R, T> StreamDeserializer<R, T>
where R: read::Read,
T: de::Deserialize
{
/// Create a JSON stream deserializer from one of the possible serde_json
/// input sources.
///
/// Typically it is more convenient to use one of these methods instead:
///
/// - Deserializer::from_str(...).into_iter()
/// - Deserializer::from_bytes(...).into_iter()
/// - Deserializer::from_iter(...).into_iter()
/// - Deserializer::from_reader(...).into_iter()
pub fn new(read: R) -> Self {
StreamDeserializer {
de: Deserializer::new(read),
_marker: PhantomData,
}
}
}

impl<R, T> Iterator for StreamDeserializer<R, T>
where R: Read,
T: de::Deserialize,
Expand Down
83 changes: 79 additions & 4 deletions json/src/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ pub struct Position {
pub column: usize,
}

/// JSON input source that reads from an iterator of bytes.
pub struct IteratorRead<Iter>
where Iter: Iterator<Item = io::Result<u8>>,
{
Expand All @@ -75,16 +76,26 @@ pub struct IteratorRead<Iter>
ch: Option<u8>,
}

/// Specialization for Iter=&[u8]. This is more efficient than other iterators
/// because peek() can be read-only and we can compute line/col position only if
/// an error happens.
/// JSON input source that reads from a std::io input stream.
pub struct IoRead<R>
where R: io::Read
{
delegate: IteratorRead<io::Bytes<R>>,
}

/// JSON input source that reads from a slice of bytes.
//
// This is more efficient than other iterators because peek() can be read-only
// and we can compute line/col position only if an error happens.
pub struct SliceRead<'a> {
slice: &'a [u8],
/// Index of the *next* byte that will be returned by next() or peek().
index: usize,
}

/// Elide UTF-8 checks by assuming that the input is valid UTF-8.
/// JSON input source that reads from a UTF-8 string.
//
// Able to elide UTF-8 checks by assuming that the input is valid UTF-8.
pub struct StrRead<'a> {
delegate: SliceRead<'a>,
}
Expand All @@ -99,6 +110,7 @@ mod private {
impl<Iter> IteratorRead<Iter>
where Iter: Iterator<Item = io::Result<u8>>,
{
/// Create a JSON input source to read from an iterator of bytes.
pub fn new(iter: Iter) -> Self {
IteratorRead {
iter: LineColIterator::new(iter),
Expand Down Expand Up @@ -220,7 +232,69 @@ impl<Iter> Read for IteratorRead<Iter>

//////////////////////////////////////////////////////////////////////////////

impl<R> IoRead<R>
where R: io::Read
{
/// Create a JSON input source to read from a std::io input stream.
pub fn new(reader: R) -> Self {
IoRead {
delegate: IteratorRead::new(reader.bytes()),
}
}
}

impl<R> private::Sealed for IoRead<R>
where R: io::Read {}

impl<R> Read for IoRead<R>
where R: io::Read
{
#[inline]
fn next(&mut self) -> io::Result<Option<u8>> {
self.delegate.next()
}

#[inline]
fn peek(&mut self) -> io::Result<Option<u8>> {
self.delegate.peek()
}

#[inline]
fn discard(&mut self) {
self.delegate.discard();
}

#[inline]
fn position(&self) -> Position {
self.delegate.position()
}

#[inline]
fn peek_position(&self) -> Position {
self.delegate.peek_position()
}

#[inline]
fn parse_str<'s>(
&'s mut self,
scratch: &'s mut Vec<u8>
) -> Result<&'s str> {
self.delegate.parse_str(scratch)
}

#[inline]
fn parse_str_raw<'s>(
&'s mut self,
scratch: &'s mut Vec<u8>
) -> Result<&'s [u8]> {
self.delegate.parse_str_raw(scratch)
}
}

//////////////////////////////////////////////////////////////////////////////

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,
Expand Down Expand Up @@ -362,6 +436,7 @@ impl<'a> Read 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()),
Expand Down

0 comments on commit af7f3f4

Please sign in to comment.