~cdv/sexprs

4278f705d8aa38a00986f0e03607ab26fa4cf711 — Chris Vittal 6 months ago acdd134
Serializer
2 files changed, 789 insertions(+), 225 deletions(-)

M Cargo.toml
M src/ser.rs
M Cargo.toml => Cargo.toml +4 -0
@@ 13,3 13,7 @@ readme = "README.md"
[dependencies]
serde = "1"
itoa = "0.4"
ryu = "1"

[dev-dependencies]
serde = {version = "1", features = ["derive"]}

M src/ser.rs => src/ser.rs +785 -225
@@ 1,391 1,951 @@
use std::io::{self, Write};
use std::io;

use serde::ser;

use crate::{Error, Result};

pub fn to_string<T>(_value: &T) -> Result<String>
where
    T: ser::Serialize + ?Sized,
{
    todo!()
pub struct Serializer<W, F = CompactFormatter> {
    writer: W,
    fmt: F,
}

pub struct Serializer<W> {
    writer: W,
impl<W: io::Write, F: Formatter> Serializer<W, F> {
    pub fn with_formatter(writer: W, fmt: F) -> Self {
        Self { writer, fmt }
    }
}

impl<W: Write> Serializer<W> {
impl<W: io::Write> Serializer<W> {
    pub fn new(writer: W) -> Self {
        Self { writer }
        Self::with_formatter(writer, CompactFormatter)
    }
}

impl<W: io::Write> Serializer<W, PrettyFormatter<'_>> {
    pub fn pretty(writer: W) -> Self {
        Self::with_formatter(writer, PrettyFormatter::default())
    }
}

impl<W: Write> ser::Serializer for &mut Serializer<W> {
#[derive(Eq, PartialEq)]
enum State {
    Empty,
    First,
    Rest,
}

pub struct Compound<'a, W: 'a, F: 'a> {
    ser: &'a mut Serializer<W, F>,
    state: State,
}

impl<'a, W: io::Write, F: Formatter> ser::Serializer for &'a mut Serializer<W, F> {
    type Ok = ();
    type Error = Error;

    type SerializeSeq = Self;
    type SerializeTuple = Self;
    type SerializeTupleStruct = Self;
    type SerializeTupleVariant = Self;
    type SerializeMap = Self;
    type SerializeStruct = Self;
    type SerializeStructVariant = Self;
    type SerializeSeq = Compound<'a, W, F>;
    type SerializeTuple = Compound<'a, W, F>;
    type SerializeTupleStruct = Compound<'a, W, F>;
    type SerializeTupleVariant = Compound<'a, W, F>;
    type SerializeMap = Compound<'a, W, F>;
    type SerializeStruct = Compound<'a, W, F>;
    type SerializeStructVariant = Compound<'a, W, F>;

    fn serialize_bool(self, v: bool) -> Result<()> {
        if v {
            Ok(self.writer.write_all(b"#t")?)
        } else {
            Ok(self.writer.write_all(b"#f")?)
        }
        self.fmt.write_bool(&mut self.writer, v).map_err(Error::io)
    }

    fn serialize_i8(self, v: i8) -> Result<()> {
        itoa::write(self.writer, v)?;
        Ok(())
        self.fmt.write_i8(&mut self.writer, v).map_err(Error::io)
    }

    fn serialize_i16(self, v: i16) -> Result<()> {
        itoa::write(self.writer, v)?;
        Ok(())
        self.fmt.write_i16(&mut self.writer, v).map_err(Error::io)
    }

    fn serialize_i32(self, v: i32) -> Result<()> {
        itoa::write(self.writer, v)?;
        Ok(())
        self.fmt.write_i32(&mut self.writer, v).map_err(Error::io)
    }

    fn serialize_i64(self, v: i64) -> Result<()> {
        itoa::write(self.writer, v)?;
        Ok(())
        self.fmt.write_i64(&mut self.writer, v).map_err(Error::io)
    }

    fn serialize_u8(self, v: u8) -> Result<()> {
        itoa::write(self.writer, v)?;
        Ok(())
        self.fmt.write_u8(&mut self.writer, v).map_err(Error::io)
    }

    fn serialize_u16(self, v: u16) -> Result<()> {
        itoa::write(self.writer, v)?;
        Ok(())
        self.fmt.write_u16(&mut self.writer, v).map_err(Error::io)
    }

    fn serialize_u32(self, v: u32) -> Result<()> {
        itoa::write(self.writer, v)?;
        Ok(())
        self.fmt.write_u32(&mut self.writer, v).map_err(Error::io)
    }

    fn serialize_u64(self, v: u64) -> Result<()> {
        itoa::write(self.writer, v)?;
        Ok(())
        self.fmt.write_u64(&mut self.writer, v).map_err(Error::io)
    }

    fn serialize_f32(
        self,
        _: f32,
    ) -> Result<()>
        todo!()
    fn serialize_f32(self, v: f32) -> Result<()> {
        self.fmt.write_f32(&mut self.writer, v).map_err(Error::io)
    }

    fn serialize_f64(
        self,
        _: f64,
    ) -> Result<()> {
        todo!()
    fn serialize_f64(self, v: f64) -> Result<()> {
        self.fmt.write_f64(&mut self.writer, v).map_err(Error::io)
    }

    fn serialize_char(
        self,
        _: char,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::Ok,
        <Self as serde::ser::Serializer>::Error,
    > {
        todo!()
    }
    fn serialize_str(
        self,
        _: &str,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::Ok,
        <Self as serde::ser::Serializer>::Error,
    > {
        todo!()
    }
    fn serialize_bytes(
        self,
        _: &[u8],
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::Ok,
        <Self as serde::ser::Serializer>::Error,
    > {
        todo!()
    }
    fn serialize_none(
        self,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::Ok,
        <Self as serde::ser::Serializer>::Error,
    > {
        todo!()
    fn serialize_char(self, c: char) -> Result<()> {
        let mut buf = [0; 4];
        let buf = c.encode_utf8(&mut buf);
        self.serialize_str(buf)
    }
    fn serialize_some<T>(
        self,
        _: &T,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::Ok,
        <Self as serde::ser::Serializer>::Error,
    >

    fn serialize_str(self, s: &str) -> Result<()> {
        self.fmt.begin_string(&mut self.writer)?;
        format_escaped_str_contents(&mut self.writer, &mut self.fmt, s)?;
        self.fmt.end_string(&mut self.writer).map_err(Error::io)
    }

    fn serialize_bytes(self, s: &[u8]) -> Result<()> {
        let mut seq = self.serialize_seq(Some(s.len()))?;
        for b in s {
            ser::SerializeSeq::serialize_element(&mut seq, b)?;
        }
        ser::SerializeSeq::end(seq)
    }

    fn serialize_none(self) -> Result<()> {
        self.serialize_unit()
    }

    fn serialize_some<T>(self, v: &T) -> Result<()>
    where
        T: serde::ser::Serialize,
        T: serde::ser::Serialize + ?Sized,
    {
        todo!()
        v.serialize(self)
    }
    fn serialize_unit(
        self,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::Ok,
        <Self as serde::ser::Serializer>::Error,
    > {
        todo!()

    fn serialize_unit(self) -> Result<()> {
        self.fmt.empty_list(&mut self.writer).map_err(Error::io)
    }
    fn serialize_unit_struct(
        self,
        _: &'static str,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::Ok,
        <Self as serde::ser::Serializer>::Error,
    > {
        todo!()

    fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
        self.serialize_unit()
    }
    fn serialize_unit_variant(
        self,
        _: &'static str,
        _: u32,
        _: &'static str,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::Ok,
        <Self as serde::ser::Serializer>::Error,
    > {
        todo!()

    fn serialize_unit_variant(self, _: &'static str, _: u32, name: &'static str) -> Result<()> {
        self.fmt
            .write_atom(&mut self.writer, name)
            .map_err(Error::io)
    }
    fn serialize_newtype_struct<T>(
        self,
        _: &'static str,
        _: &T,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::Ok,
        <Self as serde::ser::Serializer>::Error,
    >

    fn serialize_newtype_struct<T>(self, _: &'static str, v: &T) -> Result<()>
    where
        T: serde::ser::Serialize,
        T: serde::ser::Serialize + ?Sized,
    {
        todo!()
        v.serialize(self)
    }

    fn serialize_newtype_variant<T>(
        self,
        _: &'static str,
        _: u32,
        _: &'static str,
        _: &T,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::Ok,
        <Self as serde::ser::Serializer>::Error,
    >
        variant: &'static str,
        value: &T,
    ) -> Result<()>
    where
        T: serde::ser::Serialize,
        T: serde::ser::Serialize + ?Sized,
    {
        todo!()
        self.fmt.begin_list(&mut self.writer)?;
        self.fmt.write_atom(&mut self.writer, variant)?;
        self.writer.write_all(b" ")?;
        value.serialize(&mut *self)?;
        self.fmt.end_list(&mut self.writer).map_err(Error::io)
    }

    fn serialize_seq(self, len: std::option::Option<usize>) -> Result<Compound<'a, W, F>> {
        if len == Some(0) {
            self.fmt.empty_list(&mut self.writer)?;
            Ok(Compound {
                ser: &mut *self,
                state: State::Empty,
            })
        } else {
            self.fmt.begin_list(&mut self.writer)?;
            Ok(Compound {
                ser: &mut *self,
                state: State::First,
            })
        }
    }
    fn serialize_seq(
        self,
        _: std::option::Option<usize>,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::SerializeSeq,
        <Self as serde::ser::Serializer>::Error,
    > {
        todo!()
    }
    fn serialize_tuple(
        self,
        _: usize,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::SerializeTuple,
        <Self as serde::ser::Serializer>::Error,
    > {
        todo!()
    }
    fn serialize_tuple_struct(
        self,
        _: &'static str,
        _: usize,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::SerializeTupleStruct,
        <Self as serde::ser::Serializer>::Error,
    > {
        todo!()

    fn serialize_tuple(self, len: usize) -> Result<Compound<'a, W, F>> {
        self.serialize_seq(Some(len))
    }

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

    fn serialize_tuple_variant(
        self,
        _: &'static str,
        _: u32,
        _: &'static str,
        _: usize,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::SerializeTupleVariant,
        <Self as serde::ser::Serializer>::Error,
    > {
        todo!()
    }
    fn serialize_map(
        self,
        _: std::option::Option<usize>,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::SerializeMap,
        <Self as serde::ser::Serializer>::Error,
    > {
        todo!()
    }
    fn serialize_struct(
        self,
        _: &'static str,
        _: usize,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::SerializeStruct,
        <Self as serde::ser::Serializer>::Error,
    > {
        todo!()
        variant: &'static str,
        len: usize,
    ) -> Result<Compound<'a, W, F>> {
        let mut seq = self.serialize_seq(Some(len))?;
        seq.ser.fmt.write_atom(&mut seq.ser.writer, variant)?;
        seq.state = State::Rest;

        Ok(seq)
    }

    fn serialize_map(self, len: Option<usize>) -> Result<Compound<'a, W, F>> {
        if len == Some(0) {
            self.fmt.empty_list(&mut self.writer)?;
            Ok(Compound {
                ser: &mut *self,
                state: State::Empty,
            })
        } else {
            self.fmt.begin_list(&mut self.writer)?;
            Ok(Compound {
                ser: &mut *self,
                state: State::First,
            })
        }
    }

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

    fn serialize_struct_variant(
        self,
        _: &'static str,
        _: u32,
        _: &'static str,
        _: usize,
    ) -> std::result::Result<
        <Self as serde::ser::Serializer>::SerializeStructVariant,
        <Self as serde::ser::Serializer>::Error,
    > {
        todo!()
        variant: &'static str,
        len: usize,
    ) -> Result<Compound<'a, W, F>> {
        let mut seq = self.serialize_seq(Some(len))?;
        seq.ser.fmt.write_atom(&mut seq.ser.writer, variant)?;
        seq.state = State::Rest;

        Ok(seq)
    }
}

impl<W: Write> ser::SerializeSeq for &mut Serializer<W> {
impl<'a, W: io::Write, F: Formatter> ser::SerializeSeq for Compound<'a, W, F> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T>(&mut self, _: &T) -> Result<()>
    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
    where
        T: serde::ser::Serialize + ?Sized,
    {
        todo!()
        self.ser
            .fmt
            .begin_value(&mut self.ser.writer, self.state == State::First)?;
        self.state = State::Rest;
        value.serialize(&mut *self.ser)
    }

    fn end(self) -> Result<()> {
        todo!()
        if self.state == State::Empty {
            Ok(())
        } else {
            self.ser
                .fmt
                .end_list(&mut self.ser.writer)
                .map_err(Error::io)
        }
    }
}

impl<W: Write> ser::SerializeTuple for &mut Serializer<W> {
impl<'a, W: io::Write, F: Formatter> ser::SerializeTuple for Compound<'a, W, F> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T>(&mut self, _: &T) -> Result<()>
    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
    where
        T: serde::ser::Serialize + ?Sized,
    {
        todo!()
        self.ser
            .fmt
            .begin_value(&mut self.ser.writer, self.state == State::First)?;
        self.state = State::Rest;
        value.serialize(&mut *self.ser)
    }

    fn end(self) -> Result<()> {
        todo!()
        if self.state == State::Empty {
            Ok(())
        } else {
            self.ser
                .fmt
                .end_list(&mut self.ser.writer)
                .map_err(Error::io)
        }
    }
}

impl<W: Write> ser::SerializeTupleStruct for &mut Serializer<W> {
impl<'a, W: io::Write, F: Formatter> ser::SerializeTupleStruct for Compound<'a, W, F> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T>(&mut self, _: &T) -> Result<()>
    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
    where
        T: serde::ser::Serialize + ?Sized,
    {
        todo!()
        ser::SerializeSeq::serialize_element(self, value)
    }

    fn end(self) -> Result<()> {
        todo!()
        ser::SerializeSeq::end(self)
    }
}

impl<W: Write> ser::SerializeTupleVariant for &mut Serializer<W> {
impl<'a, W: io::Write, F: Formatter> ser::SerializeTupleVariant for Compound<'a, W, F> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T>(&mut self, _: &T) -> Result<()>
    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
    where
        T: serde::ser::Serialize + ?Sized,
    {
        todo!()
        self.ser.fmt.begin_value(&mut self.ser.writer, false)?;
        value.serialize(&mut *self.ser)
    }

    fn end(self) -> Result<()> {
        todo!()
        self.ser
            .fmt
            .end_list(&mut self.ser.writer)
            .map_err(Error::io)
    }
}

impl<W: Write> ser::SerializeMap for &mut Serializer<W> {
impl<'a, W: io::Write, F: Formatter> ser::SerializeMap for Compound<'a, W, F> {
    type Ok = ();
    type Error = Error;

    fn serialize_key<T>(&mut self, _: &T) -> Result<()>
    fn serialize_key<T>(&mut self, key: &T) -> Result<()>
    where
        T: serde::ser::Serialize + ?Sized,
    {
        todo!()
        self.ser
            .fmt
            .begin_value(&mut self.ser.writer, self.state == State::First)?;
        self.state = State::Rest;
        self.ser.fmt.begin_list(&mut self.ser.writer)?;
        key.serialize(&mut *self.ser)
    }

    fn serialize_value<T>(&mut self, _: &T) -> Result<()>
    fn serialize_value<T>(&mut self, value: &T) -> Result<()>
    where
        T: serde::ser::Serialize + ?Sized,
    {
        todo!()
        self.ser.fmt.begin_value(&mut self.ser.writer, false)?;
        value.serialize(&mut *self.ser)?;
        self.ser
            .fmt
            .end_list(&mut self.ser.writer)
            .map_err(Error::io)
    }

    fn end(self) -> Result<()> {
        todo!()
        self.ser
            .fmt
            .end_list(&mut self.ser.writer)
            .map_err(Error::io)
    }
}

impl<W: Write> ser::SerializeStruct for &mut Serializer<W> {
impl<'a, W: io::Write, F: Formatter> ser::SerializeStruct for Compound<'a, W, F> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T>(&mut self, _: &'static str, _: &T) -> Result<()>
    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
    where
        T: ser::Serialize + ?Sized,
    {
        todo!()
        self.ser
            .fmt
            .begin_value(&mut self.ser.writer, self.state == State::First)?;
        self.state = State::Rest;
        self.ser.fmt.begin_list(&mut self.ser.writer)?;
        self.ser.fmt.write_atom(&mut self.ser.writer, key)?;
        self.ser.fmt.begin_value(&mut self.ser.writer, false)?;
        value.serialize(&mut *self.ser)?;
        self.ser
            .fmt
            .end_list(&mut self.ser.writer)
            .map_err(Error::io)
    }

    fn end(self) -> Result<()> {
        todo!()
        ser::SerializeSeq::end(self)
    }
}

impl<W: Write> ser::SerializeStructVariant for &mut Serializer<W> {
impl<'a, W: io::Write, F: Formatter> ser::SerializeStructVariant for Compound<'a, W, F> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T>(&mut self, _: &'static str, _: &T) -> Result<()>
    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
    where
        T: ser::Serialize + ?Sized,
    {
        todo!()
        ser::SerializeStruct::serialize_field(self, key, value)
    }

    fn end(self) -> Result<()> {
        todo!()
        ser::SerializeSeq::end(self)
    }
}

pub struct CompactFormatter;

impl Formatter for CompactFormatter {
    #[inline]
    fn begin_value<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        if first {
            return Ok(());
        }

        writer.write_all(b" ")
    }

    #[inline]
    fn begin_list<W>(&mut self, writer: &mut W) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        writer.write_all(b"(")
    }

    #[inline]
    fn end_list<W>(&mut self, writer: &mut W) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        writer.write_all(b")")
    }
}

pub struct PrettyFormatter<'a> {
    current_indent: usize,
    indent: &'a [u8],
}

impl<'a> PrettyFormatter<'a> {
    pub fn new() -> Self {
        Self {
            current_indent: 0,
            indent: b" ",
        }
    }

    pub fn with_indent(indent: &'a [u8]) -> Self {
        Self {
            current_indent: 0,
            indent,
        }
    }
}

impl Default for PrettyFormatter<'_> {
    fn default() -> Self {
        Self::new()
    }
}

impl Formatter for PrettyFormatter<'_> {
    fn begin_value<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        if first {
            return Ok(());
        }

        writer.write_all(b"\n")?;
        for _ in 0..self.current_indent {
            writer.write_all(self.indent)?;
        }
        Ok(())
    }

    #[inline]
    fn begin_list<W>(&mut self, writer: &mut W) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        self.current_indent += 1;
        writer.write_all(b"(")
    }

    #[inline]
    fn end_list<W>(&mut self, writer: &mut W) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        self.current_indent -= 1;
        writer.write_all(b")")
    }
}

pub trait Formatter {
    fn begin_value<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
    where
        W: ?Sized + io::Write;
    fn begin_list<W>(&mut self, writer: &mut W) -> io::Result<()>
    where
        W: ?Sized + io::Write;
    fn end_list<W>(&mut self, writer: &mut W) -> io::Result<()>
    where
        W: ?Sized + io::Write;

    fn write<W>(&mut self, writer: &mut W, v: &[u8]) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        writer.write_all(v)
    }

    fn write_atom<W>(&mut self, writer: &mut W, v: &str) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        writer.write_all(v.as_ref())
    }

    fn write_bool<W>(&mut self, writer: &mut W, v: bool) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        let s = if v { b"#t" } else { b"#f" };
        writer.write_all(s)
    }

    #[inline]
    fn write_i8<W>(&mut self, writer: &mut W, value: i8) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        let mut buffer = itoa::Buffer::new();
        let s = buffer.format(value);
        writer.write_all(s.as_bytes())
    }

    #[inline]
    fn write_i16<W>(&mut self, writer: &mut W, value: i16) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        let mut buffer = itoa::Buffer::new();
        let s = buffer.format(value);
        writer.write_all(s.as_bytes())
    }

    #[inline]
    fn write_i32<W>(&mut self, writer: &mut W, value: i32) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        let mut buffer = itoa::Buffer::new();
        let s = buffer.format(value);
        writer.write_all(s.as_bytes())
    }

    #[inline]
    fn write_i64<W>(&mut self, writer: &mut W, value: i64) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        let mut buffer = itoa::Buffer::new();
        let s = buffer.format(value);
        writer.write_all(s.as_bytes())
    }

    #[inline]
    fn write_u8<W>(&mut self, writer: &mut W, value: u8) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        let mut buffer = itoa::Buffer::new();
        let s = buffer.format(value);
        writer.write_all(s.as_bytes())
    }

    #[inline]
    fn write_u16<W>(&mut self, writer: &mut W, value: u16) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        let mut buffer = itoa::Buffer::new();
        let s = buffer.format(value);
        writer.write_all(s.as_bytes())
    }

    #[inline]
    fn write_u32<W>(&mut self, writer: &mut W, value: u32) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        let mut buffer = itoa::Buffer::new();
        let s = buffer.format(value);
        writer.write_all(s.as_bytes())
    }

    #[inline]
    fn write_u64<W>(&mut self, writer: &mut W, value: u64) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        let mut buffer = itoa::Buffer::new();
        let s = buffer.format(value);
        writer.write_all(s.as_bytes())
    }

    #[inline]
    fn write_f32<W>(&mut self, writer: &mut W, value: f32) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        let mut buffer = ryu::Buffer::new();
        let s = buffer.format_finite(value);
        writer.write_all(s.as_bytes())
    }

    #[inline]
    fn write_f64<W>(&mut self, writer: &mut W, value: f64) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        let mut buffer = ryu::Buffer::new();
        let s = buffer.format_finite(value);
        writer.write_all(s.as_bytes())
    }

    #[inline]
    fn write_str_part<W>(&mut self, writer: &mut W, value: &str) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        writer.write_all(value.as_ref())
    }

    #[inline]
    fn empty_list<W>(&mut self, writer: &mut W) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        writer.write_all(b"()")
    }

    #[inline]
    fn begin_string<W>(&mut self, writer: &mut W) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        writer.write_all(b"\"")
    }

    #[inline]
    fn end_string<W>(&mut self, writer: &mut W) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        writer.write_all(b"\"")
    }

    fn space<W>(&mut self, writer: &mut W) -> io::Result<()>
    where
        W: ?Sized + io::Write,
    {
        writer.write_all(b" ")
    }
}

