mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-15 13:11:01 +00:00
Merge pull request #736 from nox/serialize-iter
Introduce collect_seq and collect_map
This commit is contained in:
+1
-1
@@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
#![doc(html_root_url="https://docs.serde.rs")]
|
#![doc(html_root_url="https://docs.serde.rs")]
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
#![cfg_attr(feature = "unstable", feature(nonzero, inclusive_range, zero_one))]
|
#![cfg_attr(feature = "unstable", feature(inclusive_range, nonzero, specialization, zero_one))]
|
||||||
#![cfg_attr(feature = "alloc", feature(alloc))]
|
#![cfg_attr(feature = "alloc", feature(alloc))]
|
||||||
#![cfg_attr(feature = "collections", feature(collections))]
|
#![cfg_attr(feature = "collections", feature(collections))]
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(linkedlist, type_complexity, doc_markdown))]
|
#![cfg_attr(feature = "cargo-clippy", allow(linkedlist, type_complexity, doc_markdown))]
|
||||||
|
|||||||
+32
-48
@@ -66,9 +66,6 @@ use super::{
|
|||||||
#[cfg(any(feature = "std", feature = "unstable"))]
|
#[cfg(any(feature = "std", feature = "unstable"))]
|
||||||
use super::Error;
|
use super::Error;
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
|
||||||
use super::Iterator;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
macro_rules! impl_visit {
|
macro_rules! impl_visit {
|
||||||
@@ -147,24 +144,6 @@ impl<T> Serialize for PhantomData<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
impl<T> Serialize for [T]
|
|
||||||
where T: Serialize,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where S: Serializer,
|
|
||||||
{
|
|
||||||
let mut seq = try!(serializer.serialize_seq(Some(self.len())));
|
|
||||||
for e in self {
|
|
||||||
try!(seq.serialize_element(e));
|
|
||||||
}
|
|
||||||
seq.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
macro_rules! array_impls {
|
macro_rules! array_impls {
|
||||||
@@ -220,33 +199,7 @@ array_impls!(32);
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(not(feature = "unstable"))]
|
||||||
impl<'a, I> Serialize for Iterator<I>
|
|
||||||
where I: IntoIterator, <I as IntoIterator>::Item: Serialize
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where S: Serializer,
|
|
||||||
{
|
|
||||||
// FIXME: use specialization to prevent invalidating the object in case of clonable iterators?
|
|
||||||
let iter = match self.data.borrow_mut().take() {
|
|
||||||
Some(iter) => iter.into_iter(),
|
|
||||||
None => return Err(Error::custom("Iterator used twice")),
|
|
||||||
};
|
|
||||||
let size = match iter.size_hint() {
|
|
||||||
(lo, Some(hi)) if lo == hi => Some(lo),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
let mut seq = try!(serializer.serialize_seq(size));
|
|
||||||
for e in iter {
|
|
||||||
try!(seq.serialize_element(&e));
|
|
||||||
}
|
|
||||||
seq.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
macro_rules! serialize_seq {
|
macro_rules! serialize_seq {
|
||||||
() => {
|
() => {
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -262,6 +215,24 @@ macro_rules! serialize_seq {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "unstable")]
|
||||||
|
macro_rules! serialize_seq {
|
||||||
|
() => {
|
||||||
|
#[inline]
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.collect_seq(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Serialize for [T]
|
||||||
|
where T: Serialize,
|
||||||
|
{
|
||||||
|
serialize_seq!();
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "collections"))]
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<T> Serialize for BinaryHeap<T>
|
impl<T> Serialize for BinaryHeap<T>
|
||||||
where T: Serialize + Ord
|
where T: Serialize + Ord
|
||||||
@@ -550,6 +521,7 @@ tuple_impls! {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(not(feature = "unstable"))]
|
||||||
macro_rules! serialize_map {
|
macro_rules! serialize_map {
|
||||||
() => {
|
() => {
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -566,6 +538,18 @@ macro_rules! serialize_map {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "unstable")]
|
||||||
|
macro_rules! serialize_map {
|
||||||
|
() => {
|
||||||
|
#[inline]
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.collect_map(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "collections"))]
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<K, V> Serialize for BTreeMap<K, V>
|
impl<K, V> Serialize for BTreeMap<K, V>
|
||||||
where K: Serialize + Ord,
|
where K: Serialize + Ord,
|
||||||
|
|||||||
+62
-23
@@ -98,10 +98,8 @@ use std::error;
|
|||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
use error;
|
use error;
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
|
||||||
use core::cell::RefCell;
|
|
||||||
|
|
||||||
use core::fmt::Display;
|
use core::fmt::Display;
|
||||||
|
use core::iter::IntoIterator;
|
||||||
|
|
||||||
mod impls;
|
mod impls;
|
||||||
mod impossible;
|
mod impossible;
|
||||||
@@ -242,7 +240,7 @@ pub trait Serialize {
|
|||||||
/// is the `serde_json::value::Serializer` (distinct from the main `serde_json`
|
/// is the `serde_json::value::Serializer` (distinct from the main `serde_json`
|
||||||
/// serializer) that produces a `serde_json::Value` data structure in memory as
|
/// serializer) that produces a `serde_json::Value` data structure in memory as
|
||||||
/// output.
|
/// output.
|
||||||
pub trait Serializer {
|
pub trait Serializer: Sized {
|
||||||
/// The output type produced by this `Serializer` during successful
|
/// The output type produced by this `Serializer` during successful
|
||||||
/// serialization. Most serializers that produce text or binary output
|
/// serialization. Most serializers that produce text or binary output
|
||||||
/// should set `Ok = ()` and serialize into an `io::Write` or buffer
|
/// should set `Ok = ()` and serialize into an `io::Write` or buffer
|
||||||
@@ -607,6 +605,41 @@ pub trait Serializer {
|
|||||||
variant: &'static str,
|
variant: &'static str,
|
||||||
len: usize,
|
len: usize,
|
||||||
) -> Result<Self::SerializeStructVariant, Self::Error>;
|
) -> Result<Self::SerializeStructVariant, Self::Error>;
|
||||||
|
|
||||||
|
/// Collect an iterator as a sequence.
|
||||||
|
///
|
||||||
|
/// The default implementation serializes each item yielded by the iterator
|
||||||
|
/// using `Self::SerializeSeq`. Implementors should not need to override
|
||||||
|
/// this method.
|
||||||
|
fn collect_seq<I>(self, iter: I) -> Result<Self::Ok, Self::Error>
|
||||||
|
where I: IntoIterator,
|
||||||
|
<I as IntoIterator>::Item: Serialize,
|
||||||
|
{
|
||||||
|
let iter = iter.into_iter();
|
||||||
|
let mut serializer = try!(self.serialize_seq(iter.len_hint()));
|
||||||
|
for item in iter {
|
||||||
|
try!(serializer.serialize_element(&item));
|
||||||
|
}
|
||||||
|
serializer.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collect an iterator as a map.
|
||||||
|
///
|
||||||
|
/// The default implementation serializes each pair yielded by the iterator
|
||||||
|
/// using `Self::SerializeMap`. Implementors should not need to override
|
||||||
|
/// this method.
|
||||||
|
fn collect_map<K, V, I>(self, iter: I) -> Result<Self::Ok, Self::Error>
|
||||||
|
where K: Serialize,
|
||||||
|
V: Serialize,
|
||||||
|
I: IntoIterator<Item = (K, V)>,
|
||||||
|
{
|
||||||
|
let iter = iter.into_iter();
|
||||||
|
let mut serializer = try!(self.serialize_map(iter.len_hint()));
|
||||||
|
for (key, value) in iter {
|
||||||
|
try!(serializer.serialize_entry(&key, &value));
|
||||||
|
}
|
||||||
|
serializer.end()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returned from `Serializer::serialize_seq` and
|
/// Returned from `Serializer::serialize_seq` and
|
||||||
@@ -803,26 +836,32 @@ pub trait SerializeStructVariant {
|
|||||||
fn end(self) -> Result<Self::Ok, Self::Error>;
|
fn end(self) -> Result<Self::Ok, Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper type for iterators that implements `Serialize` for iterators whose
|
trait LenHint: Iterator {
|
||||||
/// items implement `Serialize`. Don't use multiple times. Create new versions
|
fn len_hint(&self) -> Option<usize>;
|
||||||
/// of this with the `serde::ser::iterator` function every time you want to
|
|
||||||
/// serialize an iterator.
|
|
||||||
#[cfg(feature = "unstable")]
|
|
||||||
pub struct Iterator<I>
|
|
||||||
where <I as IntoIterator>::Item: Serialize,
|
|
||||||
I: IntoIterator
|
|
||||||
{
|
|
||||||
data: RefCell<Option<I>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a wrapper type that can be passed to any function expecting a
|
impl<I: Iterator> LenHint for I {
|
||||||
/// `Serialize` and will serialize the given iterator as a sequence.
|
#[cfg(not(feature = "unstable"))]
|
||||||
#[cfg(feature = "unstable")]
|
fn len_hint(&self) -> Option<usize> {
|
||||||
pub fn iterator<I>(iter: I) -> Iterator<I>
|
iterator_len_hint(self)
|
||||||
where <I as IntoIterator>::Item: Serialize,
|
}
|
||||||
I: IntoIterator
|
|
||||||
{
|
#[cfg(feature = "unstable")]
|
||||||
Iterator {
|
default fn len_hint(&self) -> Option<usize> {
|
||||||
data: RefCell::new(Some(iter)),
|
iterator_len_hint(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "unstable")]
|
||||||
|
impl<I: ExactSizeIterator> LenHint for I {
|
||||||
|
fn len_hint(&self) -> Option<usize> {
|
||||||
|
Some(self.len())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iterator_len_hint<I: Iterator>(iter: &I) -> Option<usize> {
|
||||||
|
match iter.size_hint() {
|
||||||
|
(lo, Some(hi)) if lo == hi => Some(lo),
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user