mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-13 23:01:01 +00:00
add wrapper to serde that allows serializing iterators as sequences
This commit is contained in:
+1
-1
@@ -30,7 +30,7 @@ extern crate alloc;
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
mod core {
|
mod core {
|
||||||
pub use std::{ops, hash, fmt, cmp, marker, mem, i8, i16, i32, i64, u8, u16, u32, u64, isize,
|
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")]
|
#[cfg(feature = "unstable")]
|
||||||
extern crate core;
|
extern crate core;
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ use super::{
|
|||||||
Error,
|
Error,
|
||||||
Serialize,
|
Serialize,
|
||||||
Serializer,
|
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 {
|
macro_rules! serialize_seq {
|
||||||
() => {
|
() => {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ use error;
|
|||||||
#[cfg(all(feature = "collections", not(feature = "std")))]
|
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||||
use collections::String;
|
use collections::String;
|
||||||
|
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
use core::cell::RefCell;
|
||||||
|
|
||||||
pub mod impls;
|
pub mod impls;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -410,3 +413,20 @@ pub trait Serializer {
|
|||||||
state: Self::StructVariantState,
|
state: Self::StructVariantState,
|
||||||
) -> Result<(), Self::Error>;
|
) -> 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;
|
extern crate fnv;
|
||||||
use self::fnv::FnvHasher;
|
use self::fnv::FnvHasher;
|
||||||
|
|
||||||
|
use serde::ser::iterator;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
@@ -98,6 +100,45 @@ declare_ser_tests! {
|
|||||||
Token::I32(1),
|
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 {
|
test_slice {
|
||||||
&[0][..0] => &[
|
&[0][..0] => &[
|
||||||
Token::SeqStart(Some(0)),
|
Token::SeqStart(Some(0)),
|
||||||
|
|||||||
Reference in New Issue
Block a user