use super::{Map, Value};
use crate::{Error, Number, Result};
use indexmap::map;
use serde::de::{self, value::StringDeserializer, IntoDeserializer, Visitor};
use serde::{forward_to_deserialize_any, Deserialize, Deserializer};
use std::fmt;
impl<'de> Deserialize<'de> for Value {
fn deserialize<D>(deserializer: D) -> Result<Value, D::Error>
where
D: Deserializer<'de>,
{
struct ValueVisitor;
impl<'de> Visitor<'de> for ValueVisitor {
type Value = Value;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("any valid HCL value")
}
fn visit_bool<E>(self, value: bool) -> Result<Value, E> {
Ok(Value::Bool(value))
}
fn visit_i64<E>(self, value: i64) -> Result<Value, E> {
Ok(Value::Number(value.into()))
}
fn visit_u64<E>(self, value: u64) -> Result<Value, E> {
Ok(Value::Number(value.into()))
}
fn visit_f64<E>(self, value: f64) -> Result<Value, E> {
Ok(Number::from_f64(value).map_or(Value::Null, Value::Number))
}
fn visit_str<E>(self, value: &str) -> Result<Value, E>
where
E: serde::de::Error,
{
self.visit_string(value.to_owned())
}
fn visit_string<E>(self, value: String) -> Result<Value, E> {
Ok(Value::String(value))
}
fn visit_none<E>(self) -> Result<Value, E> {
Ok(Value::Null)
}
fn visit_some<D>(self, deserializer: D) -> Result<Value, D::Error>
where
D: serde::Deserializer<'de>,
{
Deserialize::deserialize(deserializer)
}
fn visit_unit<E>(self) -> Result<Value, E> {
Ok(Value::Null)
}
fn visit_seq<V>(self, mut visitor: V) -> Result<Value, V::Error>
where
V: de::SeqAccess<'de>,
{
let mut vec = Vec::with_capacity(visitor.size_hint().unwrap_or(0));
while let Some(elem) = visitor.next_element()? {
vec.push(elem);
}
Ok(Value::Array(vec))
}
fn visit_map<V>(self, mut visitor: V) -> Result<Value, V::Error>
where
V: de::MapAccess<'de>,
{
let mut map = Map::with_capacity(visitor.size_hint().unwrap_or(0));
while let Some((key, value)) = visitor.next_entry()? {
map.insert(key, value);
}
Ok(Value::Object(map))
}
}
deserializer.deserialize_any(ValueVisitor)
}
}
pub struct ValueDeserializer {
value: Value,
}
impl ValueDeserializer {
pub fn new(value: Value) -> ValueDeserializer {
ValueDeserializer { value }
}
}
impl<'de> IntoDeserializer<'de, Error> for Value {
type Deserializer = ValueDeserializer;
fn into_deserializer(self) -> Self::Deserializer {
ValueDeserializer { value: self }
}
}
impl<'de> de::Deserializer<'de> for ValueDeserializer {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
where
V: de::Visitor<'de>,
{
match self.value {
Value::Null => visitor.visit_unit(),
Value::Bool(b) => visitor.visit_bool(b),
Value::Number(n) => n.deserialize_any(visitor).map_err(de::Error::custom),
Value::String(s) => visitor.visit_string(s),
Value::Array(array) => visitor.visit_seq(array.into_deserializer()),
Value::Object(object) => visitor.visit_map(object.into_deserializer()),
}
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.value {
Value::Null => visitor.visit_none(),
_ => visitor.visit_some(self),
}
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: de::Visitor<'de>,
{
match self.value {
Value::String(s) => visitor.visit_enum(s.into_deserializer()),
Value::Object(object) => visitor.visit_enum(EnumAccess::new(object)),
_ => Err(de::Error::custom("expected an enum")),
}
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf unit unit_struct newtype_struct seq tuple
tuple_struct map struct identifier ignored_any
}
}
struct EnumAccess {
iter: map::IntoIter<String, Value>,
}
impl EnumAccess {
fn new(map: Map<String, Value>) -> Self {
EnumAccess {
iter: map.into_iter(),
}
}
}
impl<'de> de::EnumAccess<'de> for EnumAccess {
type Error = Error;
type Variant = VariantAccess;
fn variant_seed<V>(mut self, seed: V) -> Result<(V::Value, Self::Variant)>
where
V: de::DeserializeSeed<'de>,
{
match self.iter.next() {
Some((value, variant)) => Ok((
seed.deserialize::<StringDeserializer<Error>>(value.into_deserializer())?,
VariantAccess::new(variant),
)),
None => Err(de::Error::custom("expected an enum variant")),
}
}
}
struct VariantAccess {
value: Value,
}
impl VariantAccess {
fn new(value: Value) -> Self {
VariantAccess { value }
}
}
impl<'de> de::VariantAccess<'de> for VariantAccess {
type Error = Error;
fn unit_variant(self) -> Result<()> {
Err(de::Error::custom("expected a string"))
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
where
T: de::DeserializeSeed<'de>,
{
seed.deserialize(ValueDeserializer::new(self.value))
}
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
where
V: de::Visitor<'de>,
{
de::Deserializer::deserialize_seq(ValueDeserializer::new(self.value), visitor)
}
fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
where
V: de::Visitor<'de>,
{
de::Deserializer::deserialize_map(ValueDeserializer::new(self.value), visitor)
}
}