diff --git a/.travis.yml b/.travis.yml index 81f8bd7..7123702 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,9 +5,9 @@ rust: - stable script: | cargo build --verbose && - cargo build --features=heapsizeof --verbose && + cargo build --all-features --verbose && cargo test --verbose && - cargo test --features=heapsizeof --verbose && + cargo test --all-features --verbose && ([ $TRAVIS_RUST_VERSION != nightly ] || cargo test --verbose --no-default-features) && ([ $TRAVIS_RUST_VERSION != nightly ] || cargo bench --verbose bench) notifications: diff --git a/Cargo.toml b/Cargo.toml index 5516116..6488521 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,3 +20,7 @@ path = "lib.rs" [dependencies] heapsize = { version = "0.4", optional = true } +serde = { version = "1", optional = true } + +[dev_dependencies] +bincode = "0.8" diff --git a/lib.rs b/lib.rs index 2a4e736..71a30f4 100644 --- a/lib.rs +++ b/lib.rs @@ -29,6 +29,9 @@ use alloc::Vec; #[cfg(feature="heapsizeof")] extern crate heapsize; +#[cfg(feature = "serde")] +extern crate serde; + #[cfg(not(feature = "std"))] mod std { pub use core::*; @@ -47,6 +50,12 @@ use std::slice; use std::io; #[cfg(feature="heapsizeof")] use std::os::raw::c_void; +#[cfg(feature = "serde")] +use serde::ser::{Serialize, Serializer, SerializeSeq}; +#[cfg(feature = "serde")] +use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; +#[cfg(feature = "serde")] +use std::marker::PhantomData; #[cfg(feature="heapsizeof")] use heapsize::{HeapSizeOf, heap_size_of}; @@ -713,6 +722,53 @@ impl> io::Write for SmallVec { } } +#[cfg(feature = "serde")] +impl Serialize for SmallVec where A::Item: Serialize { + fn serialize(&self, serializer: S) -> Result { + let mut state = serializer.serialize_seq(Some(self.len()))?; + for item in self { + state.serialize_element(&item)?; + } + state.end() + } +} + +#[cfg(feature = "serde")] +impl<'de, A: Array> Deserialize<'de> for SmallVec where A::Item: Deserialize<'de> { + fn deserialize>(deserializer: D) -> Result { + deserializer.deserialize_seq(SmallVecVisitor{phantom: PhantomData}) + } +} + +#[cfg(feature = "serde")] +struct SmallVecVisitor { + phantom: PhantomData +} + +#[cfg(feature = "serde")] +impl<'de, A: Array> Visitor<'de> for SmallVecVisitor +where A::Item: Deserialize<'de>, +{ + type Value = SmallVec; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a sequence") + } + + fn visit_seq(self, mut seq: B) -> Result + where + B: SeqAccess<'de>, + { + let mut values = SmallVec::new(); + + while let Some(value) = seq.next_element()? { + values.push(value); + } + + Ok(values) + } +} + impl<'a, A: Array> From<&'a [A::Item]> for SmallVec where A::Item: Clone { #[inline] fn from(slice: &'a [A::Item]) -> SmallVec { @@ -1549,4 +1605,25 @@ pub mod tests { small_vec.write_all(&data[..]).unwrap(); assert_eq!(small_vec.as_ref(), data.as_ref()); } + + extern crate bincode; + + #[cfg(feature = "serde")] + #[test] + fn test_serde() { + use self::bincode::{serialize, deserialize, Bounded}; + let mut small_vec: SmallVec<[i32; 2]> = SmallVec::new(); + small_vec.push(1); + let encoded = serialize(&small_vec, Bounded(100)).unwrap(); + let decoded: SmallVec<[i32; 2]> = deserialize(&encoded).unwrap(); + assert_eq!(small_vec, decoded); + small_vec.push(2); + // Spill the vec + small_vec.push(3); + small_vec.push(4); + // Check again after spilling. + let encoded = serialize(&small_vec, Bounded(100)).unwrap(); + let decoded: SmallVec<[i32; 2]> = deserialize(&encoded).unwrap(); + assert_eq!(small_vec, decoded); + } }