use std::borrow::Cow;
use serde::{
de::{self, IntoDeserializer, Visitor, value::BorrowedStrDeserializer},
forward_to_deserialize_any,
};
use crate::error::{Error, Result};
#[inline]
pub(super) fn parse_bool(s: &str) -> Result<bool> {
if s.eq_ignore_ascii_case("true") || s.eq_ignore_ascii_case("yes") {
Ok(true)
} else if s.eq_ignore_ascii_case("false") || s.eq_ignore_ascii_case("no") {
Ok(false)
} else {
Err(Error::msg(format!("cannot parse `{s}` as a bool")))
}
}
#[inline]
pub(super) fn parse_char(s: &str) -> Result<char> {
let mut char_li = s.chars();
let c = char_li
.next()
.ok_or_else(|| Error::msg("an empty string cannot be parsed as a char"))?;
if char_li.next().is_some() {
return Err(Error::msg(format!("`{s}` is not a single character")));
}
Ok(c)
}
pub(super) struct ScalarDe<'de>(pub Cow<'de, str>);
macro_rules! scalar_numeric {
($($de:ident => $visit:ident => $t:ty),* $(,)?) => {
$(
#[inline]
fn $de<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let s = self.0.as_ref();
let n: $t = s
.trim()
.parse()
.map_err(|_| Error::msg(format!("cannot parse `{s}` as {}", stringify!($t))))?;
visitor.$visit(n)
}
)*
};
}
impl<'de> ScalarDe<'de> {
#[inline]
fn visit_cow<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match self.0 {
Cow::Borrowed(s) => visitor.visit_borrowed_str(s),
Cow::Owned(s) => visitor.visit_string(s),
}
}
}
impl<'de> de::Deserializer<'de> for ScalarDe<'de> {
type Error = Error;
#[inline]
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.visit_cow(visitor)
}
#[inline]
fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_bool(parse_bool(self.0.as_ref())?)
}
#[inline]
fn deserialize_char<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_char(parse_char(self.0.as_ref())?)
}
#[inline]
fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.visit_cow(visitor)
}
#[inline]
fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.visit_cow(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"))
}
#[inline]
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
if self.0.is_empty() {
visitor.visit_none()
} else {
visitor.visit_some(self)
}
}
#[inline]
fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
if self.0.is_empty() {
visitor.visit_unit()
} else {
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, _: V) -> Result<V::Value> {
Err(Error::msg("expected a list value"))
}
fn deserialize_tuple<V: Visitor<'de>>(self, _: usize, _: V) -> Result<V::Value> {
Err(Error::msg("expected a list value"))
}
fn deserialize_tuple_struct<V: Visitor<'de>>(
self,
_: &'static str,
_: usize,
_: V,
) -> Result<V::Value> {
Err(Error::msg("expected a list value"))
}
fn deserialize_map<V: Visitor<'de>>(self, _: V) -> Result<V::Value> {
Err(Error::msg("expected a dictionary value"))
}
fn deserialize_struct<V: Visitor<'de>>(
self,
_: &'static str,
_: &'static [&'static str],
_: V,
) -> Result<V::Value> {
Err(Error::msg("expected a dictionary value"))
}
fn deserialize_enum<V: Visitor<'de>>(
self,
_: &'static str,
_: &'static [&'static str],
visitor: V,
) -> Result<V::Value> {
match &self.0 {
Cow::Borrowed(b) => visitor.visit_enum(BorrowedStrDeserializer::new(b)),
Cow::Owned(o) => visitor.visit_enum(o.as_str().into_deserializer()),
}
}
#[inline]
fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.visit_cow(visitor)
}
#[inline]
fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_unit()
}
scalar_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,
}
}
pub(super) struct KeyDe<'a, 'de: 'a>(pub &'a Cow<'de, str>);
impl<'a, 'de: 'a> de::Deserializer<'de> for KeyDe<'a, 'de> {
type Error = Error;
#[inline]
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match self.0 {
Cow::Borrowed(s) => visitor.visit_borrowed_str(s),
Cow::Owned(s) => visitor.visit_str(s),
}
}
#[inline]
fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.deserialize_any(visitor)
}
#[inline]
fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.deserialize_any(visitor)
}
#[inline]
fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.deserialize_any(visitor)
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char bytes
byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum ignored_any
}
}