1
Fork 0

Implement generic writer target

Implements `to_writer` and `to_vec` functions.
This commit is contained in:
Lucas Schwiderski 2024-03-21 10:03:15 +01:00
parent 73d2b23ce5
commit 5ec97dab43
Signed by: lucas
GPG key ID: AA12679AAA6DF4D8
5 changed files with 176 additions and 131 deletions

View file

@ -8,6 +8,8 @@
=== Added === Added
- implement serializing into generic `io::Write`
=== Fixed === Fixed
- fix parsing CRLF - fix parsing CRLF

View file

@ -1,4 +1,4 @@
use std::fmt; use std::{fmt, io};
use crate::parser::Token; use crate::parser::Token;
@ -38,6 +38,7 @@ pub(crate) enum ErrorCode {
ExpectedTopLevelObject, ExpectedTopLevelObject,
ExpectedValue, ExpectedValue,
TrailingCharacters, TrailingCharacters,
NonFiniteFloat,
} }
impl fmt::Display for ErrorCode { impl fmt::Display for ErrorCode {
@ -64,6 +65,7 @@ impl fmt::Display for ErrorCode {
ErrorCode::ExpectedTopLevelObject => f.write_str("expected object at the top level"), ErrorCode::ExpectedTopLevelObject => f.write_str("expected object at the top level"),
ErrorCode::ExpectedValue => f.write_str("expected a value"), ErrorCode::ExpectedValue => f.write_str("expected a value"),
ErrorCode::TrailingCharacters => f.write_str("unexpected trailing characters"), ErrorCode::TrailingCharacters => f.write_str("unexpected trailing characters"),
ErrorCode::NonFiniteFloat => f.write_str("got infinite floating point number"),
} }
} }
} }
@ -166,3 +168,9 @@ impl Error {
} }
} }
} }
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
Self::new(ErrorCode::Message(format!("{}", err)), 0, 0, None)
}
}

View file

@ -5,4 +5,4 @@ mod ser;
pub use de::{from_str, Deserializer}; pub use de::{from_str, Deserializer};
pub use error::{Error, Result}; pub use error::{Error, Result};
pub use ser::{to_string, Serializer}; pub use ser::{to_string, to_vec, to_writer, Serializer};

View file

