use crate::de::enter;
use crate::error::{Step, UclError};
use crate::handoff;
use crate::ser::marker;
use crate::value::{Entry, UclArray, UclObject, UclValue};
use serde::de::{self, Deserialize, DeserializeOwned, DeserializeSeed, Unexpected, Visitor};
use std::fmt;
pub fn from_value<T: DeserializeOwned>(value: UclValue) -> Result<T, UclError> {
T::deserialize(ValueDeserializer::<false>::new(value)).map_err(UclError::in_document)
}
fn float_to_i64(f: f64) -> Option<i64> {
if f.fract() == 0.0 && (-9_223_372_036_854_775_808.0..9_223_372_036_854_775_808.0).contains(&f)
{
Some(f as i64)
} else {
None
}
}
fn float_to_u64(f: f64) -> Option<u64> {
if f.fract() == 0.0 && (0.0..18_446_744_073_709_551_616.0).contains(&f) {
Some(f as u64)
} else {
None
}
}
fn unexpected(value: &UclValue) -> Unexpected<'_> {
match value {
UclValue::String(s) => Unexpected::Str(s),
UclValue::Integer(i) => Unexpected::Signed(*i),
UclValue::Float(f) => Unexpected::Float(*f),
UclValue::Time(_) => Unexpected::Other("time value"),
UclValue::Boolean(b) => Unexpected::Bool(*b),
UclValue::Null => Unexpected::Unit,
UclValue::Object(_) => Unexpected::Map,
UclValue::Array(_) => Unexpected::Seq,
}
}
fn invalid_type<'de, V: Visitor<'de>>(value: &UclValue, visitor: &V) -> UclError {
de::Error::invalid_type(unexpected(value), visitor)
}
pub(crate) struct ValueDeserializer<const PATHS: bool> {
value: UclValue,
depth: usize,
}
impl<const PATHS: bool> ValueDeserializer<PATHS> {
pub(crate) fn new(value: UclValue) -> Self {
Self::nested(value, 0)
}
fn nested(value: UclValue, depth: usize) -> Self {
Self { value, depth }
}
fn visit_object<'de, V: Visitor<'de>>(
object: UclObject,
depth: usize,
visitor: V,
keys: Keys,
) -> Result<V::Value, UclError> {
match enter(depth) {
Ok(depth) => visitor.visit_map(MapAccess::<PATHS>::new(object, depth, keys)),
Err(e) => {
crate::value::discard(UclValue::Object(object));
Err(e)
}
}
}
fn visit_array<'de, V: Visitor<'de>>(
array: UclArray,
depth: usize,
visitor: V,
single: bool,
) -> Result<V::Value, UclError> {
match enter(depth) {
Ok(depth) => visitor.visit_seq(SeqAccess::<PATHS>::new(array, depth, single)),
Err(e) => {
crate::value::discard(UclValue::Array(array));
Err(e)
}
}
}
}
impl<'de, const PATHS: bool> de::Deserializer<'de> for ValueDeserializer<PATHS> {
type Error = UclError;
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
match self.value {
UclValue::String(s) => visitor.visit_string(s),
UclValue::Integer(i) => visitor.visit_i64(i),
UclValue::Float(f) | UclValue::Time(f) => visitor.visit_f64(f),
UclValue::Boolean(b) => visitor.visit_bool(b),
UclValue::Null => visitor.visit_unit(),
UclValue::Object(obj) => Self::visit_object(obj, self.depth, visitor, Keys::Object),
UclValue::Array(arr) => Self::visit_array(arr, self.depth, visitor, false),
}
}
fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
match self.value {
UclValue::Boolean(b) => visitor.visit_bool(b),
other => Err(invalid_type(&other, &visitor)),
}
}
fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
match self.value {
UclValue::Integer(i) => visitor.visit_i64(i),
UclValue::Float(f) | UclValue::Time(f) => match float_to_i64(f) {
Some(i) => visitor.visit_i64(i),
None => Err(de::Error::invalid_value(Unexpected::Float(f), &visitor)),
},
other => Err(invalid_type(&other, &visitor)),
}
}
fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
match self.value {
UclValue::Integer(i) => visitor.visit_i64(i),
UclValue::Float(f) | UclValue::Time(f) => match float_to_u64(f) {
Some(u) => visitor.visit_u64(u),
None => Err(de::Error::invalid_value(Unexpected::Float(f), &visitor)),
},
other => Err(invalid_type(&other, &visitor)),
}
}
fn deserialize_i8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
self.deserialize_i64(visitor)
}
fn deserialize_i16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
self.deserialize_i64(visitor)
}
fn deserialize_i32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
self.deserialize_i64(visitor)
}
fn deserialize_i128<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
self.deserialize_i64(visitor)
}
fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
self.deserialize_u64(visitor)
}
fn deserialize_u16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
self.deserialize_u64(visitor)
}
fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
self.deserialize_u64(visitor)
}
fn deserialize_u128<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
self.deserialize_u64(visitor)
}
fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
self.deserialize_f64(visitor)
}
fn deserialize_f64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
match self.value {
UclValue::Float(f) | UclValue::Time(f) => visitor.visit_f64(f),
UclValue::Integer(i) => visitor.visit_f64(i as f64),
other => Err(invalid_type(&other, &visitor)),
}
}
fn deserialize_char<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
match self.value {
UclValue::String(s) => {
let mut chars = s.chars();
match (chars.next(), chars.next()) {
(Some(c), None) => visitor.visit_char(c),
_ => Err(de::Error::invalid_value(Unexpected::Str(&s), &visitor)),
}
}
other => Err(invalid_type(&other, &visitor)),
}
}
fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
self.deserialize_string(visitor)
}
fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
match self.value {
UclValue::String(s) => visitor.visit_string(s),
other => Err(invalid_type(&other, &visitor)),
}
}
fn deserialize_bytes<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
match self.value {
UclValue::String(s) => visitor.visit_string(s),
UclValue::Array(array) => Self::visit_array(array, self.depth, visitor, false),
other => Err(invalid_type(&other, &visitor)),
}
}
fn deserialize_byte_buf<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
self.deserialize_bytes(visitor)
}
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
match self.value {
UclValue::Null => visitor.visit_none(),
_ => visitor.visit_some(self),
}
}
fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
match self.value {
UclValue::Null => visitor.visit_unit(),
other => Err(invalid_type(&other, &visitor)),
}
}
fn deserialize_unit_struct<V: Visitor<'de>>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, UclError> {
self.deserialize_unit(visitor)
}
fn deserialize_newtype_struct<V: Visitor<'de>>(
self,
name: &'static str,
visitor: V,
) -> Result<V::Value, UclError> {
if name != marker::VALUE {
return visitor.visit_newtype_struct(self);
}
handoff::put(self.value);
let result = visitor.visit_enum(TreeAccess);
drop(handoff::take());
result
}
fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
match self.value {
UclValue::Array(array) => Self::visit_array(array, self.depth, visitor, false),
UclValue::Object(_) => Err(de::Error::invalid_type(Unexpected::Map, &visitor)),
single => Self::visit_array(vec![single], self.depth, visitor, true),
}
}
fn deserialize_tuple<V: Visitor<'de>>(
self,
_len: usize,
visitor: V,
) -> Result<V::Value, UclError> {
self.deserialize_seq(visitor)
}
fn deserialize_tuple_struct<V: Visitor<'de>>(
self,
_name: &'static str,
_len: usize,
visitor: V,
) -> Result<V::Value, UclError> {
self.deserialize_seq(visitor)
}
fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
match self.value {
UclValue::Object(object) => {
Self::visit_object(object, self.depth, visitor, Keys::Object)
}
UclValue::Array(array) => {
let object = array
.into_iter()
.enumerate()
.map(|(i, v)| (i.to_string(), v))
.collect();
Self::visit_object(object, self.depth, visitor, Keys::Indices)
}
other => Err(invalid_type(&other, &visitor)),
}
}
fn deserialize_struct<V: Visitor<'de>>(
self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, UclError> {
self.deserialize_map(visitor)
}
fn deserialize_enum<V: Visitor<'de>>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, UclError> {
match self.value {
UclValue::String(s) => visitor.visit_enum(EnumAccess::<PATHS>::unit(s)),
UclValue::Object(mut obj) if obj.len() == 1 => match enter(self.depth) {
Ok(depth) => {
let (name, entry) = obj.remove_index(0).unwrap();
visitor.visit_enum(EnumAccess::<PATHS>::data(name, entry, depth))
}
Err(e) => {
crate::value::discard(UclValue::Object(obj));
Err(e)
}
},
UclValue::Object(obj) => Err(de::Error::invalid_length(
obj.len(),
&"an object with exactly one key (the variant name)",
)),
other => Err(invalid_type(&other, &visitor)),
}
}
fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
self.deserialize_string(visitor)
}
fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
visitor.visit_unit()
}
}
pub(crate) struct SeqAccess<const PATHS: bool> {
items: std::vec::IntoIter<UclValue>,
depth: usize,
len: Option<usize>,
}
impl<const PATHS: bool> SeqAccess<PATHS> {
fn new(array: UclArray, depth: usize, single: bool) -> Self {
Self {
len: (!single).then_some(array.len()),
items: array.into_iter(),
depth,
}
}
}
impl<'de, const PATHS: bool> de::SeqAccess<'de> for SeqAccess<PATHS> {
type Error = UclError;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, UclError>
where
T: DeserializeSeed<'de>,
{
match self.items.next() {
Some(value) if !PATHS => seed
.deserialize(ValueDeserializer::<PATHS>::nested(value, self.depth))
.map(Some),
Some(value) => {
let mut result =
seed.deserialize(ValueDeserializer::<PATHS>::nested(value, self.depth));
if let (Err(e), Some(len)) = (&mut result, self.len) {
e.add_step(Step::Index(len - self.items.len() - 1));
}
result.map(Some)
}
None => Ok(None),
}
}
fn size_hint(&self) -> Option<usize> {
Some(self.items.len())
}
}
#[derive(Debug, Clone, Copy)]
enum Keys {
Object,
Indices,
}
struct MapAccess<const PATHS: bool> {
entries: indexmap::map::IntoIter<String, Entry>,
entry: Option<Entry>,
key: String,
depth: usize,
keys: Keys,
}
impl<const PATHS: bool> MapAccess<PATHS> {
fn new(object: UclObject, depth: usize, keys: Keys) -> Self {
Self {
entries: object.into_iter(),
entry: None,
key: String::new(),
depth,
keys,
}
}
fn step<'k>(&self, key: &'k str, on_key: bool, multi: bool) -> Step<'k> {
match self.keys {
Keys::Object if on_key => Step::Key(key),
Keys::Object if multi => Step::Values(key),
Keys::Object => Step::Entry(key),
Keys::Indices => Step::Index(key.parse().unwrap_or_default()),
}
}
}
impl<'de, const PATHS: bool> de::MapAccess<'de> for MapAccess<PATHS> {
type Error = UclError;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, UclError>
where
K: DeserializeSeed<'de>,
{
match self.entries.next() {
Some((key, entry)) if !PATHS => {
self.entry = Some(entry);
seed.deserialize(OwnedKey { key }).map(Some)
}
Some((key, entry)) => {
let mut result = seed.deserialize(KeyDeserializer { key: &key });
if let Err(e) = &mut result {
e.add_step(self.step(&key, true, false));
}
self.entry = Some(entry);
self.key = key;
result.map(Some)
}
None => Ok(None),
}
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, UclError>
where
V: DeserializeSeed<'de>,
{
match self.entry.take() {
Some(entry) if !PATHS => seed.deserialize(ValueDeserializer::<PATHS>::nested(
entry.into_value(),
self.depth,
)),
Some(entry) => {
let multi = entry.is_multi();
let mut result = seed.deserialize(ValueDeserializer::<PATHS>::nested(
entry.into_value(),
self.depth,
));
if let Err(e) = &mut result {
e.add_step(self.step(&self.key, false, multi));
}
result
}
None => Err(<UclError as de::Error>::custom(
"map value requested before its key",
)),
}
}
fn size_hint(&self) -> Option<usize> {
Some(self.entries.len())
}
}
struct EnumAccess<const PATHS: bool> {
name: String,
data: Option<Entry>,
depth: usize,
}
impl<const PATHS: bool> EnumAccess<PATHS> {
fn unit(name: String) -> Self {
Self {
name,
data: None,
depth: 0,
}
}
fn data(name: String, data: Entry, depth: usize) -> Self {
Self {
name,
data: Some(data),
depth,
}
}
}
impl<'de, const PATHS: bool> de::EnumAccess<'de> for EnumAccess<PATHS> {
type Error = UclError;
type Variant = VariantAccess<PATHS>;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, VariantAccess<PATHS>), UclError>
where
V: DeserializeSeed<'de>,
{
let multi = self.data.as_ref().is_some_and(Entry::is_multi);
let data = self.data.map(Entry::into_value);
if !PATHS || data.is_none() {
let name = ValueDeserializer::<PATHS>::new(UclValue::String(self.name));
let access = VariantAccess {
data,
multi,
depth: self.depth,
name: String::new(),
};
return Ok((seed.deserialize(name)?, access));
}
let variant = seed
.deserialize(KeyDeserializer { key: &self.name })
.map_err(|e| e.at_key(&self.name))?;
let access = VariantAccess {
data,
multi,
depth: self.depth,
name: self.name,
};
Ok((variant, access))
}
}
struct VariantAccess<const PATHS: bool> {
data: Option<UclValue>,
multi: bool,
depth: usize,
name: String,
}
impl<const PATHS: bool> VariantAccess<PATHS> {
fn locate<T>(&self, mut result: Result<T, UclError>) -> Result<T, UclError> {
if PATHS && let Err(e) = &mut result {
e.add_step(if self.multi {
Step::Values(&self.name)
} else {
Step::Entry(&self.name)
});
}
result
}
}
impl<'de, const PATHS: bool> de::VariantAccess<'de> for VariantAccess<PATHS> {
type Error = UclError;
fn unit_variant(self) -> Result<(), UclError> {
match &self.data {
None => Ok(()),
Some(value) => {
let e: UclError = de::Error::invalid_type(unexpected(value), &"unit variant");
self.locate(Err(e))
}
}
}
fn newtype_variant_seed<T>(mut self, seed: T) -> Result<T::Value, UclError>
where
T: DeserializeSeed<'de>,
{
match self.data.take() {
Some(value) => {
let result =
seed.deserialize(ValueDeserializer::<PATHS>::nested(value, self.depth));
self.locate(result)
}
None => Err(de::Error::invalid_type(
Unexpected::UnitVariant,
&"newtype variant",
)),
}
}
fn tuple_variant<V>(mut self, _len: usize, visitor: V) -> Result<V::Value, UclError>
where
V: Visitor<'de>,
{
let result = match self.data.take() {
Some(UclValue::Array(array)) => {
ValueDeserializer::<PATHS>::visit_array(array, self.depth, visitor, false)
}
Some(value) => {
ValueDeserializer::<PATHS>::visit_array(vec![value], self.depth, visitor, true)
}
None => {
return Err(de::Error::invalid_type(
Unexpected::UnitVariant,
&"tuple variant",
));
}
};
self.locate(result)
}
fn struct_variant<V>(
mut self,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, UclError>
where
V: Visitor<'de>,
{
let result = match self.data.take() {
Some(UclValue::Object(object)) => {
ValueDeserializer::<PATHS>::visit_object(object, self.depth, visitor, Keys::Object)
}
Some(value) => Err(de::Error::invalid_type(
unexpected(&value),
&"struct variant",
)),
None => {
return Err(de::Error::invalid_type(
Unexpected::UnitVariant,
&"struct variant",
));
}
};
self.locate(result)
}
}
macro_rules! forward_to {
($make:ident; $($method:ident($($arg:ident: $ty:ty),*))*) => {
$(
fn $method<V>(self, $($arg: $ty,)* visitor: V) -> Result<V::Value, UclError>
where
V: Visitor<'de>,
{
self.$make().$method($($arg,)* visitor)
}
)*
};
}
struct KeyDeserializer<'a> {
key: &'a str,
}
impl KeyDeserializer<'_> {
fn value(self) -> ValueDeserializer<false> {
ValueDeserializer::<false>::new(UclValue::String(self.key.to_owned()))
}
}
macro_rules! parse_key {
($($method:ident => $ty:ty, $visit:ident;)*) => {
$(
fn $method<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
match self.key.parse::<$ty>() {
Ok(v) => visitor.$visit(v),
Err(_) => Err(de::Error::invalid_value(Unexpected::Str(&self.key), &visitor)),
}
}
)*
};
}
impl<'de> de::Deserializer<'de> for KeyDeserializer<'_> {
type Error = UclError;
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
visitor.visit_str(self.key)
}
fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
visitor.visit_str(self.key)
}
fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
visitor.visit_string(self.key.to_owned())
}
fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
visitor.visit_str(self.key)
}
parse_key! {
deserialize_bool => bool, visit_bool;
deserialize_i8 => i64, visit_i64;
deserialize_i16 => i64, visit_i64;
deserialize_i32 => i64, visit_i64;
deserialize_i64 => i64, visit_i64;
deserialize_i128 => i128, visit_i128;
deserialize_u8 => u64, visit_u64;
deserialize_u16 => u64, visit_u64;
deserialize_u32 => u64, visit_u64;
deserialize_u64 => u64, visit_u64;
deserialize_u128 => u128, visit_u128;
deserialize_f32 => f64, visit_f64;
deserialize_f64 => f64, visit_f64;
}
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
visitor.visit_some(self)
}
fn deserialize_newtype_struct<V: Visitor<'de>>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, UclError> {
visitor.visit_newtype_struct(self)
}
forward_to! { value;
deserialize_char()
deserialize_bytes()
deserialize_byte_buf()
deserialize_unit()
deserialize_unit_struct(name: &'static str)
deserialize_seq()
deserialize_tuple(len: usize)
deserialize_tuple_struct(name: &'static str, len: usize)
deserialize_map()
deserialize_struct(name: &'static str, fields: &'static [&'static str])
deserialize_enum(name: &'static str, variants: &'static [&'static str])
deserialize_ignored_any()
}
}
struct OwnedKey {
key: String,
}
impl OwnedKey {
fn value(self) -> ValueDeserializer<false> {
ValueDeserializer::new(UclValue::String(self.key))
}
}
impl<'de> de::Deserializer<'de> for OwnedKey {
type Error = UclError;
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
visitor.visit_string(self.key)
}
parse_key! {
deserialize_bool => bool, visit_bool;
deserialize_i8 => i64, visit_i64;
deserialize_i16 => i64, visit_i64;
deserialize_i32 => i64, visit_i64;
deserialize_i64 => i64, visit_i64;
deserialize_i128 => i128, visit_i128;
deserialize_u8 => u64, visit_u64;
deserialize_u16 => u64, visit_u64;
deserialize_u32 => u64, visit_u64;
deserialize_u64 => u64, visit_u64;
deserialize_u128 => u128, visit_u128;
deserialize_f32 => f64, visit_f64;
deserialize_f64 => f64, visit_f64;
}
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, UclError> {
visitor.visit_some(self)
}
fn deserialize_newtype_struct<V: Visitor<'de>>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, UclError> {
visitor.visit_newtype_struct(self)
}
forward_to! { value;
deserialize_char()
deserialize_str()
deserialize_string()
deserialize_bytes()
deserialize_byte_buf()
deserialize_unit()
deserialize_unit_struct(name: &'static str)
deserialize_seq()
deserialize_tuple(len: usize)
deserialize_tuple_struct(name: &'static str, len: usize)
deserialize_map()
deserialize_struct(name: &'static str, fields: &'static [&'static str])
deserialize_enum(name: &'static str, variants: &'static [&'static str])
deserialize_identifier()
deserialize_ignored_any()
}
}
struct TreeAccess;
impl<'de> de::EnumAccess<'de> for TreeAccess {
type Error = UclError;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self), UclError>
where
V: DeserializeSeed<'de>,
{
let name = de::value::StrDeserializer::<UclError>::new(marker::TREE);
Ok((seed.deserialize(name)?, self))
}
}
impl<'de> de::VariantAccess<'de> for TreeAccess {
type Error = UclError;
fn unit_variant(self) -> Result<(), UclError> {
Ok(())
}
fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, UclError>
where
T: DeserializeSeed<'de>,
{
Err(de::Error::invalid_type(
Unexpected::UnitVariant,
&"newtype variant",
))
}
fn tuple_variant<V: Visitor<'de>>(
self,
_len: usize,
_visitor: V,
) -> Result<V::Value, UclError> {
Err(de::Error::invalid_type(
Unexpected::UnitVariant,
&"tuple variant",
))
}
fn struct_variant<V: Visitor<'de>>(
self,
_fields: &'static [&'static str],
_visitor: V,
) -> Result<V::Value, UclError> {
Err(de::Error::invalid_type(
Unexpected::UnitVariant,
&"struct variant",
))
}
}
impl<'de> Deserialize<'de> for UclValue {
fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
deserializer.deserialize_newtype_struct(marker::VALUE, ValueVisitor)
}
}
impl<'de> Deserialize<'de> for UclObject {
fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
match UclValue::deserialize(deserializer)? {
UclValue::Object(object) => Ok(object),
other => Err(de::Error::invalid_type(unexpected(&other), &"a UCL object")),
}
}
}
struct ValueVisitor;
impl<'de> Visitor<'de> for ValueVisitor {
type Value = UclValue;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("a UCL value")
}
fn visit_bool<E: de::Error>(self, v: bool) -> Result<UclValue, E> {
Ok(UclValue::Boolean(v))
}
fn visit_i64<E: de::Error>(self, v: i64) -> Result<UclValue, E> {
Ok(UclValue::Integer(v))
}
fn visit_i128<E: de::Error>(self, v: i128) -> Result<UclValue, E> {
i64::try_from(v)
.map(UclValue::Integer)
.map_err(|_| E::invalid_value(Unexpected::Other("128-bit integer"), &self))
}
fn visit_u64<E: de::Error>(self, v: u64) -> Result<UclValue, E> {
i64::try_from(v)
.map(UclValue::Integer)
.map_err(|_| E::invalid_value(Unexpected::Unsigned(v), &"an integer up to i64::MAX"))
}
fn visit_u128<E: de::Error>(self, v: u128) -> Result<UclValue, E> {
i64::try_from(v)
.map(UclValue::Integer)
.map_err(|_| E::invalid_value(Unexpected::Other("128-bit integer"), &self))
}
fn visit_f64<E: de::Error>(self, v: f64) -> Result<UclValue, E> {
Ok(UclValue::Float(v))
}
fn visit_str<E: de::Error>(self, v: &str) -> Result<UclValue, E> {
Ok(UclValue::String(v.to_owned()))
}
fn visit_string<E: de::Error>(self, v: String) -> Result<UclValue, E> {
Ok(UclValue::String(v))
}
fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<UclValue, E> {
match std::str::from_utf8(v) {
Ok(s) => Ok(UclValue::String(s.to_owned())),
Err(_) => Err(E::invalid_value(Unexpected::Bytes(v), &"UTF-8 text")),
}
}
fn visit_unit<E: de::Error>(self) -> Result<UclValue, E> {
Ok(UclValue::Null)
}
fn visit_none<E: de::Error>(self) -> Result<UclValue, E> {
Ok(UclValue::Null)
}
fn visit_some<D: de::Deserializer<'de>>(self, deserializer: D) -> Result<UclValue, D::Error> {
UclValue::deserialize(deserializer)
}
fn visit_newtype_struct<D: de::Deserializer<'de>>(
self,
deserializer: D,
) -> Result<UclValue, D::Error> {
deserializer.deserialize_any(self)
}
fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<UclValue, A::Error> {
let mut items = Vec::with_capacity(seq.size_hint().unwrap_or(0).min(4096));
while let Some(item) = seq.next_element()? {
items.push(item);
}
Ok(UclValue::Array(items))
}
fn visit_map<A: de::MapAccess<'de>>(self, mut map: A) -> Result<UclValue, A::Error> {
let mut object = UclObject::new();
while let Some((key, value)) = map.next_entry::<String, UclValue>()? {
object.append(key, value);
}
Ok(UclValue::Object(object))
}
fn visit_enum<A: de::EnumAccess<'de>>(self, data: A) -> Result<UclValue, A::Error> {
use de::VariantAccess;
let (name, variant): (String, _) = data.variant()?;
if name == marker::TREE {
variant.unit_variant()?;
if let Some(value) = handoff::take() {
return Ok(value);
}
}
Err(de::Error::custom(format!(
"the enum variant `{name}`: a UCL value is an object, an array or a scalar"
)))
}
}