mod val;
use itoa::Buffer as ItoaBuffer;
use nt_syntax::{STEP, push_indent};
use serde::{
Serialize,
ser::{
self, Impossible, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant,
},
};
pub use val::to_value;
use zmij::Buffer as ZmijBuffer;
use crate::{
dump::{is_inline_key, multiline, write_multiline_key, write_str_block},
error::{Error, Result},
};
pub fn to_string<T: Serialize + ?Sized>(value: &T) -> Result<String> {
let mut out = String::with_capacity(128);
value.serialize(StreamSer {
out: &mut out,
depth: 0,
ctx: Ctx::Root,
})?;
Ok(out)
}
#[derive(Clone, Copy, PartialEq, Eq)]
enum Ctx {
Root,
AfterDash,
AfterColon,
BlockChild,
}
struct StreamSer<'a> {
out: &'a mut String,
depth: usize,
ctx: Ctx,
}
impl<'a> StreamSer<'a> {
#[inline]
fn emit_clean_scalar(self, s: &str) -> Result<()> {
match self.ctx {
Ctx::AfterColon | Ctx::AfterDash => {
if !s.is_empty() {
self.out.push(' ');
self.out.push_str(s);
}
self.out.push('\n');
}
Ctx::Root | Ctx::BlockChild => {
push_indent(self.out, self.depth);
if s.is_empty() {
self.out.push_str(">\n");
} else {
self.out.push_str("> ");
self.out.push_str(s);
self.out.push('\n');
}
}
}
Ok(())
}
fn emit_str(self, s: &str) -> Result<()> {
match self.ctx {
Ctx::AfterColon | Ctx::AfterDash => {
if s.is_empty() {
self.out.push('\n');
} else if !multiline(s) {
self.out.push(' ');
self.out.push_str(s);
self.out.push('\n');
} else {
self.out.push('\n');
write_str_block(self.out, self.depth + STEP, s);
}
}
Ctx::Root | Ctx::BlockChild => {
write_str_block(self.out, self.depth, s);
}
}
Ok(())
}
#[inline]
fn enter_container(&mut self) -> usize {
match self.ctx {
Ctx::AfterColon | Ctx::AfterDash => {
self.out.push('\n');
self.depth + STEP
}
Ctx::Root | Ctx::BlockChild => self.depth,
}
}
}
#[inline]
fn write_dict_key(out: &mut String, depth: usize, raw_key: &str) -> (usize, Ctx) {
if is_inline_key(raw_key) {
push_indent(out, depth);
out.push_str(raw_key);
out.push(':');
(depth, Ctx::AfterColon)
} else {
write_multiline_key(out, depth, raw_key);
(depth + STEP, Ctx::BlockChild)
}
}
macro_rules! stream_int {
($($method:ident => $t:ty),* $(,)?) => {
$(
#[inline]
fn $method(self, v: $t) -> Result<Self::Ok> {
let mut b = ItoaBuffer::new();
self.emit_clean_scalar(b.format(v))
}
)*
};
}
macro_rules! key_int {
($($method:ident => $t:ty),* $(,)?) => {
$(
#[inline]
fn $method(self, v: $t) -> Result<Self::Ok> {
let mut b = ItoaBuffer::new();
self.emit(b.format(v))
}
)*
};
}
impl<'a> ser::Serializer for StreamSer<'a> {
type Ok = ();
type Error = Error;
type SerializeSeq = StreamSeq<'a>;
type SerializeTuple = StreamSeq<'a>;
type SerializeTupleStruct = StreamSeq<'a>;
type SerializeTupleVariant = StreamTupleVariant<'a>;
type SerializeMap = StreamMap<'a>;
type SerializeStruct = StreamMap<'a>;
type SerializeStructVariant = StreamStructVariant<'a>;
#[inline]
fn serialize_bool(self, v: bool) -> Result<()> {
self.emit_clean_scalar(if v { "true" } else { "false" })
}
stream_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,
}
#[inline]
fn serialize_f32(self, v: f32) -> Result<()> {
let mut b = ZmijBuffer::new();
self.emit_clean_scalar(b.format(v))
}
#[inline]
fn serialize_f64(self, v: f64) -> Result<()> {
let mut b = ZmijBuffer::new();
self.emit_clean_scalar(b.format(v))
}
#[inline]
fn serialize_char(self, v: char) -> Result<()> {
let mut buf = [0u8; 4];
self.emit_str(v.encode_utf8(&mut buf))
}
#[inline]
fn serialize_str(self, v: &str) -> Result<()> {
self.emit_str(v)
}
fn serialize_bytes(self, _: &[u8]) -> Result<()> {
Err(Error::msg("NestedText does not support byte arrays"))
}
#[inline]
fn serialize_none(self) -> Result<()> {
self.emit_str("")
}
#[inline]
fn serialize_some<T: Serialize + ?Sized>(self, value: &T) -> Result<()> {
value.serialize(self)
}
#[inline]
fn serialize_unit(self) -> Result<()> {
self.emit_str("")
}
#[inline]
fn serialize_unit_struct(self, _: &'static str) -> Result<()> {
self.emit_str("")
}
#[inline]
fn serialize_unit_variant(self, _: &'static str, _: u32, variant: &'static str) -> Result<()> {
self.emit_str(variant)
}
#[inline]
fn serialize_newtype_struct<T: Serialize + ?Sized>(
self,
_: &'static str,
value: &T,
) -> Result<()> {
value.serialize(self)
}
fn serialize_newtype_variant<T: Serialize + ?Sized>(
mut self,
_: &'static str,
_: u32,
variant: &'static str,
value: &T,
) -> Result<()> {
let d = self.enter_container();
let (vd, vctx) = write_dict_key(self.out, d, variant);
value.serialize(StreamSer {
out: self.out,
depth: vd,
ctx: vctx,
})
}
fn serialize_seq(mut self, len: Option<usize>) -> Result<StreamSeq<'a>> {
let d = self.enter_container();
if d == 0
&& let Some(n) = len.filter(|&n| n > 0)
{
self.out.reserve(n.saturating_mul(16));
}
Ok(StreamSeq {
out: self.out,
depth: d,
count: 0,
})
}
fn serialize_tuple(self, len: usize) -> Result<StreamSeq<'a>> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_struct(self, _: &'static str, len: usize) -> Result<StreamSeq<'a>> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_variant(
mut self,
_: &'static str,
_: u32,
variant: &'static str,
_: usize,
) -> Result<StreamTupleVariant<'a>> {
let d = self.enter_container();
let (vd, vctx) = write_dict_key(self.out, d, variant);
let seq_depth = match vctx {
Ctx::AfterColon => {
self.out.push('\n');
vd + STEP
}
_ => vd,
};
Ok(StreamTupleVariant {
seq: StreamSeq {
out: self.out,
depth: seq_depth,
count: 0,
},
})
}
fn serialize_map(mut self, len: Option<usize>) -> Result<StreamMap<'a>> {
let d = self.enter_container();
if d == 0
&& let Some(n) = len.filter(|&n| n > 0)
{
self.out.reserve(n.saturating_mul(64));
}
Ok(StreamMap {
out: self.out,
depth: d,
count: 0,
val_target: None,
})
}
fn serialize_struct(self, _: &'static str, len: usize) -> Result<StreamMap<'a>> {
self.serialize_map(Some(len))
}
fn serialize_struct_variant(
mut self,
_: &'static str,
_: u32,
variant: &'static str,
_: usize,
) -> Result<StreamStructVariant<'a>> {
let d = self.enter_container();
let (vd, vctx) = write_dict_key(self.out, d, variant);
let map_depth = match vctx {
Ctx::AfterColon => {
self.out.push('\n');
vd + STEP
}
_ => vd,
};
Ok(StreamStructVariant {
map: StreamMap {
out: self.out,
depth: map_depth,
count: 0,
val_target: None,
},
})
}
}
pub struct StreamSeq<'a> {
out: &'a mut String,
depth: usize,
count: usize,
}
impl SerializeSeq for StreamSeq<'_> {
type Ok = ();
type Error = Error;
#[inline]
fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
self.count += 1;
push_indent(self.out, self.depth);
self.out.push('-');
value.serialize(StreamSer {
out: self.out,
depth: self.depth,
ctx: Ctx::AfterDash,
})
}
#[inline]
fn end(self) -> Result<()> {
if self.count == 0 {
push_indent(self.out, self.depth);
self.out.push_str("[]\n");
}
Ok(())
}
}
impl SerializeTuple for StreamSeq<'_> {
type Ok = ();
type Error = Error;
fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
SerializeSeq::serialize_element(self, value)
}
fn end(self) -> Result<()> {
SerializeSeq::end(self)
}
}
impl SerializeTupleStruct for StreamSeq<'_> {
type Ok = ();
type Error = Error;
fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
SerializeSeq::serialize_element(self, value)
}
fn end(self) -> Result<()> {
SerializeSeq::end(self)
}
}
pub struct StreamTupleVariant<'a> {
seq: StreamSeq<'a>,
}
impl SerializeTupleVariant for StreamTupleVariant<'_> {
type Ok = ();
type Error = Error;
fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
SerializeSeq::serialize_element(&mut self.seq, value)
}
fn end(self) -> Result<()> {
SerializeSeq::end(self.seq)
}
}
pub struct StreamMap<'a> {
out: &'a mut String,
depth: usize,
count: usize,
val_target: Option<(usize, Ctx)>,
}
impl SerializeMap for StreamMap<'_> {
type Ok = ();
type Error = Error;
#[inline]
fn serialize_key<T: Serialize + ?Sized>(&mut self, key: &T) -> Result<()> {
self.count += 1;
let target = key.serialize(KeyWriter {
out: self.out,
depth: self.depth,
})?;
self.val_target = Some(target);
Ok(())
}
#[inline]
fn serialize_value<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
let (vd, vctx) = self
.val_target
.take()
.ok_or_else(|| Error::msg("missing dictionary key"))?;
value.serialize(StreamSer {
out: self.out,
depth: vd,
ctx: vctx,
})
}
#[inline]
fn end(self) -> Result<()> {
if self.count == 0 {
push_indent(self.out, self.depth);
self.out.push_str("{}\n");
}
Ok(())
}
}
impl SerializeStruct for StreamMap<'_> {
type Ok = ();
type Error = Error;
#[inline]
fn serialize_field<T: Serialize + ?Sized>(&mut self, key: &'static str, value: &T) -> Result<()> {
self.count += 1;
let (vd, vctx) = write_dict_key(self.out, self.depth, key);
value.serialize(StreamSer {
out: self.out,
depth: vd,
ctx: vctx,
})
}
#[inline]
fn end(self) -> Result<()> {
SerializeMap::end(self)
}
}
pub struct StreamStructVariant<'a> {
map: StreamMap<'a>,
}
impl SerializeStructVariant for StreamStructVariant<'_> {
type Ok = ();
type Error = Error;
fn serialize_field<T: Serialize + ?Sized>(&mut self, key: &'static str, value: &T) -> Result<()> {
SerializeStruct::serialize_field(&mut self.map, key, value)
}
fn end(self) -> Result<()> {
SerializeStruct::end(self.map)
}
}
struct KeyWriter<'a> {
out: &'a mut String,
depth: usize,
}
impl KeyWriter<'_> {
#[inline]
fn emit(self, s: &str) -> Result<(usize, Ctx)> {
Ok(write_dict_key(self.out, self.depth, s))
}
}
impl ser::Serializer for KeyWriter<'_> {
type Ok = (usize, Ctx);
type Error = Error;
type SerializeSeq = Impossible<(usize, Ctx), Error>;
type SerializeTuple = Impossible<(usize, Ctx), Error>;
type SerializeTupleStruct = Impossible<(usize, Ctx), Error>;
type SerializeTupleVariant = Impossible<(usize, Ctx), Error>;
type SerializeMap = Impossible<(usize, Ctx), Error>;
type SerializeStruct = Impossible<(usize, Ctx), Error>;
type SerializeStructVariant = Impossible<(usize, Ctx), Error>;
fn serialize_bool(self, v: bool) -> Result<Self::Ok> {
self.emit(if v { "true" } else { "false" })
}
key_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<Self::Ok> {
let mut b = ZmijBuffer::new();
self.emit(b.format(v))
}
fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
let mut b = ZmijBuffer::new();
self.emit(b.format(v))
}
fn serialize_char(self, v: char) -> Result<Self::Ok> {
let mut buf = [0u8; 4];
self.emit(v.encode_utf8(&mut buf))
}
#[inline]
fn serialize_str(self, v: &str) -> Result<Self::Ok> {
self.emit(v)
}
fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok> {
Err(Error::msg("NestedText dictionary keys must be strings"))
}
fn serialize_none(self) -> Result<Self::Ok> {
self.emit("")
}
fn serialize_some<T: Serialize + ?Sized>(self, value: &T) -> Result<Self::Ok> {
value.serialize(self)
}
fn serialize_unit(self) -> Result<Self::Ok> {
self.emit("")
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok> {
self.emit("")
}
fn serialize_unit_variant(self, _: &'static str, _: u32, v: &'static str) -> Result<Self::Ok> {
self.emit(v)
}
fn serialize_newtype_struct<T: Serialize + ?Sized>(
self,
_: &'static str,
value: &T,
) -> Result<Self::Ok> {
value.serialize(self)
}
fn serialize_newtype_variant<T: Serialize + ?Sized>(
self,
_: &'static str,
_: u32,
_: &'static str,
_: &T,
) -> Result<Self::Ok> {
Err(Error::msg("NestedText dictionary keys must be strings"))
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq> {
Err(Error::msg("NestedText dictionary keys must be strings"))
}
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple> {
Err(Error::msg("NestedText dictionary keys must be strings"))
}
fn serialize_tuple_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeTupleStruct> {
Err(Error::msg("NestedText dictionary keys must be strings"))
}
fn serialize_tuple_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleVariant> {
Err(Error::msg("NestedText dictionary keys must be strings"))
}
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap> {
Err(Error::msg("NestedText dictionary keys must be strings"))
}
fn serialize_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeStruct> {
Err(Error::msg("NestedText dictionary keys must be strings"))
}
fn serialize_struct_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
_: usize,
) -> Result<Self::SerializeStructVariant> {
Err(Error::msg("NestedText dictionary keys must be strings"))
}
}