@ -1,36 +1,75 @@
use std::io;
use serde::Serialize; use serde::Serialize;
use crate::error::{Error, ErrorCode, Result}; use crate::error::{Error, ErrorCode, Result};
// TODO: Make configurable // TODO: Make configurable
const INDENT: &str = " "; const INDENT: [u8; 2] = [0x20, 0x20];
pub struct Serializer { pub struct Serializer<W> {
// The current indentation level // The current indentation level
level: usize, level: usize,
// The output string writer: W,
output: String,
} }
#[inline]
pub fn to_writer<T, W>(writer: &mut W, value: &T) -> Result<()>
where
W: io::Write,
T: Serialize,
{
let mut serializer = Serializer::new(writer);
value.serialize(&mut serializer)
}
#[inline]
pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
where
T: Serialize,
{
let mut vec = Vec::with_capacity(128);
to_writer(&mut vec, value)?;
Ok(vec)
}
#[inline]
pub fn to_string<T>(value: &T) -> Result<String> pub fn to_string<T>(value: &T) -> Result<String>
where where
T: Serialize, T: Serialize,
{ {
let mut serializer = Serializer { let vec = to_vec(value)?;
level: 0, let string = if cfg!(debug_assertions) {
output: String::new(), String::from_utf8(vec).expect("We do not emit invalid UTF-8")
} else {
unsafe { String::from_utf8_unchecked(vec) }
}; };
value.serialize(&mut serializer)?; Ok(string)
Ok(serializer.output)
} }
impl Serializer { impl<W> Serializer<W>
fn add_indent(&mut self) { where
W: io::Write,
{
pub fn new(writer: W) -> Self {
Self { level: 0, writer }
}
#[inline]
fn write(&mut self, bytes: impl AsRef<[u8]>) -> Result<()> {
self.writer.write_all(bytes.as_ref()).map_err(Error::from)
}
#[inline]
fn add_indent(&mut self) -> Result<()> {
for _ in 0..self.level.saturating_sub(1) { for _ in 0..self.level.saturating_sub(1) {
self.output += INDENT; self.write(INDENT)?;
}
} }
Ok(())
}
#[inline]
fn ensure_top_level_struct(&self) -> Result<()> { fn ensure_top_level_struct(&self) -> Result<()> {
if self.level == 0 { if self.level == 0 {
return Err(Error::new(ErrorCode::ExpectedTopLevelObject, 0, 0, None)); return Err(Error::new(ErrorCode::ExpectedTopLevelObject, 0, 0, None));
@ -40,7 +79,10 @@ impl Serializer {
} }
} }
impl<'a> serde::ser::Serializer for &'a mut Serializer { impl<'a, W> serde::ser::Serializer for &'a mut Serializer<W>
where
W: io::Write,
{
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
@ -54,7 +96,7 @@ impl<'a> serde::ser::Serializer for &'a mut Serializer {
fn serialize_bool(self, v: bool) -> Result<Self::Ok> { fn serialize_bool(self, v: bool) -> Result<Self::Ok> {
self.ensure_top_level_struct()?; self.ensure_top_level_struct()?;
self.output += if v { "true" } else { "false" }; self.write(if v { "true" } else { "false" })?;
Ok(()) Ok(())
} }
@ -72,8 +114,7 @@ impl<'a> serde::ser::Serializer for &'a mut Serializer {
fn serialize_i64(self, v: i64) -> Result<Self::Ok> { fn serialize_i64(self, v: i64) -> Result<Self::Ok> {
self.ensure_top_level_struct()?; self.ensure_top_level_struct()?;
self.output += &v.to_string(); self.serialize_str(&format!("{}", v))
Ok(())
} }
fn serialize_u8(self, v: u8) -> Result<Self::Ok> { fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
@ -90,33 +131,25 @@ impl<'a> serde::ser::Serializer for &'a mut Serializer {
fn serialize_u64(self, v: u64) -> Result<Self::Ok> { fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
self.ensure_top_level_struct()?; self.ensure_top_level_struct()?;
self.output += &v.to_string(); self.serialize_str(&format!("{}", v))
Ok(())
} }
fn serialize_f32(self, v: f32) -> Result<Self::Ok> { fn serialize_f32(self, v: f32) -> Result<Self::Ok> {
if v.is_finite() {
self.serialize_f64(v.into()) self.serialize_f64(v.into())
} else {
self.ensure_top_level_struct()?;
self.output += "null";
Ok(())
}
} }
fn serialize_f64(self, v: f64) -> Result<Self::Ok> { fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
self.ensure_top_level_struct()?; self.ensure_top_level_struct()?;
if v.is_finite() { if !v.is_finite() {
self.output += &v.to_string(); return Err(Error::new(ErrorCode::NonFiniteFloat, 0, 0, None));
} else {
self.output += "null";
} }
Ok(())
self.serialize_str(&format!("{}", v))
} }
fn serialize_char(self, v: char) -> Result<Self::Ok> { fn serialize_char(self, v: char) -> Result<Self::Ok> {
let mut buf = [0; 4]; let mut buf = [0; 4];
self.serialize_str(v.encode_utf8(&mut buf)) self.serialize_bytes(v.encode_utf8(&mut buf).as_bytes())
} }
fn serialize_str(self, v: &str) -> Result<Self::Ok> { fn serialize_str(self, v: &str) -> Result<Self::Ok> {
@ -126,45 +159,52 @@ impl<'a> serde::ser::Serializer for &'a mut Serializer {
v.is_empty() || v.contains([' ', '\n', '\r', '\t', '=', '\'', '"', '\\', ':']); v.is_empty() || v.contains([' ', '\n', '\r', '\t', '=', '\'', '"', '\\', ':']);
if needs_quotes { if needs_quotes {
self.output += "\""; self.write(b"\"")?;
// Since we've added a layer of quotes, we now need to escape
// certain characters.
for c in v.chars() { for c in v.chars() {
match c { match c {
'\t' => { '\t' => {
self.output.push('\\'); self.write(b"\\")?;
self.output.push('t'); self.write(b"t")?;
} }
'\n' => { '\n' => {
self.output.push('\\'); self.write(b"\\")?;
self.output.push('n'); self.write(b"n")?;
} }
'\r' => { '\r' => {
self.output.push('\\'); self.write(b"\\")?;
self.output.push('r'); self.write(b"r")?;
} }
'"' => { '"' => {
self.output.push('\\'); self.write(b"\\")?;
self.output.push('"'); self.write(b"\"")?;
} }
'\\' => { '\\' => {
self.output.push('\\'); self.write(b"\\")?;
self.output.push('\\'); self.write(b"\\")?;
} }
c => { c => {
self.output.push(c); self.serialize_char(c)?;
} }
}; };
} }
self.output += "\""; self.write(b"\"")?;
} else { } else {
self.output += v; self.write(v.as_bytes())?;
} }
Ok(()) Ok(())
} }
fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok> { fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok> {
todo!() self.ensure_top_level_struct()?;
// For now we assume that the byte array contains
// valid SJSON.
// TODO: Turn this into an actual array of encoded bytes.
self.write(v)
} }
fn serialize_none(self) -> Result<Self::Ok> { fn serialize_none(self) -> Result<Self::Ok> {
@ -184,8 +224,7 @@ impl<'a> serde::ser::Serializer for &'a mut Serializer {
fn serialize_unit(self) -> Result<Self::Ok> { fn serialize_unit(self) -> Result<Self::Ok> {
self.ensure_top_level_struct()?; self.ensure_top_level_struct()?;
self.output += "null"; self.write(b"null")
Ok(())
} }
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok> { fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok> {
@ -223,19 +262,18 @@ impl<'a> serde::ser::Serializer for &'a mut Serializer {
{ {
self.ensure_top_level_struct()?; self.ensure_top_level_struct()?;
self.output += "{ "; self.write(b"{ ")?;
variant.serialize(&mut *self)?; variant.serialize(&mut *self)?;
self.output += " = "; self.write(b" = ")?;
value.serialize(&mut *self)?; value.serialize(&mut *self)?;
self.output += " }\n"; self.write(b" }")
Ok(())
} }
// Serialize the start of a sequence. // Serialize the start of a sequence.
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> { fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
self.ensure_top_level_struct()?; self.ensure_top_level_struct()?;
self.output += "[\n"; self.write(b"[\n")?;
self.level += 1; self.level += 1;
Ok(self) Ok(self)
} }
@ -266,7 +304,7 @@ impl<'a> serde::ser::Serializer for &'a mut Serializer {
variant.serialize(&mut *self)?; variant.serialize(&mut *self)?;
self.output += " = [\n"; self.write(b" = [\n")?;
self.level += 1; self.level += 1;
Ok(self) Ok(self)
@ -274,7 +312,7 @@ impl<'a> serde::ser::Serializer for &'a mut Serializer {
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> { fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
if self.level > 0 { if self.level > 0 {
self.output += "{\n"; self.write(b"{\n")?;
} }
self.level += 1; self.level += 1;
Ok(self) Ok(self)
@ -296,7 +334,7 @@ impl<'a> serde::ser::Serializer for &'a mut Serializer {
variant.serialize(&mut *self)?; variant.serialize(&mut *self)?;
self.output += " = {\n"; self.write(b" = {\n")?;
self.level += 1; self.level += 1;
Ok(self) Ok(self)
@ -310,7 +348,10 @@ impl<'a> serde::ser::Serializer for &'a mut Serializer {
} }
} }
impl<'a> serde::ser::SerializeSeq for &'a mut Serializer { impl<'a, W> serde::ser::SerializeSeq for &'a mut Serializer<W>
where
W: io::Write,
{
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
@ -318,23 +359,22 @@ impl<'a> serde::ser::SerializeSeq for &'a mut Serializer {
where where
T: Serialize, T: Serialize,
{ {
self.add_indent(); self.add_indent()?;
value.serialize(&mut **self)?; value.serialize(&mut **self)?;
if !self.output.ends_with('\n') { self.write(b"\n")
self.output += "\n";
}
Ok(())
} }
fn end(self) -> Result<Self::Ok> { fn end(self) -> Result<Self::Ok> {
self.level -= 1; self.level -= 1;
self.add_indent(); self.add_indent()?;
self.output += "]\n"; self.write(b"]")
Ok(())
} }
} }
impl<'a> serde::ser::SerializeTuple for &'a mut Serializer { impl<'a, W> serde::ser::SerializeTuple for &'a mut Serializer<W>
where
W: io::Write,
{
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
@ -342,23 +382,22 @@ impl<'a> serde::ser::SerializeTuple for &'a mut Serializer {
where where
T: Serialize, T: Serialize,
{ {
self.add_indent(); self.add_indent()?;
value.serialize(&mut **self)?; value.serialize(&mut **self)?;
if !self.output.ends_with('\n') { self.write(b"\n")
self.output += "\n";
}
Ok(())
} }
fn end(self) -> Result<Self::Ok> { fn end(self) -> Result<Self::Ok> {
self.level -= 1; self.level -= 1;
self.add_indent(); self.add_indent()?;
self.output += "]\n"; self.write(b"]")
Ok(())
} }
} }
impl<'a> serde::ser::SerializeTupleStruct for &'a mut Serializer { impl<'a, W> serde::ser::SerializeTupleStruct for &'a mut Serializer<W>
where
W: io::Write,
{
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
@ -366,23 +405,22 @@ impl<'a> serde::ser::SerializeTupleStruct for &'a mut Serializer {
where where
T: Serialize, T: Serialize,
{ {
self.add_indent(); self.add_indent()?;
value.serialize(&mut **self)?; value.serialize(&mut **self)?;
if !self.output.ends_with('\n') { self.write(b"\n")
self.output += "\n";
}
Ok(())
} }
fn end(self) -> Result<Self::Ok> { fn end(self) -> Result<Self::Ok> {
self.level -= 1; self.level -= 1;
self.add_indent(); self.add_indent()?;
self.output += "]\n"; self.write(b"]")
Ok(())
} }
} }
impl<'a> serde::ser::SerializeTupleVariant for &'a mut Serializer { impl<'a, W> serde::ser::SerializeTupleVariant for &'a mut Serializer<W>
where
W: io::Write,
{
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
@ -390,28 +428,31 @@ impl<'a> serde::ser::SerializeTupleVariant for &'a mut Serializer {
where where
T: Serialize, T: Serialize,
{ {
self.add_indent(); self.add_indent()?;
value.serialize(&mut **self)?; value.serialize(&mut **self)?;
if !self.output.ends_with('\n') { self.write(b"\n")
self.output += "\n";
}
Ok(())
} }
fn end(self) -> Result<Self::Ok> { fn end(self) -> Result<Self::Ok> {
self.level -= 1; self.level -= 1;
self.add_indent(); self.add_indent()?;
self.output += "]\n"; self.write(b"]\n")?;
self.level -= 1; self.level -= 1;
if self.level > 0 { if self.level > 0 {
self.add_indent(); self.add_indent()?;
self.output += "}\n"; self.write(b"}")?;
} }
Ok(()) Ok(())
} }
} }
impl<'a> serde::ser::SerializeMap for &'a mut Serializer { impl<'a, W> serde::ser::SerializeMap for &'a mut Serializer<W>
where
W: io::Write,
{
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
@ -419,7 +460,7 @@ impl<'a> serde::ser::SerializeMap for &'a mut Serializer {
where where
T: Serialize, T: Serialize,
{ {
self.add_indent(); self.add_indent()?;
key.serialize(&mut **self) key.serialize(&mut **self)
} }
@ -430,25 +471,25 @@ impl<'a> serde::ser::SerializeMap for &'a mut Serializer {
// It doesn't make a difference where the `=` is added. But doing it here // It doesn't make a difference where the `=` is added. But doing it here
// means `serialize_key` is only a call to a different function, which should // means `serialize_key` is only a call to a different function, which should
// have greater optimization potential for the compiler. // have greater optimization potential for the compiler.
self.output += " = "; self.write(b" = ")?;
value.serialize(&mut **self)?; value.serialize(&mut **self)?;
if !self.output.ends_with('\n') { self.write(b"\n")
self.output += "\n";
}
Ok(())
} }
fn end(self) -> Result<Self::Ok> { fn end(self) -> Result<Self::Ok> {
if self.level > 1 { if self.level > 1 {
self.level -= 1; self.level -= 1;
self.add_indent(); self.add_indent()?;
self.output += "}\n"; self.write(b"}")?;
} }
Ok(()) Ok(())
} }
} }
impl<'a> serde::ser::SerializeStruct for &'a mut Serializer { impl<'a, W> serde::ser::SerializeStruct for &'a mut Serializer<W>
where
W: io::Write,
{
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
@ -456,29 +497,29 @@ impl<'a> serde::ser::SerializeStruct for &'a mut Serializer {
where where
T: Serialize, T: Serialize,
{ {
self.add_indent(); self.add_indent()?;
key.serialize(&mut **self)?; key.serialize(&mut **self)?;
self.output += " = "; self.write(b" = ")?;
value.serialize(&mut **self)?; value.serialize(&mut **self)?;
if !self.output.ends_with('\n') { self.write(b"\n")
self.output += "\n";
}
Ok(())
} }
fn end(self) -> Result<Self::Ok> { fn end(self) -> Result<Self::Ok> {
if self.level > 1 { if self.level > 1 {
self.level -= 1; self.level -= 1;
self.add_indent(); self.add_indent()?;
self.output += "}\n"; self.write(b"}")?;
} }
Ok(()) Ok(())
} }
} }
impl<'a> serde::ser::SerializeStructVariant for &'a mut Serializer { impl<'a, W> serde::ser::SerializeStructVariant for &'a mut Serializer<W>
where
W: std::io::Write,
{
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
@ -486,21 +527,18 @@ impl<'a> serde::ser::SerializeStructVariant for &'a mut Serializer {
where where
T: Serialize, T: Serialize,
{ {
self.add_indent(); self.add_indent()?;
key.serialize(&mut **self)?; key.serialize(&mut **self)?;
self.output += " = "; self.write(b" = ")?;
value.serialize(&mut **self)?; value.serialize(&mut **self)?;
if !self.output.ends_with('\n') { self.write(b"\n")
self.output += "\n";
}
Ok(())
} }
fn end(self) -> Result<Self::Ok> { fn end(self) -> Result<Self::Ok> {
if self.level > 0 { if self.level > 0 {
self.level -= 1; self.level -= 1;
self.add_indent(); self.add_indent()?;
self.output += "}\n"; self.write(b"}")?;
} }
Ok(()) Ok(())
} }

View file

@ -1,4 +1,4 @@
use serde_sjson::to_string; use serde_sjson::{to_string, Error};
#[test] #[test]
fn serialize_null() { fn serialize_null() {
@ -81,17 +81,14 @@ fn serialize_non_representable_floats() {
} }
let tests = [std::f64::NAN, std::f64::INFINITY, std::f64::NEG_INFINITY]; let tests = [std::f64::NAN, std::f64::INFINITY, std::f64::NEG_INFINITY];
let expected = String::from("value = null\n");
for value in tests { for value in tests {
let value = Value64 { value }; let value = Value64 { value };
let actual = to_string(&value).unwrap(); assert!(to_string(&value).is_err());
assert_eq!(actual, expected);
} }
let tests = [std::f32::NAN, std::f32::INFINITY, std::f32::NEG_INFINITY]; let tests = [std::f32::NAN, std::f32::INFINITY, std::f32::NEG_INFINITY];
for value in tests { for value in tests {
let value = Value32 { value }; let value = Value32 { value };
let actual = to_string(&value).unwrap(); assert!(to_string(&value).is_err());
assert_eq!(actual, expected);
} }
} }