serde_nt 0.1.12

NestedText (de)serialization for serde, powered by nt_syntax
Documentation
//! 从已解析 `Value` 树反序列化(支持 [`from_value`] 与行内集合回退)。

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