1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
//! Deserialization of adjacently tagged values using tuples.
//!
//! See [`ser::adj::tuple`](::ser::adj::tuple) for a description of this tagging
//! format.
use de::seed::SeedFactory;
use std::fmt;
use std::marker::PhantomData;
use serde;
/// Deserialize a tuple-based adjacently tagged value.
///
/// The deserializer controls the underlying data format while the seed-factory
/// specifies the instructions (depending on the tag) on how the value should be
/// deserialized.
///
/// See [`de`](::de) for more information on
/// [`SeedFactory`](::de::SeedFactory) and implementations thereof.
///
/// See [`deserialize_seed`](deserialize_seed) for a version that allows you to
/// pass a `DeserializeSeed` implementation to deserialize the tag. This version
/// is equivalent to `deserialize_seed(deserializer, seed_factory,
/// PhantomData<T>)`
pub fn deserialize<'de, T, D, F>(deserializer: D, seed_factory: F) -> Result<F::Value, D::Error>
where
T: serde::Deserialize<'de>,
D: serde::Deserializer<'de>,
F: SeedFactory<'de, T>,
{
deserialize_seed(deserializer, seed_factory, PhantomData::<T>)
}
/// Deserialize a tuple-based adjacently tagged value with the given tag-seed.
///
/// The deserializer controls the underlying data format while the seed-factory
/// specifies the instructions (depending on the tag) on how the value should be
/// deserialized.
///
/// See [`de`](::de) for more information on
/// [`SeedFactory`](::de::SeedFactory) and implementations thereof.
pub fn deserialize_seed<'de, D, F, S>(
deserializer: D,
seed_factory: F,
tag_seed: S,
) -> Result<F::Value, D::Error>
where
D: serde::Deserializer<'de>,
F: SeedFactory<'de, S::Value>,
S: serde::de::DeserializeSeed<'de>,
{
deserializer.deserialize_tuple(2, Visitor::new(seed_factory, tag_seed))
}
/// A visitor that can be used to deserialize a tuple-based adjacently tagged
/// value.
///
/// This visitor handles a tuple-based adjacently tagged value, which is
/// represented by a tuple containing exactly two elements. The first element of
/// this tuple is the tag, the second element the value. Thus this visitor will
/// return an error if the visited type is not a tuple (i.e. sequence) with two
/// elements.
///
/// The [`SeedFactory`](::de::SeedFactory) provided to this visitor
/// provides a `serde::de::DeserializeSeed` implementation depending on the tag,
/// which then determines how the value is going to be deserialized.
///
/// See [`de`](::de) for more information on
/// [`SeedFactory`](::de::SeedFactory) and implementations thereof.
pub struct Visitor<F, S> {
seed_factory: F,
tag_seed: S,
}
impl<F, S> Visitor<F, S> {
/// Creates a new visitor with the given
/// [`SeedFactory`](::de::SeedFactory).
pub fn new(seed_factory: F, tag_seed: S) -> Self {
Visitor {
seed_factory,
tag_seed,
}
}
}
impl<'de, F, S> serde::de::Visitor<'de> for Visitor<F, S>
where
F: SeedFactory<'de, S::Value>,
S: serde::de::DeserializeSeed<'de>,
{
type Value = F::Value;
fn expecting(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
write!(fmtr, "a tuple with exactly two elements")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
use serde::de::Error;
// try to validate the length
match seq.size_hint() {
Some(n) if n != 2 => Err(Error::invalid_length(n, &self))?,
_ => {},
}
let tag = seq.next_element_seed(self.tag_seed)?
.ok_or_else(|| Error::invalid_length(0, &"a tuple with exactly two elements"))?;
seq.next_element_seed(self.seed_factory.seed(tag)?)?
.ok_or_else(|| Error::invalid_length(1, &"a tuple with exactly two elements"))
}
}