Introduce Serializer::collect_seq

This function serializes the given iterator as a sequence. Its iter parameter
has type I: IntoIterator, <I as IntoIterator>::Item: Serialize, which means it
will work both for iterators passed by value, therefore consuming them, and as
the value for a #[serde(serialize_with)] attribute, where it will be called as
Serializer::collect_seq(&self.field, serializer), relying on the common practice
of implementing IntoIterator for &C where C is a data type representing some
kind of collection.
This commit is contained in:
Anthony Ramine 2017-01-31 22:59:09 +01:00
parent ce230adf12
commit d00a895902

View File

@ -102,6 +102,7 @@ use error;
use core::cell::RefCell;
use core::fmt::Display;
use core::iter::IntoIterator;
mod impls;
mod impossible;
@ -242,7 +243,7 @@ pub trait Serialize {
/// is the `serde_json::value::Serializer` (distinct from the main `serde_json`
/// serializer) that produces a `serde_json::Value` data structure in memory as
/// output.
pub trait Serializer {
pub trait Serializer: Sized {
/// The output type produced by this `Serializer` during successful
/// serialization. Most serializers that produce text or binary output
/// should set `Ok = ()` and serialize into an `io::Write` or buffer
@ -607,6 +608,23 @@ pub trait Serializer {
variant: &'static str,
len: usize,
) -> 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(iterator_len_hint(&iter)));
for item in iter {
try!(serializer.serialize_element(&item));
}
serializer.end()
}
}
/// Returned from `Serializer::serialize_seq` and
@ -826,3 +844,10 @@ pub fn iterator<I>(iter: I) -> Iterator<I>
data: RefCell::new(Some(iter)),
}
}
fn iterator_len_hint<I: Iterator>(iter: &I) -> Option<usize> {
match iter.size_hint() {
(lo, Some(hi)) if lo == hi => Some(lo),
_ => None,
}
}