serde_nt 0.1.12

NestedText (de)serialization for serde, powered by nt_syntax
Documentation
//! `to_value`:序列化为拥有所有权的 `nt_syntax::Value<'static>`(静态字面量用 `Cow::Borrowed` 零分配)。

use std::borrow::Cow;

use itoa::{Buffer as ItoaBuffer, Integer};
use nt_syntax::Value;
use serde::{
  Serialize,
  ser::{
    self, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
    SerializeTupleStruct, SerializeTupleVariant,
  },
};
use zmij::{Buffer as ZmijBuffer, Float};

use crate::error::{Error, Result};

/// 序列化为拥有所有权的 [`Value<'static>`]
pub fn to_value<T: Serialize + ?Sized>(value: &T) -> Result<Value<'static>> {
  value.serialize(ValueSer)
}

struct ValueSer;

macro_rules! val_int {
  ($($method:ident => $t:ty),* $(,)?) => {
    $(
      fn $method(self, v: $t) -> Result<Value<'static>> {
        Ok(int(v))
      }
    )*
  };
}

impl ser::Serializer for ValueSer {
  type Ok = Value<'static>;
  type Error = Error;
  type SerializeSeq = SeqSer;
  type SerializeTuple = SeqSer;
  type SerializeTupleStruct = SeqSer;
  type SerializeTupleVariant = TupleVariantSer;
  type SerializeMap = MapSer;
  type SerializeStruct = MapSer;
  type SerializeStructVariant = StructVariantSer;

  fn serialize_bool(self, v: bool) -> Result<Value<'static>> {
    Ok(Value::Str(Cow::Borrowed(if v { "true" } else { "false" })))
  }

  val_int! {
    serialize_i8 => i8,
    serialize_i16 => i16,
    serialize_i32 => i32,
    serialize_i64 => i64,
    serialize_i128 => i128,
    serialize_u8 => u8,
    serialize_u16 => u16,
    serialize_u32 => u32,
    serialize_u64 => u64,
    serialize_u128 => u128,
  }

  fn serialize_f32(self, v: f32) -> Result<Value<'static>> {
    Ok(float(v))
  }

  fn serialize_f64(self, v: f64) -> Result<Value<'static>> {
    Ok(float(v))
  }

  fn serialize_char(self, v: char) -> Result<Value<'static>> {
    Ok(Value::Str(Cow::Owned(v.to_string())))
  }

  fn serialize_str(self, v: &str) -> Result<Value<'static>> {
    Ok(Value::Str(Cow::Owned(v.to_owned())))
  }

  fn serialize_bytes(self, _: &[u8]) -> Result<Value<'static>> {
    Err(Error::msg("NestedText does not support byte arrays"))
  }

  fn serialize_none(self) -> Result<Value<'static>> {
    Ok(Value::empty_str())
  }

  fn serialize_some<T: Serialize + ?Sized>(self, value: &T) -> Result<Value<'static>> {
    value.serialize(self)
  }

  fn serialize_unit(self) -> Result<Value<'static>> {
    Ok(Value::empty_str())
  }

  fn serialize_unit_struct(self, _: &'static str) -> Result<Value<'static>> {
    Ok(Value::empty_str())
  }

  fn serialize_unit_variant(
    self,
    _: &'static str,
    _: u32,
    variant: &'static str,
  ) -> Result<Value<'static>> {
    Ok(Value::Str(Cow::Borrowed(variant)))
  }

  fn serialize_newtype_struct<T: Serialize + ?Sized>(
    self,
    _: &'static str,
    value: &T,
  ) -> Result<Value<'static>> {
    value.serialize(self)
  }

  fn serialize_newtype_variant<T: Serialize + ?Sized>(
    self,
    _: &'static str,
    _: u32,
    variant: &'static str,
    value: &T,
  ) -> Result<Value<'static>> {
    Ok(Value::Dict(vec![(
      Cow::Borrowed(variant),
      value.serialize(self)?,
    )]))
  }

  fn serialize_seq(self, len: Option<usize>) -> Result<SeqSer> {
    Ok(SeqSer {
      item_li: Vec::with_capacity(len.unwrap_or(0)),
    })
  }

  fn serialize_tuple(self, len: usize) -> Result<SeqSer> {
    self.serialize_seq(Some(len))
  }

  fn serialize_tuple_struct(self, _: &'static str, len: usize) -> Result<SeqSer> {
    self.serialize_seq(Some(len))
  }

  fn serialize_tuple_variant(
    self,
    _: &'static str,
    _: u32,
    variant: &'static str,
    len: usize,
  ) -> Result<TupleVariantSer> {
    Ok(TupleVariantSer {
      variant,
      item_li: Vec::with_capacity(len),
    })
  }

  fn serialize_map(self, len: Option<usize>) -> Result<MapSer> {
    Ok(MapSer {
      pair_li: Vec::with_capacity(len.unwrap_or(0)),
      key: None,
    })
  }

  fn serialize_struct(self, _: &'static str, len: usize) -> Result<MapSer> {
    self.serialize_map(Some(len))
  }

  fn serialize_struct_variant(
    self,
    _: &'static str,
    _: u32,
    variant: &'static str,
    len: usize,
  ) -> Result<StructVariantSer> {
    Ok(StructVariantSer {
      variant,
      pair_li: Vec::with_capacity(len),
    })
  }
}

