Add Serde support (#110)

* Add Serde support.

* Removes `serde/alloc` from deps( tests still pass without it anyways)

* Fix some issues that could result in a panic.

* Wait, actually use the size_hint properly.

* Error instead of silent truncation.

* That wasn't meant to be a default feature.
This commit is contained in:
aspen
2020-08-17 09:39:29 -04:00
committed by GitHub
parent c9d373ceaf
commit 1dbf6bfe73
6 changed files with 237 additions and 0 deletions
+78
View File
@@ -1,6 +1,15 @@
use super::*;
use core::convert::TryInto;
#[cfg(feature = "serde")]
use core::marker::PhantomData;
#[cfg(feature = "serde")]
use serde::de::{
Deserialize, Deserializer, Error as DeserializeError, SeqAccess, Visitor,
};
#[cfg(feature = "serde")]
use serde::ser::{Serialize, SerializeSeq, Serializer};
/// Helper to make an `ArrayVec`.
///
/// You specify the backing array type, and optionally give all the elements you
@@ -130,6 +139,38 @@ impl<A: Array, I: SliceIndex<[A::Item]>> IndexMut<I> for ArrayVec<A> {
}
}
#[cfg(feature = "serde")]
impl<A: Array> Serialize for ArrayVec<A>
where
A::Item: Serialize,
{
#[must_use]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(self.len()))?;
for element in self.iter() {
seq.serialize_element(element)?;
}
seq.end()
}
}
#[cfg(feature = "serde")]
impl<'de, A: Array> Deserialize<'de> for ArrayVec<A>
where
A: Default,
A::Item: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(ArrayVecVisitor(PhantomData))
}
}
impl<A: Array> ArrayVec<A> {
/// Move all values from `other` into this vec.
///
@@ -1502,3 +1543,40 @@ impl<A: Array> ArrayVec<A> {
self.drain_to_vec_and_reserve(0)
}
}
#[cfg(feature = "serde")]
struct ArrayVecVisitor<A: Array>(PhantomData<A>);
#[cfg(feature = "serde")]
impl<'de, A: Array> Visitor<'de> for ArrayVecVisitor<A>
where
A: Default,
A::Item: Deserialize<'de>,
{
type Value = ArrayVec<A>;
fn expecting(
&self,
formatter: &mut core::fmt::Formatter,
) -> core::fmt::Result {
formatter.write_str("a sequence")
}
fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
where
S: SeqAccess<'de>,
{
let mut new_arrayvec: ArrayVec<A> = Default::default();
let mut idx = 0usize;
while let Some(value) = seq.next_element()? {
if new_arrayvec.len() >= new_arrayvec.capacity() {
return Err(DeserializeError::invalid_length(idx, &self));
}
new_arrayvec.push(value);
idx = idx + 1;
}
Ok(new_arrayvec)
}
}
+3
View File
@@ -39,6 +39,9 @@
//! ArrayVec.
//! * `rustc_1_40` makes the crate assume a minimum rust version of `1.40.0`,
//! which allows some better internal optimizations.
//! * `serde` provides a `Serialize` and `Deserialize` implementation for
//! [`TinyVec`] and [`ArrayVec`] types, provided the inner item also
//! has an implementation.
//!
//! ## API
//! The general goal of the crate is that, as much as possible, the vecs here
+74
View File
@@ -5,6 +5,13 @@ use super::*;
use alloc::vec::{self, Vec};
use tinyvec_macros::impl_mirrored;
#[cfg(feature = "serde")]
use core::marker::PhantomData;
#[cfg(feature = "serde")]
use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
#[cfg(feature = "serde")]
use serde::ser::{Serialize, SerializeSeq, Serializer};
/// Helper to make a `TinyVec`.
///
/// You specify the backing array type, and optionally give all the elements you
@@ -136,6 +143,38 @@ impl<A: Array, I: SliceIndex<[A::Item]>> IndexMut<I> for TinyVec<A> {
}
}
#[cfg(feature = "serde")]
impl<A: Array> Serialize for TinyVec<A>
where
A::Item: Serialize,
{
#[must_use]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(self.len()))?;
for element in self.iter() {
seq.serialize_element(element)?;
}
seq.end()
}
}
#[cfg(feature = "serde")]
impl<'de, A: Array> Deserialize<'de> for TinyVec<A>
where
A: Default,
A::Item: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(TinyVecVisitor(PhantomData))
}
}
impl<A: Array> TinyVec<A> {
/// Returns whether elements are on heap
#[inline(always)]
@@ -1411,3 +1450,38 @@ where
write!(f, "]")
}
}
#[cfg(feature = "serde")]
struct TinyVecVisitor<A: Array>(PhantomData<A>);
#[cfg(feature = "serde")]
impl<'de, A: Array> Visitor<'de> for TinyVecVisitor<A>
where
A: Default,
A::Item: Deserialize<'de>,
{
type Value = TinyVec<A>;
fn expecting(
&self,
formatter: &mut core::fmt::Formatter,
) -> core::fmt::Result {
formatter.write_str("a sequence")
}
fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
where
S: SeqAccess<'de>,
{
let mut new_tinyvec = match seq.size_hint() {
Some(expected_size) => TinyVec::with_capacity(expected_size),
None => Default::default(),
};
while let Some(value) = seq.next_element()? {
new_tinyvec.push(value);
}
Ok(new_tinyvec)
}
}