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

View File

@ -15,6 +15,7 @@ use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, Va
use de::MapAccess;
use de::from_primitive::FromPrimitive;
use private::de::DeserializeFromSeed;
#[cfg(any(feature = "std", feature = "alloc"))]
use private::de::size_hint;
@ -51,6 +52,7 @@ impl<'de> Deserialize<'de> for () {
struct BoolVisitor;
impl<'de> Visitor<'de> for BoolVisitor {
type Value = bool;
@ -210,6 +212,8 @@ impl<'de> Deserialize<'de> for char {
#[cfg(any(feature = "std", feature = "alloc"))]
struct StringVisitor;
#[cfg(any(feature = "std", feature = "alloc"))]
struct StringFromVisitor<'a>(&'a mut String);
#[cfg(any(feature = "std", feature = "alloc"))]
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"))]
impl<'de> Deserialize<'de> for String {
fn deserialize<D>(deserializer: D) -> Result<String, D::Error>
@ -262,6 +319,13 @@ impl<'de> Deserialize<'de> for String {
{
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> {
marker: PhantomData<T>,
}
struct OptionFromVisitor<'a, T: 'a>(&'a mut Option<T>);
impl<'de, T> Visitor<'de> for OptionVisitor<T>
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>
where
T: Deserialize<'de>,
@ -467,6 +575,13 @@ where
{
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)*)* >,
$access:ident,
$ctor:expr,
$clear:expr,
$with_capacity:expr,
$reserve:expr,
$insert:expr
) => {
impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty<T $(, $typaram)*>
@ -554,16 +671,59 @@ macro_rules! seq_impl {
let visitor = SeqVisitor { marker: PhantomData };
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"))]
seq_impl!(
BinaryHeap<T: Ord>,
seq,
BinaryHeap::new(),
BinaryHeap::clear,
BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())),
BinaryHeap::reserve,
BinaryHeap::push);
#[cfg(any(feature = "std", feature = "alloc"))]
@ -571,7 +731,9 @@ seq_impl!(
BTreeSet<T: Eq + Ord>,
seq,
BTreeSet::new(),
BTreeSet::clear,
BTreeSet::new(),
nop_reserve,
BTreeSet::insert);
#[cfg(any(feature = "std", feature = "alloc"))]
@ -579,7 +741,9 @@ seq_impl!(
LinkedList<T>,
seq,
LinkedList::new(),
LinkedList::clear,
LinkedList::new(),
nop_reserve,
LinkedList::push_back);
#[cfg(feature = "std")]
@ -587,7 +751,9 @@ seq_impl!(
HashSet<T: Eq + Hash, S: BuildHasher + Default>,
seq,
HashSet::with_hasher(S::default()),
HashSet::clear,
HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
HashSet::reserve,
HashSet::insert);
#[cfg(any(feature = "std", feature = "alloc"))]
@ -595,7 +761,9 @@ seq_impl!(
Vec<T>,
seq,
Vec::new(),
Vec::clear,
Vec::with_capacity(size_hint::cautious(seq.size_hint())),
Vec::reserve,
Vec::push);
#[cfg(any(feature = "std", feature = "alloc"))]
@ -603,7 +771,9 @@ seq_impl!(
VecDeque<T>,
seq,
VecDeque::new(),
VecDeque::clear,
VecDeque::with_capacity(size_hint::cautious(seq.size_hint())),
VecDeque::reserve,
VecDeque::push_back);
////////////////////////////////////////////////////////////////////////////////
@ -611,6 +781,7 @@ seq_impl!(
struct ArrayVisitor<A> {
marker: PhantomData<A>,
}
struct ArrayFromVisitor<'a, A: 'a>(&'a mut A);
impl<A> ArrayVisitor<A> {
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]
where
T: Deserialize<'de>,
@ -683,6 +883,13 @@ macro_rules! array_impls {
{
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 {
($($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,)+) {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<($($name,)+), D::Error>
where
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! {
1 TupleVisitor1 => (0 T0)
2 TupleVisitor2 => (0 T0 1 T1)
3 TupleVisitor3 => (0 T0 1 T1 2 T2)
4 TupleVisitor4 => (0 T0 1 T1 2 T2 3 T3)
5 TupleVisitor5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
6 TupleVisitor6 => (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)
8 TupleVisitor8 => (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)
10 TupleVisitor10 => (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)
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)
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)
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)
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)
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)
1 => (0 T0)
2 => (0 T0 1 T1)
3 => (0 T0 1 T1 2 T2)
4 => (0 T0 1 T1 2 T2 3 T3)
5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
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 => (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 => (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 => (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 => (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)
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -8,7 +8,7 @@
use lib::*;
use de::{Deserialize, Deserializer, IntoDeserializer, Error, Visitor};
use de::{Deserialize, Deserializer, DeserializeSeed, IntoDeserializer, Error, Visitor};
#[cfg(any(feature = "std", feature = "alloc"))]
use de::Unexpected;
@ -2009,3 +2009,20 @@ where
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)
}
}