blob: 197ad6ea7a75e69518dd8b9fef3e6f6e27448138 [file] [log] [blame]
use crate::de::Error;
/// Deserializes table values into enum variants.
pub(crate) struct TableEnumDeserializer {
value: crate::Item,
}
impl TableEnumDeserializer {
pub(crate) fn new(value: crate::Item) -> Self {
TableEnumDeserializer { value }
}
}
impl<'de> serde::de::VariantAccess<'de> for TableEnumDeserializer {
type Error = Error;
fn unit_variant(self) -> Result<(), Self::Error> {
match self.value {
crate::Item::Table(values) => {
if values.is_empty() {
Ok(())
} else {
Err(Error::custom("expected empty table", values.span()))
}
}
crate::Item::Value(crate::Value::InlineTable(values)) => {
if values.is_empty() {
Ok(())
} else {
Err(Error::custom("expected empty table", values.span()))
}
}
e => Err(Error::custom(
format!("expected table, found {}", e.type_name()),
e.span(),
)),
}
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
where
T: serde::de::DeserializeSeed<'de>,
{
seed.deserialize(super::ValueDeserializer::new(self.value))
}
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
match self.value {
crate::Item::Table(values) => {
let values_span = values.span();
let tuple_values = values
.items
.into_iter()
.enumerate()
.map(
|(index, (_, value))| match value.key.get().parse::<usize>() {
Ok(key_index) if key_index == index => Ok(value.value),
Ok(_) | Err(_) => Err(Error::custom(
format!(
"expected table key `{}`, but was `{}`",
index,
value.key.get()
),
value.key.span(),
)),
},
)
// Fold all values into a `Vec`, or return the first error.
.fold(Ok(Vec::with_capacity(len)), |result, value_result| {
result.and_then(move |mut tuple_values| match value_result {
Ok(value) => {
tuple_values.push(value);
Ok(tuple_values)
}
// `Result<de::Value, Self::Error>` to `Result<Vec<_>, Self::Error>`
Err(e) => Err(e),
})
})?;
if tuple_values.len() == len {
serde::de::Deserializer::deserialize_seq(
super::ArrayDeserializer::new(tuple_values, values_span),
visitor,
)
} else {
Err(Error::custom(
format!("expected tuple with length {}", len),
values_span,
))
}
}
crate::Item::Value(crate::Value::InlineTable(values)) => {
let values_span = values.span();
let tuple_values = values
.items
.into_iter()
.enumerate()
.map(
|(index, (_, value))| match value.key.get().parse::<usize>() {
Ok(key_index) if key_index == index => Ok(value.value),
Ok(_) | Err(_) => Err(Error::custom(
format!(
"expected table key `{}`, but was `{}`",
index,
value.key.get()
),
value.key.span(),
)),
},
)
// Fold all values into a `Vec`, or return the first error.
.fold(Ok(Vec::with_capacity(len)), |result, value_result| {
result.and_then(move |mut tuple_values| match value_result {
Ok(value) => {
tuple_values.push(value);
Ok(tuple_values)
}
// `Result<de::Value, Self::Error>` to `Result<Vec<_>, Self::Error>`
Err(e) => Err(e),
})
})?;
if tuple_values.len() == len {
serde::de::Deserializer::deserialize_seq(
super::ArrayDeserializer::new(tuple_values, values_span),
visitor,
)
} else {
Err(Error::custom(
format!("expected tuple with length {}", len),
values_span,
))
}
}
e => Err(Error::custom(
format!("expected table, found {}", e.type_name()),
e.span(),
)),
}
}
fn struct_variant<V>(
self,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
serde::de::Deserializer::deserialize_struct(
super::ValueDeserializer::new(self.value).with_struct_key_validation(),
"", // TODO: this should be the variant name
fields,
visitor,
)
}
}