serde_nt 0.1.12

NestedText (de)serialization for serde, powered by nt_syntax
Documentation
//! 零拷贝标量与字典键反序列化原语(由 `stream` 与 `val` 共享)。

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)
}

/// 已提取出的单行/多行纯字符串标量反序列化器(栈上 `Cow`,零附加分配)
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,
  }
}

/// 值树字典键反序列化器:借用引用不克隆 Owned `String`
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
  }
}