const UU: u8 = b'u';
const QU: u8 = b'q';
const BS: u8 = b'\\';
const __: u8 = 0;

static ESCAPE: [u8; 256] = [
    //   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, // 0
    UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, // 1
    __, __, QU, __, __, __, __, __, __, __, __, __, __, __, __, __, // 2
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 3
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 4
    __, __, __, __, __, __, __, __, __, __, __, __, BS, __, __, __, // 5
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 6
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 7
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 8
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 9
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // A
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // B
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // C
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // D
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // E
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F
];

fn format_escaped_str_contents<W, F>(
    writer: &mut W,
    formatter: &mut F,
    value: &str,
) -> io::Result<()>
where
    W: ?Sized + io::Write,
    F: ?Sized + Formatter,
{
    let bytes = value.as_bytes();
    let mut start = 0;

    for (i, &b) in bytes.iter().enumerate() {
        let esc = ESCAPE[b as usize];
        if esc == 0 {
            continue;
        }

        if start < i {
            formatter.write_str_part(writer, &value[start..i])?;
        }

        match esc {
            QU => writer.write_all(b"\\\"")?,
            BS => writer.write_all(br"\\")?,
            UU => {
                static HEX: [u8; 16] = *b"0123456789abcdef";
                let uesc = &[
                    b'\\',
                    b'u',
                    b'0',
                    b'0',
                    HEX[(b >> 4) as usize],
                    HEX[(b & 0xf) as usize],
                ];
                writer.write_all(uesc)?;
            }
            _ => unreachable!(),
        }

        start = i + 1;
    }

    if start != bytes.len() {
        formatter.write_str_part(writer, &value[start..])?;
    }

    Ok(())
}

