use std::fmt::Write as FmtWrite;
use crate::error::{Error, Result};
use serde::ser::{self, Serialize};
pub fn to_string<T: Serialize>(value: &T) -> Result<String> {
let mut ser = Serializer::new(0);
value.serialize(&mut ser)?;
Ok(ser.output)
}
pub struct Serializer {
pub(crate) output: String,
indent: usize,
}
impl Serializer {
fn new(indent: usize) -> Self {
Serializer {
output: String::new(),
indent,
}
}
fn pad(&self) -> String {
" ".repeat(self.indent)
}
}
fn escape(s: &str) -> String {
if s.chars()
.any(|c| matches!(c, ' ' | '\t' | '\n' | '\r' | '#' | '{' | '}' | '='))
{
format!("\"{s}\"")
} else {
s.to_owned()
}
}
impl<'a> ser::Serializer for &'a mut Serializer {
type Ok = ();
type Error = Error;
type SerializeSeq = SeqSerializer<'a>;
type SerializeTuple = SeqSerializer<'a>;
type SerializeTupleStruct = SeqSerializer<'a>;
type SerializeTupleVariant = SeqSerializer<'a>;
type SerializeMap = MapSerializer<'a>;
type SerializeStruct = MapSerializer<'a>;
type SerializeStructVariant = MapSerializer<'a>;
fn serialize_bool(self, v: bool) -> Result<()> {
self.output.push_str(if v { "true" } else { "false" });
Ok(())
}
fn serialize_i8(self, v: i8) -> Result<()> {
write!(self.output, "{v}").map_err(|e| Error::Message(e.to_string()))
}
fn serialize_i16(self, v: i16) -> Result<()> {
write!(self.output, "{v}").map_err(|e| Error::Message(e.to_string()))
}
fn serialize_i32(self, v: i32) -> Result<()> {
write!(self.output, "{v}").map_err(|e| Error::Message(e.to_string()))
}
fn serialize_i64(self, v: i64) -> Result<()> {
write!(self.output, "{v}").map_err(|e| Error::Message(e.to_string()))
}
fn serialize_u8(self, v: u8) -> Result<()> {
write!(self.output, "{v}").map_err(|e| Error::Message(e.to_string()))
}
fn serialize_u16(self, v: u16) -> Result<()> {
write!(self.output, "{v}").map_err(|e| Error::Message(e.to_string()))
}
fn serialize_u32(self, v: u32) -> Result<()> {
write!(self.output, "{v}").map_err(|e| Error::Message(e.to_string()))
}
fn serialize_u64(self, v: u64) -> Result<()> {
write!(self.output, "{v}").map_err(|e| Error::Message(e.to_string()))
}
fn serialize_f32(self, v: f32) -> Result<()> {
write!(self.output, "{v}").map_err(|e| Error::Message(e.to_string()))
}
fn serialize_f64(self, v: f64) -> Result<()> {
write!(self.output, "{v}").map_err(|e| Error::Message(e.to_string()))
}
fn serialize_char(self, v: char) -> Result<()> {
self.output.push_str(&escape(&v.to_string()));
Ok(())
}
fn serialize_str(self, v: &str) -> Result<()> {
self.output.push_str(&escape(v));
Ok(())
}
fn serialize_bytes(self, _v: &[u8]) -> Result<()> {
Err(Error::UnsupportedType("bytes"))
}
fn serialize_none(self) -> Result<()> {
self.output.push_str("null");
Ok(())
}
fn serialize_some<T: Serialize + ?Sized>(self, value: &T) -> Result<()> {
value.serialize(self)
}
fn serialize_unit(self) -> Result<()> {
self.output.push_str("null");
Ok(())
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
self.serialize_unit()
}
fn serialize_unit_variant(
self,
_name: &'static str,
_index: u32,
variant: &'static str,
) -> Result<()> {
self.serialize_str(variant)
}
fn serialize_newtype_struct<T: Serialize + ?Sized>(
self,
_name: &'static str,
value: &T,
) -> Result<()> {
value.serialize(self)
}
fn serialize_newtype_variant<T: Serialize + ?Sized>(
self,
_name: &'static str,
_index: u32,
variant: &'static str,
value: &T,
) -> Result<()> {
let mut ms = MapSerializer {
ser: self,
current_key: None,
variant_name: None,
};
ms.write_kv(variant, value)
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
Ok(SeqSerializer {
parent: self,
items: Vec::new(),
variant: None,
})
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_struct(
self,
_name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_index: u32,
variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant> {
Ok(SeqSerializer {
parent: self,
items: Vec::new(),
variant: Some(variant.to_owned()),
})
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
Ok(MapSerializer {
ser: self,
current_key: None,
variant_name: None,
})
}
fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
self.serialize_map(Some(len))
}
fn serialize_struct_variant(
self,
_name: &'static str,
_index: u32,
variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant> {
Ok(MapSerializer {
ser: self,
current_key: None,
variant_name: Some(variant.to_owned()),
})
}
}
pub struct SeqSerializer<'a> {
parent: &'a mut Serializer,
items: Vec<String>,
variant: Option<String>,
}
impl ser::SerializeSeq for SeqSerializer<'_> {
type Ok = ();
type Error = Error;
fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
let mut inner = Serializer::new(0);
value.serialize(&mut inner)?;
self.items.push(inner.output);
Ok(())
}
fn end(self) -> Result<()> {
let pad = self.parent.pad();
let inner_pad = " ".repeat(self.parent.indent + 2);
writeln!(self.parent.output, "{{").map_err(|e| Error::Message(e.to_string()))?;
for item in &self.items {
writeln!(self.parent.output, "{inner_pad}{item}")
.map_err(|e| Error::Message(e.to_string()))?;
}
writeln!(self.parent.output, "{pad}}}").map_err(|e| Error::Message(e.to_string()))
}
}
impl ser::SerializeTuple for SeqSerializer<'_> {
type Ok = ();
type Error = Error;
fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
ser::SerializeSeq::serialize_element(self, value)
}
fn end(self) -> Result<()> {
ser::SerializeSeq::end(self)
}
}
impl ser::SerializeTupleStruct for SeqSerializer<'_> {
type Ok = ();
type Error = Error;
fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
ser::SerializeSeq::serialize_element(self, value)
}
fn end(self) -> Result<()> {
ser::SerializeSeq::end(self)
}
}
impl ser::SerializeTupleVariant for SeqSerializer<'_> {
type Ok = ();
type Error = Error;
fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
ser::SerializeSeq::serialize_element(self, value)
}
fn end(self) -> Result<()> {
let variant = self.variant.ok_or_else(|| {
Error::Message("variant name missing in SerializeTupleVariant::end".into())
})?;
let pad = self.parent.pad();
let inner_pad = " ".repeat(self.parent.indent + 2);
writeln!(self.parent.output, "{pad}{} = {{", escape(&variant))
.map_err(|e| Error::Message(e.to_string()))?;
for item in &self.items {
writeln!(self.parent.output, "{inner_pad}{item}")
.map_err(|e| Error::Message(e.to_string()))?;
}
writeln!(self.parent.output, "{pad}}}").map_err(|e| Error::Message(e.to_string()))
}
}
struct KeySerializer(String);
impl ser::Serializer for &mut KeySerializer {
type Ok = ();
type Error = Error;
type SerializeSeq = ser::Impossible<(), Error>;
type SerializeTuple = ser::Impossible<(), Error>;
type SerializeTupleStruct = ser::Impossible<(), Error>;
type SerializeTupleVariant = ser::Impossible<(), Error>;
type SerializeMap = ser::Impossible<(), Error>;
type SerializeStruct = ser::Impossible<(), Error>;
type SerializeStructVariant = ser::Impossible<(), Error>;
fn serialize_str(self, v: &str) -> Result<()> {
v.clone_into(&mut self.0);
Ok(())
}
fn serialize_bool(self, _v: bool) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_i8(self, _v: i8) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_i16(self, _v: i16) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_i32(self, _v: i32) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_i64(self, _v: i64) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_u8(self, _v: u8) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_u16(self, _v: u16) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_u32(self, _v: u32) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_u64(self, _v: u64) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_f32(self, _v: f32) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_f64(self, _v: f64) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_char(self, _v: char) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_bytes(self, _v: &[u8]) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_none(self) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_some<T: Serialize + ?Sized>(self, _v: &T) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_unit(self) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_unit_variant(
self,
_name: &'static str,
_idx: u32,
_variant: &'static str,
) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_newtype_struct<T: Serialize + ?Sized>(
self,
_name: &'static str,
value: &T,
) -> Result<()> {
value.serialize(self)
}
fn serialize_newtype_variant<T: Serialize + ?Sized>(
self,
_name: &'static str,
_idx: u32,
_variant: &'static str,
_value: &T,
) -> Result<()> {
Err(Error::KeyMustBeString)
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
Err(Error::KeyMustBeString)
}
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
Err(Error::KeyMustBeString)
}
fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleStruct> {
Err(Error::KeyMustBeString)
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_idx: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant> {
Err(Error::KeyMustBeString)
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
Err(Error::KeyMustBeString)
}
fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
Err(Error::KeyMustBeString)
}
fn serialize_struct_variant(
self,
_name: &'static str,
_idx: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant> {
Err(Error::KeyMustBeString)
}
}
pub struct MapSerializer<'a> {
ser: &'a mut Serializer,
current_key: Option<String>,
variant_name: Option<String>,
}
impl MapSerializer<'_> {
fn write_kv<T: Serialize + ?Sized>(&mut self, key: &str, value: &T) -> Result<()> {
let indent = self.ser.indent;
let pad = " ".repeat(indent);
let mut first = Serializer::new(indent);
value.serialize(&mut first)?;
let rendered = first.output;
if rendered.contains('\n')
&& !rendered.trim_start().starts_with('{')
&& !rendered.trim_start().starts_with('"')
{
writeln!(self.ser.output, "{pad}{} {{", escape(key))
.map_err(|e| Error::Message(e.to_string()))?;
let mut inner = Serializer::new(indent + 2);
value.serialize(&mut inner)?;
self.ser.output.push_str(&inner.output);
writeln!(self.ser.output, "{pad}}}").map_err(|e| Error::Message(e.to_string()))?;
} else if rendered.contains('\n') {
writeln!(
self.ser.output,
"{pad}{} = {}",
escape(key),
rendered.trim_end()
)
.map_err(|e| Error::Message(e.to_string()))?;
} else {
let rendered = rendered.trim_end_matches('\n');
writeln!(self.ser.output, "{pad}{} = {rendered}", escape(key))
.map_err(|e| Error::Message(e.to_string()))?;
}
Ok(())
}
}
impl ser::SerializeMap for MapSerializer<'_> {
type Ok = ();
type Error = Error;
fn serialize_key<T: Serialize + ?Sized>(&mut self, key: &T) -> Result<()> {
let mut ks = KeySerializer(String::new());
key.serialize(&mut ks)?;
self.current_key = Some(ks.0);
Ok(())
}
fn serialize_value<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
let key = self
.current_key
.take()
.ok_or_else(|| Error::Parse("serialize_value called before serialize_key".into()))?;
self.write_kv(&key, value)
}
fn end(self) -> Result<()> {
if let Some(variant) = self.variant_name {
let pad = " ".repeat(self.ser.indent.saturating_sub(2));
let header = format!("{pad}{} {{\n", escape(&variant));
let footer = format!("{pad}}}\n");
self.ser.output.insert_str(0, &header);
self.ser.output.push_str(&footer);
}
Ok(())
}
}
impl ser::SerializeStruct for MapSerializer<'_> {
type Ok = ();
type Error = Error;
fn serialize_field<T: Serialize + ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<()> {
self.write_kv(key, value)
}
fn end(self) -> Result<()> {
ser::SerializeMap::end(self)
}
}
impl ser::SerializeStructVariant for MapSerializer<'_> {
type Ok = ();
type Error = Error;
fn serialize_field<T: Serialize + ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<()> {
self.write_kv(key, value)
}
fn end(self) -> Result<()> {
ser::SerializeMap::end(self)
}
}