add wrapper to serde that allows serializing iterators as sequences
This commit is contained in:
parent
ca47eb929c
commit
dced4416a7
@ -30,7 +30,7 @@ extern crate alloc;
|
||||
#[cfg(feature = "std")]
|
||||
mod core {
|
||||
pub use std::{ops, hash, fmt, cmp, marker, mem, i8, i16, i32, i64, u8, u16, u32, u64, isize,
|
||||
usize, f32, f64, char, str, num, slice, iter};
|
||||
usize, f32, f64, char, str, num, slice, iter, cell};
|
||||
#[cfg(feature = "unstable")]
|
||||
extern crate core;
|
||||
#[cfg(feature = "unstable")]
|
||||
|
@ -70,6 +70,7 @@ use super::{
|
||||
Error,
|
||||
Serialize,
|
||||
Serializer,
|
||||
IteratorSerializer,
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -221,6 +222,33 @@ array_impls!(32);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
impl<'a, I> Serialize for IteratorSerializer<I>
|
||||
where I: Iterator, <I as Iterator>::Item: Serialize
|
||||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||
where S: Serializer,
|
||||
{
|
||||
// FIXME: use specialization to prevent invalidating the object in case of clonable iterators?
|
||||
let iter = match self.0.borrow_mut().take() {
|
||||
Some(iter) => iter,
|
||||
None => return Err(S::Error::custom("IteratorSerializer used twice")),
|
||||
};
|
||||
let size = match iter.size_hint() {
|
||||
(lo, Some(hi)) if lo == hi => Some(lo),
|
||||
_ => None,
|
||||
};
|
||||
let mut state = try!(serializer.serialize_seq(size));
|
||||
for e in iter {
|
||||
try!(serializer.serialize_seq_elt(&mut state, e));
|
||||
}
|
||||
serializer.serialize_seq_end(state)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! serialize_seq {
|
||||
() => {
|
||||
#[inline]
|
||||
|
@ -18,6 +18,9 @@ use error;
|
||||
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||
use collections::String;
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use core::cell::RefCell;
|
||||
|
||||
pub mod impls;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -410,3 +413,20 @@ pub trait Serializer {
|
||||
state: Self::StructVariantState,
|
||||
) -> Result<(), Self::Error>;
|
||||
}
|
||||
|
||||
|
||||
/// A wrapper type for iterators that implements `Serialize` for iterators whose items implement
|
||||
/// `Serialize`. Don't use multiple times. Create new versions of this with the `iterator` function
|
||||
/// every time you want to serialize an iterator.
|
||||
pub struct IteratorSerializer<I>(RefCell<Option<I>>)
|
||||
where <I as Iterator>::Item: Serialize,
|
||||
I: Iterator;
|
||||
|
||||
/// Creates a temporary type that can be passed to any function expecting a `Serialize` and will
|
||||
/// serialize the given iterator as a sequence
|
||||
pub fn iterator<I>(iter: I) -> IteratorSerializer<I>
|
||||
where <I as Iterator>::Item: Serialize,
|
||||
I: Iterator
|
||||
{
|
||||
IteratorSerializer(RefCell::new(Some(iter)))
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ use self::serde_test::{
|
||||
extern crate fnv;
|
||||
use self::fnv::FnvHasher;
|
||||
|
||||
use serde::ser::iterator;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Serialize)]
|
||||
@ -98,6 +100,45 @@ declare_ser_tests! {
|
||||
Token::I32(1),
|
||||
],
|
||||
}
|
||||
test_iterator {
|
||||
iterator([0; 0].iter()) => &[
|
||||
Token::SeqStart(Some(0)),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
iterator([1, 2, 3].iter()) => &[
|
||||
Token::SeqStart(Some(3)),
|
||||
Token::SeqSep,
|
||||
Token::I32(1),
|
||||
|
||||
Token::SeqSep,
|
||||
Token::I32(2),
|
||||
|
||||
Token::SeqSep,
|
||||
Token::I32(3),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
iterator([1, 2, 3].iter().map(|x| x * 2)) => &[
|
||||
Token::SeqStart(Some(3)),
|
||||
Token::SeqSep,
|
||||
Token::I32(2),
|
||||
|
||||
Token::SeqSep,
|
||||
Token::I32(4),
|
||||
|
||||
Token::SeqSep,
|
||||
Token::I32(6),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
iterator([1, 2, 3].iter().filter(|&x| x % 2 != 0)) => &[
|
||||
Token::SeqStart(None),
|
||||
Token::SeqSep,
|
||||
Token::I32(1),
|
||||
|
||||
Token::SeqSep,
|
||||
Token::I32(3),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
}
|
||||
test_slice {
|
||||
&[0][..0] => &[
|
||||
Token::SeqStart(Some(0)),
|
||||
|
Loading…
Reference in New Issue
Block a user