pub fn to_writer<W, T>(writer: W, value: &T) -> Result<()>
where
    T: ser::Serialize + ?Sized,
    W: io::Write,
{
    let mut ser = Serializer::new(writer);
    value.serialize(&mut ser)
}

pub fn to_writer_pretty<W, T>(writer: W, value: &T) -> Result<()>
where
    T: ser::Serialize + ?Sized,
    W: io::Write,
{
    let mut ser = Serializer::pretty(writer);
    value.serialize(&mut ser)
}

pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
where
    T: ser::Serialize + ?Sized,
{
    let mut writer = Vec::with_capacity(128);
    to_writer(&mut writer, value)?;
    Ok(writer)
}

pub fn to_vec_pretty<T>(value: &T) -> Result<Vec<u8>>
where
    T: ser::Serialize + ?Sized,
{
    let mut writer = Vec::with_capacity(128);
    to_writer_pretty(&mut writer, value)?;
    Ok(writer)
}

pub fn to_string<T>(value: &T) -> Result<String>
where
    T: ser::Serialize + ?Sized,
{
    let vec = to_vec(value)?;
    Ok(unsafe { String::from_utf8_unchecked(vec) })
}

pub fn to_string_pretty<T>(value: &T) -> Result<String>
where
    T: ser::Serialize + ?Sized,
{
    let vec = to_vec_pretty(value)?;
    Ok(unsafe { String::from_utf8_unchecked(vec) })
}