fn int(v: impl Integer) -> Value<'static> {
  let mut buf = ItoaBuffer::new();
  Value::Str(Cow::Owned(buf.format(v).to_owned()))
}

fn float(v: impl Float) -> Value<'static> {
  let mut buf = ZmijBuffer::new();
  Value::Str(Cow::Owned(buf.format(v).to_owned()))
}

pub struct SeqSer {
  item_li: Vec<Value<'static>>,
}

impl SerializeSeq for SeqSer {
  type Ok = Value<'static>;
  type Error = Error;

  fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
    self.item_li.push(value.serialize(ValueSer)?);
    Ok(())
  }

  fn end(self) -> Result<Value<'static>> {
    Ok(Value::List(self.item_li))
  }
}

impl SerializeTuple for SeqSer {
  type Ok = Value<'static>;
  type Error = Error;

  fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
    SerializeSeq::serialize_element(self, value)
  }

  fn end(self) -> Result<Value<'static>> {
    SerializeSeq::end(self)
  }
}

impl SerializeTupleStruct for SeqSer {
  type Ok = Value<'static>;
  type Error = Error;

  fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
    SerializeSeq::serialize_element(self, value)
  }

  fn end(self) -> Result<Value<'static>> {
    SerializeSeq::end(self)
  }
}

pub struct TupleVariantSer {
  variant: &'static str,
  item_li: Vec<Value<'static>>,
}

impl SerializeTupleVariant for TupleVariantSer {
  type Ok = Value<'static>;
  type Error = Error;

  fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
    self.item_li.push(value.serialize(ValueSer)?);
    Ok(())
  }

  fn end(self) -> Result<Value<'static>> {
    Ok(Value::Dict(vec![(
      Cow::Borrowed(self.variant),
      Value::List(self.item_li),
    )]))
  }
}

pub struct MapSer {
  pair_li: Vec<(Cow<'static, str>, Value<'static>)>,
  key: Option<Cow<'static, str>>,
}

impl SerializeMap for MapSer {
  type Ok = Value<'static>;
  type Error = Error;

  fn serialize_key<T: Serialize + ?Sized>(&mut self, key: &T) -> Result<()> {
    self.key = Some(match key.serialize(ValueSer)? {
      Value::Str(s) => s,
      _ => return Err(Error::msg("NestedText dictionary keys must be strings")),
    });
    Ok(())
  }

  fn serialize_value<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
    let key = self
      .key
      .take()
      .ok_or_else(|| Error::msg("missing dictionary key"))?;
    self.pair_li.push((key, value.serialize(ValueSer)?));
    Ok(())
  }

  fn end(self) -> Result<Value<'static>> {
    Ok(Value::Dict(self.pair_li))
  }
}

impl SerializeStruct for MapSer {
  type Ok = Value<'static>;
  type Error = Error;

  fn serialize_field<T: Serialize + ?Sized>(&mut self, key: &'static str, value: &T) -> Result<()> {
    self
      .pair_li
      .push((Cow::Borrowed(key), value.serialize(ValueSer)?));
    Ok(())
  }

  fn end(self) -> Result<Value<'static>> {
    Ok(Value::Dict(self.pair_li))
  }
}

pub struct StructVariantSer {
  variant: &'static str,
  pair_li: Vec<(Cow<'static, str>, Value<'static>)>,
}

impl SerializeStructVariant for StructVariantSer {
  type Ok = Value<'static>;
  type Error = Error;

  fn serialize_field<T: Serialize + ?Sized>(&mut self, key: &'static str, value: &T) -> Result<()> {
    self
      .pair_li
      .push((Cow::Borrowed(key), value.serialize(ValueSer)?));
    Ok(())
  }

  fn end(self) -> Result<Value<'static>> {
    Ok(Value::Dict(vec![(
      Cow::Borrowed(self.variant),
      Value::Dict(self.pair_li),
    )]))
  }
}