use crate::dumper::{dumps, DumpOptions};
use crate::error::{Error, ErrorKind};
use crate::value::Value;
use serde::ser::{self, Serialize};
pub fn to_string<T: Serialize>(value: &T) -> Result<String, Error> {
let v = value.serialize(ValueSerializer)?;
Ok(dumps(&v, &DumpOptions::default()))
}
pub fn to_string_with_options<T: Serialize>(
value: &T,
options: &DumpOptions,
) -> Result<String, Error> {
let v = value.serialize(ValueSerializer)?;
Ok(dumps(&v, options))
}
struct ValueSerializer;
impl ser::Serializer for ValueSerializer {
type Ok = Value;
type Error = Error;
type SerializeSeq = SeqSerializer;
type SerializeTuple = SeqSerializer;
type SerializeTupleStruct = SeqSerializer;
type SerializeTupleVariant = TupleVariantSerializer;
type SerializeMap = MapSerializer;
type SerializeStruct = MapSerializer;
type SerializeStructVariant = StructVariantSerializer;
fn serialize_bool(self, v: bool) -> Result<Value, Error> {
Ok(Value::String(v.to_string()))
}
fn serialize_i8(self, v: i8) -> Result<Value, Error> {
Ok(Value::String(v.to_string()))
}
fn serialize_i16(self, v: i16) -> Result<Value, Error> {
Ok(Value::String(v.to_string()))
}
fn serialize_i32(self, v: i32) -> Result<Value, Error> {
Ok(Value::String(v.to_string()))
}
fn serialize_i64(self, v: i64) -> Result<Value, Error> {
Ok(Value::String(v.to_string()))
}
fn serialize_u8(self, v: u8) -> Result<Value, Error> {
Ok(Value::String(v.to_string()))
}
fn serialize_u16(self, v: u16) -> Result<Value, Error> {
Ok(Value::String(v.to_string()))
}
fn serialize_u32(self, v: u32) -> Result<Value, Error> {
Ok(Value::String(v.to_string()))
}
fn serialize_u64(self, v: u64) -> Result<Value, Error> {
Ok(Value::String(v.to_string()))
}
fn serialize_f32(self, v: f32) -> Result<Value, Error> {
Ok(Value::String(v.to_string()))
}
fn serialize_f64(self, v: f64) -> Result<Value, Error> {
Ok(Value::String(v.to_string()))
}
fn serialize_char(self, v: char) -> Result<Value, Error> {
Ok(Value::String(v.to_string()))
}
fn serialize_str(self, v: &str) -> Result<Value, Error> {
Ok(Value::String(v.to_string()))
}
fn serialize_bytes(self, _v: &[u8]) -> Result<Value, Error> {
Err(Error::new(
ErrorKind::UnsupportedType,
"NestedText does not support byte arrays",
))
}
fn serialize_none(self) -> Result<Value, Error> {
Ok(Value::String(String::new()))
}
fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Value, Error> {
value.serialize(self)
}
fn serialize_unit(self) -> Result<Value, Error> {
Ok(Value::String(String::new()))
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<Value, Error> {
Ok(Value::String(String::new()))
}
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> Result<Value, Error> {
Ok(Value::String(variant.to_string()))
}
fn serialize_newtype_struct<T: ?Sized + Serialize>(
self,
_name: &'static str,
value: &T,
) -> Result<Value, Error> {
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized + Serialize>(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<Value, Error> {
let inner = value.serialize(ValueSerializer)?;
Ok(Value::Dict(vec![(variant.to_string(), inner)]))
}
fn serialize_seq(self, len: Option<usize>) -> Result<SeqSerializer, Error> {
Ok(SeqSerializer {
items: Vec::with_capacity(len.unwrap_or(0)),
})
}
fn serialize_tuple(self, len: usize) -> Result<SeqSerializer, Error> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_struct(
self,
_name: &'static str,
len: usize,
) -> Result<SeqSerializer, Error> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<TupleVariantSerializer, Error> {
Ok(TupleVariantSerializer {
variant: variant.to_string(),
items: Vec::with_capacity(len),
})
}
fn serialize_map(self, len: Option<usize>) -> Result<MapSerializer, Error> {
Ok(MapSerializer {
pairs: Vec::with_capacity(len.unwrap_or(0)),
next_key: None,
})
}
fn serialize_struct(
self,
_name: &'static str,
len: usize,
) -> Result<MapSerializer, Error> {
self.serialize_map(Some(len))
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<StructVariantSerializer, Error> {
Ok(StructVariantSerializer {
variant: variant.to_string(),
pairs: Vec::with_capacity(len),
})
}
}
struct SeqSerializer {
items: Vec<Value>,
}
impl ser::SerializeSeq for SeqSerializer {
type Ok = Value;
type Error = Error;
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Error> {
self.items.push(value.serialize(ValueSerializer)?);
Ok(())
}
fn end(self) -> Result<Value, Error> {
Ok(Value::List(self.items))
}
}
impl ser::SerializeTuple for SeqSerializer {
type Ok = Value;
type Error = Error;
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Error> {
ser::SerializeSeq::serialize_element(self, value)
}
fn end(self) -> Result<Value, Error> {
ser::SerializeSeq::end(self)
}
}
impl ser::SerializeTupleStruct for SeqSerializer {
type Ok = Value;
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Error> {
ser::SerializeSeq::serialize_element(self, value)
}
fn end(self) -> Result<Value, Error> {
ser::SerializeSeq::end(self)
}
}
struct TupleVariantSerializer {
variant: String,
items: Vec<Value>,
}
impl ser::SerializeTupleVariant for TupleVariantSerializer {
type Ok = Value;
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Error> {
self.items.push(value.serialize(ValueSerializer)?);
Ok(())
}
fn end(self) -> Result<Value, Error> {
Ok(Value::Dict(vec![(
self.variant,
Value::List(self.items),
)]))
}
}
struct MapSerializer {
pairs: Vec<(String, Value)>,
next_key: Option<String>,
}
impl ser::SerializeMap for MapSerializer {
type Ok = Value;
type Error = Error;
fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<(), Error> {
let key_value = key.serialize(ValueSerializer)?;
let key_str = match key_value {
Value::String(s) => s,
_ => {
return Err(Error::new(
ErrorKind::UnsupportedType,
"map keys must be strings",
))
}
};
self.next_key = Some(key_str);
Ok(())
}
fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Error> {
let key = self.next_key.take().expect("serialize_value called before serialize_key");
self.pairs.push((key, value.serialize(ValueSerializer)?));
Ok(())
}
fn end(self) -> Result<Value, Error> {
Ok(Value::Dict(self.pairs))
}
}
impl ser::SerializeStruct for MapSerializer {
type Ok = Value;
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Error> {
self.pairs
.push((key.to_string(), value.serialize(ValueSerializer)?));
Ok(())
}
fn end(self) -> Result<Value, Error> {
Ok(Value::Dict(self.pairs))
}
}
struct StructVariantSerializer {
variant: String,
pairs: Vec<(String, Value)>,
}
impl ser::SerializeStructVariant for StructVariantSerializer {
type Ok = Value;
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Error> {
self.pairs
.push((key.to_string(), value.serialize(ValueSerializer)?));
Ok(())
}
fn end(self) -> Result<Value, Error> {
Ok(Value::Dict(vec![(
self.variant,
Value::Dict(self.pairs),
)]))
}
}
impl ser::Error for Error {
fn custom<T: std::fmt::Display>(msg: T) -> Self {
Error::new(ErrorKind::UnsupportedType, msg.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde::Serialize;
#[test]
fn test_serialize_struct() {
#[derive(Serialize)]
struct Config {
name: String,
age: u32,
}
let config = Config {
name: "Alice".to_string(),
age: 30,
};
let s = to_string(&config).unwrap();
assert_eq!(s, "name: Alice\nage: 30\n");
}
#[test]
fn test_serialize_vec() {
let v = vec!["hello", "world"];
let s = to_string(&v).unwrap();
assert_eq!(s, "- hello\n- world\n");
}
#[test]
fn test_serialize_bool() {
#[derive(Serialize)]
struct Flags {
debug: bool,
}
let flags = Flags { debug: true };
let s = to_string(&flags).unwrap();
assert_eq!(s, "debug: true\n");
}
#[test]
fn test_serialize_option() {
#[derive(Serialize)]
struct MaybeValue {
present: Option<String>,
absent: Option<String>,
}
let v = MaybeValue {
present: Some("hello".to_string()),
absent: None,
};
let s = to_string(&v).unwrap();
assert_eq!(s, "present: hello\nabsent:\n");
}
#[test]
fn test_serialize_enum() {
#[derive(Serialize)]
enum Color {
Red,
}
let s = to_string(&Color::Red).unwrap();
assert_eq!(s, "> Red\n");
}
#[test]
fn test_serialize_nested() {
#[derive(Serialize)]
struct Outer {
items: Vec<String>,
}
let v = Outer {
items: vec!["a".to_string(), "b".to_string()],
};
let s = to_string(&v).unwrap();
assert_eq!(s, "items:\n - a\n - b\n");
}
}