Augment builtin std/core Deserialize impls to implement deserialize_from

This commit is contained in:
Alexis Beingessner
2017-11-13 13:38:27 -05:00
parent ab5e8780ab
commit bc221abb04
2 changed files with 304 additions and 53 deletions
+286 -52
View File
@@ -15,6 +15,7 @@ use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, Va
use de::MapAccess; use de::MapAccess;
use de::from_primitive::FromPrimitive; use de::from_primitive::FromPrimitive;
use private::de::DeserializeFromSeed;
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
use private::de::size_hint; use private::de::size_hint;
@@ -51,6 +52,7 @@ impl<'de> Deserialize<'de> for () {
struct BoolVisitor; struct BoolVisitor;
impl<'de> Visitor<'de> for BoolVisitor { impl<'de> Visitor<'de> for BoolVisitor {
type Value = bool; type Value = bool;
@@ -210,6 +212,8 @@ impl<'de> Deserialize<'de> for char {
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
struct StringVisitor; struct StringVisitor;
#[cfg(any(feature = "std", feature = "alloc"))]
struct StringFromVisitor<'a>(&'a mut String);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de> Visitor<'de> for StringVisitor { impl<'de> Visitor<'de> for StringVisitor {
@@ -254,6 +258,59 @@ impl<'de> Visitor<'de> for StringVisitor {
} }
} }
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, 'de> Visitor<'de> for StringFromVisitor<'a> {
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string")
}
fn visit_str<E>(self, v: &str) -> Result<(), E>
where
E: Error,
{
self.0.clear();
self.0.push_str(v);
Ok(())
}
fn visit_string<E>(self, v: String) -> Result<(), E>
where
E: Error,
{
*self.0 = v;
Ok(())
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<(), E>
where
E: Error,
{
match str::from_utf8(v) {
Ok(s) => {
self.0.clear();
self.0.push_str(s);
Ok(())
}
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
}
}
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<(), E>
where
E: Error,
{
match String::from_utf8(v) {
Ok(s) => {
*self.0 = s;
Ok(())
}
Err(e) => Err(Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self),),
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de> Deserialize<'de> for String { impl<'de> Deserialize<'de> for String {
fn deserialize<D>(deserializer: D) -> Result<String, D::Error> fn deserialize<D>(deserializer: D) -> Result<String, D::Error>
@@ -262,6 +319,13 @@ impl<'de> Deserialize<'de> for String {
{ {
deserializer.deserialize_string(StringVisitor) deserializer.deserialize_string(StringVisitor)
} }
fn deserialize_from<D>(&mut self, deserializer: D) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_string(StringFromVisitor(self))
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -421,6 +485,7 @@ forwarded_impl!((), Box<CStr>, CString::into_boxed_c_str);
struct OptionVisitor<T> { struct OptionVisitor<T> {
marker: PhantomData<T>, marker: PhantomData<T>,
} }
struct OptionFromVisitor<'a, T: 'a>(&'a mut Option<T>);
impl<'de, T> Visitor<'de> for OptionVisitor<T> impl<'de, T> Visitor<'de> for OptionVisitor<T>
where where
@@ -457,6 +522,49 @@ where
} }
} }
impl<'a, 'de, T> Visitor<'de> for OptionFromVisitor<'a, T>
where
T: Deserialize<'de>,
{
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("option")
}
#[inline]
fn visit_unit<E>(self) -> Result<(), E>
where
E: Error,
{
*self.0 = None;
Ok(())
}
#[inline]
fn visit_none<E>(self) -> Result<(), E>
where
E: Error,
{
*self.0 = None;
Ok(())
}
#[inline]
fn visit_some<D>(self, deserializer: D) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
// The some enum's repr is opaque, so we can't play cute tricks with
// its tag to build this in place unconditionally.
//
// FIXME: investigate whether branching on the old value being Some to
// deserialize_from the value is profitable (probably data-dependent?)
*self.0 = try!(T::deserialize(deserializer).map(Some));
Ok(())
}
}
impl<'de, T> Deserialize<'de> for Option<T> impl<'de, T> Deserialize<'de> for Option<T>
where where
T: Deserialize<'de>, T: Deserialize<'de>,
@@ -467,6 +575,13 @@ where
{ {
deserializer.deserialize_option(OptionVisitor { marker: PhantomData }) deserializer.deserialize_option(OptionVisitor { marker: PhantomData })
} }
fn deserialize_from<D>(&mut self, deserializer: D) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_option(OptionFromVisitor(self))
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -509,7 +624,9 @@ macro_rules! seq_impl {
$ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, $ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >,
$access:ident, $access:ident,
$ctor:expr, $ctor:expr,
$clear:expr,
$with_capacity:expr, $with_capacity:expr,
$reserve:expr,
$insert:expr $insert:expr
) => { ) => {
impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty<T $(, $typaram)*> impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty<T $(, $typaram)*>
@@ -554,16 +671,59 @@ macro_rules! seq_impl {
let visitor = SeqVisitor { marker: PhantomData }; let visitor = SeqVisitor { marker: PhantomData };
deserializer.deserialize_seq(visitor) deserializer.deserialize_seq(visitor)
} }
fn deserialize_from<D>(&mut self, deserializer: D) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
struct SeqVisitor<'a, T: 'a $(, $typaram: 'a)*>(&'a mut $ty<T $(, $typaram)*>);
impl<'a, 'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor<'a, T $(, $typaram)*>
where
T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*,
$($typaram: $bound1 $(+ $bound2)*,)*
{
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a sequence")
}
#[inline]
fn visit_seq<A>(mut self, mut $access: A) -> Result<(), A::Error>
where
A: SeqAccess<'de>,
{
$clear(&mut self.0);
$reserve(&mut self.0, size_hint::cautious($access.size_hint()));
// FIXME: try to overwrite old values here? (Vec, VecDeque, LinkedList)
while let Some(value) = try!($access.next_element()) {
$insert(&mut self.0, value);
}
Ok(())
}
}
deserializer.deserialize_seq(SeqVisitor(self))
}
} }
} }
} }
// Dummy impl of reserve
#[cfg(any(feature = "std", feature = "alloc"))]
fn nop_reserve<T, U>(_x: T, _y: U) { }
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
BinaryHeap<T: Ord>, BinaryHeap<T: Ord>,
seq, seq,
BinaryHeap::new(), BinaryHeap::new(),
BinaryHeap::clear,
BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())), BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())),
BinaryHeap::reserve,
BinaryHeap::push); BinaryHeap::push);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
@@ -571,7 +731,9 @@ seq_impl!(
BTreeSet<T: Eq + Ord>, BTreeSet<T: Eq + Ord>,
seq, seq,
BTreeSet::new(), BTreeSet::new(),
BTreeSet::clear,
BTreeSet::new(), BTreeSet::new(),
nop_reserve,
BTreeSet::insert); BTreeSet::insert);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
@@ -579,7 +741,9 @@ seq_impl!(
LinkedList<T>, LinkedList<T>,
seq, seq,
LinkedList::new(), LinkedList::new(),
LinkedList::clear,
LinkedList::new(), LinkedList::new(),
nop_reserve,
LinkedList::push_back); LinkedList::push_back);
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -587,7 +751,9 @@ seq_impl!(
HashSet<T: Eq + Hash, S: BuildHasher + Default>, HashSet<T: Eq + Hash, S: BuildHasher + Default>,
seq, seq,
HashSet::with_hasher(S::default()), HashSet::with_hasher(S::default()),
HashSet::clear,
HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()), HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
HashSet::reserve,
HashSet::insert); HashSet::insert);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
@@ -595,7 +761,9 @@ seq_impl!(
Vec<T>, Vec<T>,
seq, seq,
Vec::new(), Vec::new(),
Vec::clear,
Vec::with_capacity(size_hint::cautious(seq.size_hint())), Vec::with_capacity(size_hint::cautious(seq.size_hint())),
Vec::reserve,
Vec::push); Vec::push);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
@@ -603,7 +771,9 @@ seq_impl!(
VecDeque<T>, VecDeque<T>,
seq, seq,
VecDeque::new(), VecDeque::new(),
VecDeque::clear,
VecDeque::with_capacity(size_hint::cautious(seq.size_hint())), VecDeque::with_capacity(size_hint::cautious(seq.size_hint())),
VecDeque::reserve,
VecDeque::push_back); VecDeque::push_back);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -611,6 +781,7 @@ seq_impl!(
struct ArrayVisitor<A> { struct ArrayVisitor<A> {
marker: PhantomData<A>, marker: PhantomData<A>,
} }
struct ArrayFromVisitor<'a, A: 'a>(&'a mut A);
impl<A> ArrayVisitor<A> { impl<A> ArrayVisitor<A> {
fn new() -> Self { fn new() -> Self {
@@ -673,6 +844,35 @@ macro_rules! array_impls {
} }
} }
impl<'a, 'de, T> Visitor<'de> for ArrayFromVisitor<'a, [T; $len]>
where
T: Deserialize<'de>,
{
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(concat!("an array of length ", $len))
}
#[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
where
A: SeqAccess<'de>,
{
let mut fail_idx = None;
for (idx, dest) in self.0[..].iter_mut().enumerate() {
if try!(seq.next_element_seed(DeserializeFromSeed(dest))).is_none() {
fail_idx = Some(idx);
break;
}
}
if let Some(idx) = fail_idx {
return Err(Error::invalid_length(idx, &self));
}
Ok(())
}
}
impl<'de, T> Deserialize<'de> for [T; $len] impl<'de, T> Deserialize<'de> for [T; $len]
where where
T: Deserialize<'de>, T: Deserialize<'de>,
@@ -683,6 +883,13 @@ macro_rules! array_impls {
{ {
deserializer.deserialize_tuple($len, ArrayVisitor::<[T; $len]>::new()) deserializer.deserialize_tuple($len, ArrayVisitor::<[T; $len]>::new())
} }
fn deserialize_from<D>(&mut self, deserializer: D) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_tuple($len, ArrayFromVisitor(self))
}
} }
)+ )+
} }
@@ -726,49 +933,76 @@ array_impls! {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
macro_rules! tuple_impls { macro_rules! tuple_impls {
($($len:tt $visitor:ident => ($($n:tt $name:ident)+))+) => { ($($len:tt => ($($n:tt $name:ident)+))+) => {
$( $(
struct $visitor<$($name,)+> {
marker: PhantomData<($($name,)+)>,
}
impl<$($name,)+> $visitor<$($name,)+> {
fn new() -> Self {
$visitor { marker: PhantomData }
}
}
impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for $visitor<$($name,)+> {
type Value = ($($name,)+);
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(concat!("a tuple of size ", $len))
}
#[inline]
#[allow(non_snake_case)]
fn visit_seq<A>(self, mut seq: A) -> Result<($($name,)+), A::Error>
where
A: SeqAccess<'de>,
{
$(
let $name = match try!(seq.next_element()) {
Some(value) => value,
None => return Err(Error::invalid_length($n, &self)),
};
)+
Ok(($($name,)+))
}
}
impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) { impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) {
#[inline] #[inline]
fn deserialize<D>(deserializer: D) -> Result<($($name,)+), D::Error> fn deserialize<D>(deserializer: D) -> Result<($($name,)+), D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
deserializer.deserialize_tuple($len, $visitor::new()) struct TupleVisitor<$($name,)+> {
marker: PhantomData<($($name,)+)>,
}
impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleVisitor<$($name,)+> {
type Value = ($($name,)+);
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(concat!("a tuple of size ", $len))
}
#[inline]
#[allow(non_snake_case)]
fn visit_seq<A>(self, mut seq: A) -> Result<($($name,)+), A::Error>
where
A: SeqAccess<'de>,
{
$(
let $name = match try!(seq.next_element()) {
Some(value) => value,
None => return Err(Error::invalid_length($n, &self)),
};
)+
Ok(($($name,)+))
}
}
deserializer.deserialize_tuple($len, TupleVisitor { marker: PhantomData })
}
#[inline]
fn deserialize_from<D>(&mut self, deserializer: D) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
struct TupleVisitor<'a, $($name: 'a,)+>(&'a mut ($($name,)+));
impl<'a, 'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleVisitor<'a, $($name,)+> {
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(concat!("a tuple of size ", $len))
}
#[inline]
#[allow(non_snake_case)]
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
where
A: SeqAccess<'de>,
{
$(
if try!(seq.next_element_seed(DeserializeFromSeed(&mut (self.0).$n))).is_none() {
return Err(Error::invalid_length($n, &self));
}
)+
Ok(())
}
}
deserializer.deserialize_tuple($len, TupleVisitor(self))
} }
} }
)+ )+
@@ -776,22 +1010,22 @@ macro_rules! tuple_impls {
} }
tuple_impls! { tuple_impls! {
1 TupleVisitor1 => (0 T0) 1 => (0 T0)
2 TupleVisitor2 => (0 T0 1 T1) 2 => (0 T0 1 T1)
3 TupleVisitor3 => (0 T0 1 T1 2 T2) 3 => (0 T0 1 T1 2 T2)
4 TupleVisitor4 => (0 T0 1 T1 2 T2 3 T3) 4 => (0 T0 1 T1 2 T2 3 T3)
5 TupleVisitor5 => (0 T0 1 T1 2 T2 3 T3 4 T4) 5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
6 TupleVisitor6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5) 6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
7 TupleVisitor7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6) 7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
8 TupleVisitor8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7) 8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
9 TupleVisitor9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8) 9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
10 TupleVisitor10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9) 10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
11 TupleVisitor11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10) 11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
12 TupleVisitor12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11) 12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
13 TupleVisitor13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12) 13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
14 TupleVisitor14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13) 14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
15 TupleVisitor15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14) 15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
16 TupleVisitor16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15) 16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
+18 -1
View File
@@ -8,7 +8,7 @@
use lib::*; use lib::*;
use de::{Deserialize, Deserializer, IntoDeserializer, Error, Visitor}; use de::{Deserialize, Deserializer, DeserializeSeed, IntoDeserializer, Error, Visitor};
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
use de::Unexpected; use de::Unexpected;
@@ -2009,3 +2009,20 @@ where
map struct enum identifier ignored_any map struct enum identifier ignored_any
} }
} }
/// A DeserializeSeed helper for implementing deserialize_from Visitors.
///
/// Wraps a mutable reference and calls deserialize_from on it.
pub struct DeserializeFromSeed<'a, T: 'a>(pub &'a mut T);
impl<'a, 'de, T> DeserializeSeed<'de> for DeserializeFromSeed<'a, T>
where T: Deserialize<'de>,
{
type Value = ();
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
self.0.deserialize_from(deserializer)
}
}