#[cfg(test)]
mod test {
    use serde::Serialize;

    #[derive(Serialize)]
    enum Test {
        First,
        Second,
        Third(i32),
        Fourth(bool, u64),
        Fifth {
            name: String,
            list: Vec<u32>,
        }
    }

    #[test]
    fn tuple() {
        let a: (Test, bool, usize, f64, Test, &str) =
            (Test::Second, true, 42, 3.14159, Test::First, "it works!");
        let exp = "(Second #t 42 3.14159 First \"it works!\")";
        let res = super::to_string(&a).expect("serialization failed");
        assert_eq!(exp, res);
    }

    #[test]
    fn list() {
        let lst = &[
            Test::First,
            Test::Second,
            Test::Third(-5),
            Test::Fourth(false, std::u64::MAX),
        ];
        let res = super::to_string(&lst).expect("serialization failed");
        let exp = "(First Second (Third -5) (Fourth #f 18446744073709551615))";
        assert_eq!(exp, res);
    }

    #[test]
    fn list_pretty() {
        let lst = &[
            Test::First,
            Test::Second,
            Test::Third(-5),
            Test::Fourth(false, std::u64::MAX),
            Test::Fifth {
                name: String::from("me, myself, and I"),
                list: vec![1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233],
            }
        ];
        let res = super::to_string_pretty(&lst).expect("serialization failed");
        let exp = r#"(First
 Second
 (Third -5)
 (Fourth
  #f
  18446744073709551615)
 (Fifth
  (name
   "me, myself, and I")
  (list
   (1
    1
    2
    3
    5
    8
    13
    21
    34
    55
    89
    144
    233))))"#;
        assert_eq!(exp, res);
    }

    #[derive(Default, Serialize)]
    struct Struct {
        int: i32,
        float: f32,
        string: String,
        optional: Option<u32>,
        bytes: Vec<u8>,
    }

    #[test]
    fn test_struct() {
        let s = Struct {
            bytes: vec![0xCA, 0xFE, 0xBA, 0xBE, 0xDE, 0xAD, 0xBE, 0xEF],
            ..Default::default()
        };

        let res = super::to_string(&s).expect("serialization failed");
        let exp = "((int 0) (float 0.0) (string \"\") (optional ()) (bytes (202 254 186 190 222 173 190 239)))";
        assert_eq!(exp, res);
    }

    #[test]
    fn test_struct_pretty() {
        let s = Struct {
            bytes: vec![0xCA, 0xFE, 0xBA, 0xBE, 0xDE, 0xAD, 0xBE, 0xEF],
            optional: Some(69),
            string: String::from("\0\x01\n\t"),
            ..Default::default()
        };

        let res = super::to_string_pretty(&s).expect("serialization failed");
        let exp = r#"((int
  0)
 (float
  0.0)
 (string
  "\u0000\u0001\u000a\u0009")
 (optional
  69)
 (bytes
  (202
   254
   186
   190
   222
   173
   190
   239)))"#;
        assert_eq!(exp, res);
    }

    #[test]
    fn test_map() {
        use std::collections::BTreeMap;
        let mut s = BTreeMap::<i32, &str>::new();
        s.insert(10, "30");
        s.insert(-5, "foo");
        s.insert(std::i32::MIN, "minimum value");

        let res = super::to_string(&s).expect("serialization failed");
        let exp = format!(
            "(({} {:?}) ({} {:?}) ({} {:?}))",
            std::i32::MIN,
            "minimum value",
            -5,
            "foo",
            10,
            "30"
        );
        assert_eq!(exp, res);
    }
}