use std::{borrow::Cow, slice::Iter};
use nt_syntax::Value;
use serde::{
Deserialize, Deserializer,
de::{self, DeserializeSeed, IntoDeserializer, Visitor, value::BorrowedStrDeserializer},
};
use super::scalar::{KeyDe, parse_bool, parse_char};
use crate::error::{Error, Result};
pub fn from_value<'de, T: Deserialize<'de>>(value: &'de Value<'de>) -> Result<T> {
T::deserialize(ValDe { value })
}
pub(super) struct ValDe<'a, 'de: 'a> {
pub value: &'a Value<'de>,
}
impl<'a, 'de: 'a> ValDe<'a, 'de> {
#[inline]
fn as_str(&self) -> Result<&'a str> {
match self.value {
Value::Str(s) => Ok(s.as_ref()),
_ => Err(Error::msg("expected a string value")),
}
}
#[inline]
fn visit_cow_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match self.value {
Value::Str(Cow::Borrowed(s)) => visitor.visit_borrowed_str(s),
Value::Str(Cow::Owned(s)) => visitor.visit_str(s),
_ => Err(Error::msg("expected a string value")),
}
}
}
macro_rules! val_numeric {
($($de:ident => $visit:ident => $t:ty),* $(,)?) => {
$(
fn $de<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let s = self.as_str()?;
let n: $t = s
.trim()
.parse()
.map_err(|_| Error::msg(format!("cannot parse `{s}` as {}", stringify!($t))))?;
visitor.$visit(n)
}
)*
};
}
impl<'a, 'de: 'a> de::Deserializer<'de> for ValDe<'a, 'de> {
type Error = Error;
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match self.value {
Value::Str(_) => self.visit_cow_str(visitor),
Value::List(_) => self.deserialize_seq(visitor),
Value::Dict(_) => self.deserialize_map(visitor),
}
}
fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_bool(parse_bool(self.as_str()?)?)
}
fn deserialize_char<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_char(parse_char(self.as_str()?)?)
}
fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.visit_cow_str(visitor)
}
fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.visit_cow_str(visitor)
}
fn deserialize_bytes<V: Visitor<'de>>(self, _: V) -> Result<V::Value> {
Err(Error::msg("NestedText does not support byte arrays"))
}
fn deserialize_byte_buf<V: Visitor<'de>>(self, _: V) -> Result<V::Value> {
Err(Error::msg("NestedText does not support byte arrays"))
}
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match self.value {
Value::Str(s) if s.is_empty() => visitor.visit_none(),
_ => visitor.visit_some(self),
}
}
fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match self.value {
Value::Str(s) if s.is_empty() => visitor.visit_unit(),
_ => Err(Error::msg("unit expects an empty string")),
}
}
fn deserialize_unit_struct<V: Visitor<'de>>(
self,
_: &'static str,
visitor: V,
) -> Result<V::Value> {
self.deserialize_unit(visitor)
}
fn deserialize_newtype_struct<V: Visitor<'de>>(
self,
_: &'static str,
visitor: V,
) -> Result<V::Value> {
visitor.visit_newtype_struct(self)
}
fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match self.value {
Value::List(item_li) => visitor.visit_seq(ValSeqDe {
iter: item_li.iter(),
}),
_ => Err(Error::msg("expected a list value")),
}
}
fn deserialize_tuple<V: Visitor<'de>>(self, _: usize, visitor: V) -> Result<V::Value> {
self.deserialize_seq(visitor)
}
fn deserialize_tuple_struct<V: Visitor<'de>>(
self,
_: &'static str,
_: usize,
visitor: V,
) -> Result<V::Value> {
self.deserialize_seq(visitor)
}
fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match self.value {
Value::Dict(pair_li) => visitor.visit_map(ValMapDe {
iter: pair_li.iter(),
val: None,
}),
_ => Err(Error::msg("expected a dictionary value")),
}
}
fn deserialize_struct<V: Visitor<'de>>(
self,
_: &'static str,
_: &'static [&'static str],
visitor: V,
) -> Result<V::Value> {
self.deserialize_map(visitor)
}
fn deserialize_enum<V: Visitor<'de>>(
self,
_: &'static str,
_: &'static [&'static str],
visitor: V,
) -> Result<V::Value> {
match self.value {
Value::Str(Cow::Borrowed(s)) => visitor.visit_enum(BorrowedStrDeserializer::new(s)),
Value::Str(Cow::Owned(s)) => visitor.visit_enum(s.as_str().into_deserializer()),
Value::Dict(pair_li) if pair_li.len() == 1 => {
let (variant, value) = &pair_li[0];
visitor.visit_enum(ValEnumDe { variant, value })
}
Value::Dict(_) => Err(Error::msg("an enum dictionary must have exactly one key")),
Value::List(_) => Err(Error::msg(
"an enum expects a string or a single-entry dictionary",
)),
}
}
fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.visit_cow_str(visitor)
}
fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_unit()
}
val_numeric! {
deserialize_i8 => visit_i8 => i8,
deserialize_i16 => visit_i16 => i16,
deserialize_i32 => visit_i32 => i32,
deserialize_i64 => visit_i64 => i64,
deserialize_i128 => visit_i128 => i128,
deserialize_u8 => visit_u8 => u8,
deserialize_u16 => visit_u16 => u16,
deserialize_u32 => visit_u32 => u32,
deserialize_u64 => visit_u64 => u64,
deserialize_u128 => visit_u128 => u128,
deserialize_f32 => visit_f32 => f32,
deserialize_f64 => visit_f64 => f64,
}
}
struct ValSeqDe<'a, 'de: 'a> {
iter: Iter<'a, Value<'de>>,
}
impl<'a, 'de: 'a> de::SeqAccess<'de> for ValSeqDe<'a, 'de> {
type Error = Error;
#[inline]
fn next_element_seed<T: DeserializeSeed<'de>>(&mut self, seed: T) -> Result<Option<T::Value>> {
match self.iter.next() {
Some(value) => seed.deserialize(ValDe { value }).map(Some),
None => Ok(None),
}
}
#[inline]
fn size_hint(&self) -> Option<usize> {
Some(self.iter.len())
}
}
struct ValMapDe<'a, 'de: 'a> {
iter: Iter<'a, (Cow<'de, str>, Value<'de>)>,
val: Option<&'a Value<'de>>,
}
impl<'a, 'de: 'a> de::MapAccess<'de> for ValMapDe<'a, 'de> {
type Error = Error;
#[inline]
fn next_key_seed<K: DeserializeSeed<'de>>(&mut self, seed: K) -> Result<Option<K::Value>> {
let Some((key, value)) = self.iter.next() else {
return Ok(None);
};
self.val = Some(value);
seed.deserialize(KeyDe(key)).map(Some)
}
#[inline]
fn next_value_seed<V: DeserializeSeed<'de>>(&mut self, seed: V) -> Result<V::Value> {
seed.deserialize(ValDe {
value: self.val.take().expect("next_value called before next_key"),
})
}
#[inline]
fn size_hint(&self) -> Option<usize> {
Some(self.iter.len())
}
}
struct ValEnumDe<'a, 'de: 'a> {
variant: &'a Cow<'de, str>,
value: &'a Value<'de>,
}
impl<'a, 'de: 'a> de::EnumAccess<'de> for ValEnumDe<'a, 'de> {
type Error = Error;
type Variant = ValVariantDe<'a, 'de>;
fn variant_seed<V: DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self::Variant)> {
let variant = seed.deserialize(KeyDe(self.variant))?;
Ok((variant, ValVariantDe { value: self.value }))
}
}
struct ValVariantDe<'a, 'de: 'a> {
value: &'a Value<'de>,
}
impl<'a, 'de: 'a> de::VariantAccess<'de> for ValVariantDe<'a, 'de> {
type Error = Error;
fn unit_variant(self) -> Result<()> {
Ok(())
}
fn newtype_variant_seed<T: DeserializeSeed<'de>>(self, seed: T) -> Result<T::Value> {
seed.deserialize(ValDe { value: self.value })
}
fn tuple_variant<V: Visitor<'de>>(self, _: usize, visitor: V) -> Result<V::Value> {
ValDe { value: self.value }.deserialize_seq(visitor)
}
fn struct_variant<V: Visitor<'de>>(
self,
_: &'static [&'static str],
visitor: V,
) -> Result<V::Value> {
ValDe { value: self.value }.deserialize_map(visitor)
}
}