mirror of
https://github.com/serde-rs/json.git
synced 2026-04-18 20:56:02 +00:00
Remove deserialization from Iterator<Item = io::Result<u8>>
Use `from_reader` instead.
This commit is contained in:
@@ -75,8 +75,7 @@ enum Value {
|
||||
|
||||
A string of JSON data can be parsed into a `serde_json::Value` by the
|
||||
[`serde_json::from_str`][from_str] function. There is also
|
||||
[`from_slice`][from_slice] for parsing from a byte slice &[u8],
|
||||
[`from_iter`][from_iter] for parsing from an iterator of bytes, and
|
||||
[`from_slice`][from_slice] for parsing from a byte slice &[u8] and
|
||||
[`from_reader`][from_reader] for parsing from any `io::Read` like a File or
|
||||
a TCP stream.
|
||||
|
||||
@@ -323,7 +322,6 @@ be dual licensed as above, without any additional terms or conditions.
|
||||
[value]: https://docs.serde.rs/serde_json/value/enum.Value.html
|
||||
[from_str]: https://docs.serde.rs/serde_json/de/fn.from_str.html
|
||||
[from_slice]: https://docs.serde.rs/serde_json/de/fn.from_slice.html
|
||||
[from_iter]: https://docs.serde.rs/serde_json/de/fn.from_iter.html
|
||||
[from_reader]: https://docs.serde.rs/serde_json/de/fn.from_reader.html
|
||||
[to_string]: https://docs.serde.rs/serde_json/ser/fn.to_string.html
|
||||
[to_vec]: https://docs.serde.rs/serde_json/ser/fn.to_vec.html
|
||||
|
||||
33
src/de.rs
33
src/de.rs
@@ -18,7 +18,7 @@ use super::error::{Error, ErrorCode, Result};
|
||||
|
||||
use read::{self, Reference};
|
||||
|
||||
pub use read::{Read, IoRead, IteratorRead, SliceRead, StrRead};
|
||||
pub use read::{Read, IoRead, SliceRead, StrRead};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -40,7 +40,6 @@ where
|
||||
///
|
||||
/// - Deserializer::from_str
|
||||
/// - Deserializer::from_bytes
|
||||
/// - Deserializer::from_iter
|
||||
/// - Deserializer::from_reader
|
||||
pub fn new(read: R) -> Self {
|
||||
Deserializer {
|
||||
@@ -51,16 +50,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Deserializer<read::IteratorRead<I>>
|
||||
where
|
||||
I: Iterator<Item = io::Result<u8>>,
|
||||
{
|
||||
/// 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::IoRead<R>>
|
||||
where
|
||||
R: io::Read,
|
||||
@@ -1029,7 +1018,6 @@ where
|
||||
///
|
||||
/// - 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 {
|
||||
let offset = read.byte_offset();
|
||||
@@ -1122,23 +1110,6 @@ where
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
/// Deserialize an instance of type `T` from an iterator over bytes of JSON.
|
||||
///
|
||||
/// This conversion can fail if the structure of the Value does not match the
|
||||
/// structure expected by `T`, for example if `T` is a struct type but the Value
|
||||
/// contains something other than a JSON map. It can also fail if the structure
|
||||
/// is correct but `T`'s implementation of `Deserialize` decides that something
|
||||
/// is wrong with the data, for example required struct fields are missing from
|
||||
/// the JSON map or some number is too big to fit in the expected primitive
|
||||
/// type.
|
||||
pub fn from_iter<I, T>(iter: I) -> Result<T>
|
||||
where
|
||||
I: Iterator<Item = io::Result<u8>>,
|
||||
T: de::DeserializeOwned,
|
||||
{
|
||||
from_trait(read::IteratorRead::new(iter))
|
||||
}
|
||||
|
||||
/// Deserialize an instance of type `T` from an IO stream of JSON.
|
||||
///
|
||||
/// This conversion can fail if the structure of the Value does not match the
|
||||
@@ -1153,7 +1124,7 @@ where
|
||||
R: io::Read,
|
||||
T: de::DeserializeOwned,
|
||||
{
|
||||
from_iter(rdr.bytes())
|
||||
from_trait(read::IoRead::new(rdr))
|
||||
}
|
||||
|
||||
/// Deserialize an instance of type `T` from bytes of JSON text.
|
||||
|
||||
@@ -64,8 +64,7 @@
|
||||
//!
|
||||
//! A string of JSON data can be parsed into a `serde_json::Value` by the
|
||||
//! [`serde_json::from_str`][from_str] function. There is also
|
||||
//! [`from_slice`][from_slice] for parsing from a byte slice &[u8],
|
||||
//! [`from_iter`][from_iter] for parsing from an iterator of bytes, and
|
||||
//! [`from_slice`][from_slice] for parsing from a byte slice &[u8] and
|
||||
//! [`from_reader`][from_reader] for parsing from any `io::Read` like a File or
|
||||
//! a TCP stream.
|
||||
//!
|
||||
@@ -287,7 +286,6 @@
|
||||
//! [value]: https://docs.serde.rs/serde_json/value/enum.Value.html
|
||||
//! [from_str]: https://docs.serde.rs/serde_json/de/fn.from_str.html
|
||||
//! [from_slice]: https://docs.serde.rs/serde_json/de/fn.from_slice.html
|
||||
//! [from_iter]: https://docs.serde.rs/serde_json/de/fn.from_iter.html
|
||||
//! [from_reader]: https://docs.serde.rs/serde_json/de/fn.from_reader.html
|
||||
//! [to_string]: https://docs.serde.rs/serde_json/ser/fn.to_string.html
|
||||
//! [to_vec]: https://docs.serde.rs/serde_json/ser/fn.to_vec.html
|
||||
@@ -300,7 +298,7 @@
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(doc_markdown))]
|
||||
// Whitelisted clippy_pedantic lints
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(
|
||||
// Deserializer::from_str, from_iter, into_iter
|
||||
// Deserializer::from_str, into_iter
|
||||
should_implement_trait,
|
||||
// integer and float ser/de requires these sorts of casts
|
||||
cast_possible_truncation,
|
||||
@@ -330,7 +328,7 @@ extern crate dtoa;
|
||||
extern crate linked_hash_map;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use self::de::{Deserializer, StreamDeserializer, from_iter, from_reader, from_slice, from_str};
|
||||
pub use self::de::{Deserializer, StreamDeserializer, from_reader, from_slice, from_str};
|
||||
#[doc(inline)]
|
||||
pub use self::error::{Error, Result};
|
||||
#[doc(inline)]
|
||||
|
||||
110
src/read.rs
110
src/read.rs
@@ -82,22 +82,14 @@ pub enum Reference<'b, 'c, T: ?Sized + 'static> {
|
||||
Copied(&'c T),
|
||||
}
|
||||
|
||||
/// JSON input source that reads from an iterator of bytes.
|
||||
pub struct IteratorRead<Iter>
|
||||
where
|
||||
Iter: Iterator<Item = io::Result<u8>>,
|
||||
{
|
||||
iter: LineColIterator<Iter>,
|
||||
/// Temporary storage of peeked byte.
|
||||
ch: Option<u8>,
|
||||
}
|
||||
|
||||
/// JSON input source that reads from a std::io input stream.
|
||||
pub struct IoRead<R>
|
||||
where
|
||||
R: io::Read,
|
||||
{
|
||||
delegate: IteratorRead<io::Bytes<R>>,
|
||||
iter: LineColIterator<io::Bytes<R>>,
|
||||
/// Temporary storage of peeked byte.
|
||||
ch: Option<u8>,
|
||||
}
|
||||
|
||||
/// JSON input source that reads from a slice of bytes.
|
||||
@@ -124,28 +116,28 @@ mod private {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl<Iter> IteratorRead<Iter>
|
||||
impl<R> IoRead<R>
|
||||
where
|
||||
Iter: Iterator<Item = io::Result<u8>>,
|
||||
R: io::Read,
|
||||
{
|
||||
/// Create a JSON input source to read from an iterator of bytes.
|
||||
pub fn new(iter: Iter) -> Self {
|
||||
IteratorRead {
|
||||
iter: LineColIterator::new(iter),
|
||||
/// 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Iter> private::Sealed for IteratorRead<Iter>
|
||||
impl<R> private::Sealed for IoRead<R>
|
||||
where
|
||||
Iter: Iterator<Item = io::Result<u8>>,
|
||||
R: io::Read,
|
||||
{
|
||||
}
|
||||
|
||||
impl<Iter> IteratorRead<Iter>
|
||||
impl<R> IoRead<R>
|
||||
where
|
||||
Iter: Iterator<Item = io::Result<u8>>,
|
||||
R: io::Read,
|
||||
{
|
||||
fn parse_str_bytes<'s, T, F>(
|
||||
&'s mut self,
|
||||
@@ -181,9 +173,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, Iter> Read<'de> for IteratorRead<Iter>
|
||||
impl<'de, R> Read<'de> for IoRead<R>
|
||||
where
|
||||
Iter: Iterator<Item = io::Result<u8>>,
|
||||
R: io::Read,
|
||||
{
|
||||
#[inline]
|
||||
fn next(&mut self) -> io::Result<Option<u8>> {
|
||||
@@ -257,72 +249,6 @@ where
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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<'de, R> Read<'de> 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 byte_offset(&self) -> usize {
|
||||
self.delegate.byte_offset()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_str<'s>(&'s mut self, scratch: &'s mut Vec<u8>) -> Result<Reference<'de, 's, str>> {
|
||||
self.delegate.parse_str(scratch)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_str_raw<'s>(
|
||||
&'s mut self,
|
||||
scratch: &'s mut Vec<u8>,
|
||||
) -> Result<Reference<'de, '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 {
|
||||
@@ -348,9 +274,9 @@ impl<'a> SliceRead<'a> {
|
||||
pos
|
||||
}
|
||||
|
||||
/// The big optimization here over IteratorRead is that if the string
|
||||
/// contains no backslash escape sequences, the returned &str is a slice of
|
||||
/// the raw JSON data so we avoid copying into the scratch space.
|
||||
/// The big optimization here over IoRead is that if the string contains no
|
||||
/// backslash escape sequences, the returned &str is a slice of the raw JSON
|
||||
/// data so we avoid copying into the scratch space.
|
||||
fn parse_str_bytes<'s, T: ?Sized, F>(
|
||||
&'s mut self,
|
||||
scratch: &'s mut Vec<u8>,
|
||||
|
||||
@@ -68,8 +68,7 @@
|
||||
//!
|
||||
//! A string of JSON data can be parsed into a `serde_json::Value` by the
|
||||
//! [`serde_json::from_str`][from_str] function. There is also
|
||||
//! [`from_slice`][from_slice] for parsing from a byte slice &[u8],
|
||||
//! [`from_iter`][from_iter] for parsing from an iterator of bytes, and
|
||||
//! [`from_slice`][from_slice] for parsing from a byte slice &[u8] and
|
||||
//! [`from_reader`][from_reader] for parsing from any `io::Read` like a File or
|
||||
//! a TCP stream.
|
||||
//!
|
||||
@@ -106,7 +105,6 @@
|
||||
//! [macro]: https://docs.serde.rs/serde_json/macro.json.html
|
||||
//! [from_str]: https://docs.serde.rs/serde_json/de/fn.from_str.html
|
||||
//! [from_slice]: https://docs.serde.rs/serde_json/de/fn.from_slice.html
|
||||
//! [from_iter]: https://docs.serde.rs/serde_json/de/fn.from_iter.html
|
||||
//! [from_reader]: https://docs.serde.rs/serde_json/de/fn.from_reader.html
|
||||
|
||||
use std::fmt;
|
||||
|
||||
@@ -29,12 +29,6 @@ macro_rules! test_stream {
|
||||
assert_eq!($stream.byte_offset(), 0);
|
||||
$test
|
||||
}
|
||||
{
|
||||
let de = Deserializer::from_iter($data.bytes().map(Ok));
|
||||
let mut $stream = de.into_iter::<$ty>();
|
||||
assert_eq!($stream.byte_offset(), 0);
|
||||
$test
|
||||
}
|
||||
{
|
||||
let mut bytes = $data.as_bytes();
|
||||
let de = Deserializer::from_reader(&mut bytes);
|
||||
|
||||
@@ -39,7 +39,7 @@ use serde::ser::{self, Serialize, Serializer};
|
||||
|
||||
use serde_bytes::{ByteBuf, Bytes};
|
||||
|
||||
use serde_json::{Deserializer, Value, from_iter, from_reader, from_slice, from_str, from_value,
|
||||
use serde_json::{Deserializer, Value, from_reader, from_slice, from_str, from_value,
|
||||
to_string, to_string_pretty, to_value, to_vec, to_writer};
|
||||
|
||||
macro_rules! treemap {
|
||||
@@ -606,9 +606,6 @@ where
|
||||
let v: T = from_slice(s.as_bytes()).unwrap();
|
||||
assert_eq!(v, value.clone());
|
||||
|
||||
let v: T = from_iter(s.bytes().map(Ok)).unwrap();
|
||||
assert_eq!(v, value.clone());
|
||||
|
||||
// Make sure we can deserialize into a `Value`.
|
||||
let json_value: Value = from_str(s).unwrap();
|
||||
assert_eq!(json_value, to_value(&value).unwrap());
|
||||
@@ -639,9 +636,6 @@ where
|
||||
|
||||
let v: T = from_slice(s.as_bytes()).unwrap();
|
||||
assert_eq!(v, value.clone());
|
||||
|
||||
let v: T = from_iter(s.bytes().map(Ok)).unwrap();
|
||||
assert_eq!(v, value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,7 +653,6 @@ where
|
||||
for &(s, err) in errors {
|
||||
test_parse_err!(from_str::<T>(s) => err);
|
||||
test_parse_err!(from_slice::<T>(s.as_bytes()) => err);
|
||||
test_parse_err!(from_iter::<_, T>(s.bytes().map(Ok)) => err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -669,7 +662,6 @@ where
|
||||
{
|
||||
for &(s, err) in errors {
|
||||
test_parse_err!(from_slice::<T>(s) => err);
|
||||
test_parse_err!(from_iter::<_, T>(s.iter().cloned().map(Ok)) => err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1694,57 +1686,6 @@ fn test_allow_ser_integers_as_map_keys() {
|
||||
assert_eq!(to_string(&map).unwrap(), r#"{"-2":8,"-1":6,"1":2,"2":4}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_iter_unfused() {
|
||||
// Test that iterator isn't called after EOF.
|
||||
|
||||
use std;
|
||||
|
||||
struct Source<I: Iterator<Item = u8>> {
|
||||
iter: I,
|
||||
finished: bool,
|
||||
}
|
||||
|
||||
impl<I: Iterator<Item = u8>> Iterator for Source<I> {
|
||||
type Item = std::io::Result<u8>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
assert!(!self.finished, "next() called after iterator EOF");
|
||||
|
||||
match self.iter.next() {
|
||||
Some(b) => Some(Ok(b)),
|
||||
None => {
|
||||
self.finished = true;
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Message {
|
||||
key: u32,
|
||||
}
|
||||
|
||||
let msg: Message = from_iter(
|
||||
Source {
|
||||
iter: b"{\"key\": 1337}".iter().cloned(),
|
||||
finished: false,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(msg.key, 1337);
|
||||
|
||||
let msg: Message = from_iter(
|
||||
Source {
|
||||
iter: b"{\"key\": 1337} \t\t ".iter().cloned(),
|
||||
finished: false,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(msg.key, 1337);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_json_macro() {
|
||||
// This is tricky because the <...> is not a single TT and the comma inside
|
||||
|
||||
Reference in New Issue
Block a user