diff --git a/core/json/ser.rs b/core/json/ser.rs index 3d5646584..c80b976f4 100644 --- a/core/json/ser.rs +++ b/core/json/ser.rs @@ -1,116 +1,144 @@ use serde::ser::{self, Serialize}; -use std::{f32, f64, num::FpCategory}; +use std::{f32, f64, io, num::FpCategory}; use crate::json::error::{Error, Result}; +#[derive(Eq, PartialEq)] +pub enum State { + Empty, + First, + Rest, +} + +struct Map<'a, W: 'a, F: 'a> { + ser: &'a mut Serializer, + state: State, +} + /// Attempts to serialize the input as a JSON5 string (actually a JSON string). pub fn to_string(value: &T) -> Result where T: Serialize, { - let mut serializer = Serializer { - output: String::new(), - }; - value.serialize(&mut serializer)?; - Ok(serializer.output) + let vec = to_vec(value)?; + let string = String::from_utf8(vec).map_err(|err| Error::from(err.utf8_error()))?; + Ok(string) } -struct Serializer { - output: String, - // TODO settings for formatting (single vs double quotes, whitespace etc) +struct Serializer { + writer: W, + formatter: F, // TODO settings for formatting (single vs double quotes, whitespace etc) } -impl Serializer { - fn call_to_string(&mut self, v: &T) -> Result<()> - where - T: ToString, - { - self.output += &v.to_string(); - Ok(()) +impl Serializer +where + W: io::Write, +{ + pub fn new(writer: W) -> Self { + Serializer::with_formatter(writer, CompactFormatter) } } -impl ser::Serializer for &mut Serializer { +impl Serializer +where + W: io::Write, + F: Formatter, +{ + /// Creates a new JSON visitor whose output will be written to the writer + /// specified. + pub fn with_formatter(writer: W, formatter: F) -> Self { + Serializer { writer, formatter } + } +} + +impl<'a, W, F> ser::Serializer for &'a mut Serializer +where + W: io::Write, + F: Formatter, +{ 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 = Map<'a, W, F>; + type SerializeTuple = Map<'a, W, F>; + type SerializeTupleStruct = Map<'a, W, F>; + type SerializeTupleVariant = Map<'a, W, F>; + type SerializeMap = Map<'a, W, F>; + type SerializeStruct = Map<'a, W, F>; + type SerializeStructVariant = Map<'a, W, F>; fn serialize_bool(self, v: bool) -> Result<()> { - self.call_to_string(&v) + self.formatter + .write_bool(&mut self.writer, v) + .map_err(Error::from) } fn serialize_i8(self, v: i8) -> Result<()> { - self.call_to_string(&v) + self.formatter + .write_i8(&mut self.writer, v) + .map_err(Error::from) + // self.call_to_string(&v) } fn serialize_i16(self, v: i16) -> Result<()> { - self.call_to_string(&v) + self.formatter + .write_i16(&mut self.writer, v) + .map_err(Error::from) + // self.call_to_string(&v) } fn serialize_i32(self, v: i32) -> Result<()> { - self.call_to_string(&v) + self.formatter + .write_i32(&mut self.writer, v) + .map_err(Error::from) + // self.call_to_string(&v) } fn serialize_i64(self, v: i64) -> Result<()> { - self.call_to_string(&v) + self.formatter + .write_i64(&mut self.writer, v) + .map_err(Error::from) + // self.call_to_string(&v) } fn serialize_u8(self, v: u8) -> Result<()> { - self.call_to_string(&v) + self.formatter + .write_u8(&mut self.writer, v) + .map_err(Error::from) + // self.call_to_string(&v) } fn serialize_u16(self, v: u16) -> Result<()> { - self.call_to_string(&v) + self.formatter + .write_u16(&mut self.writer, v) + .map_err(Error::from) + // self.call_to_string(&v) } fn serialize_u32(self, v: u32) -> Result<()> { - self.call_to_string(&v) + self.formatter + .write_u32(&mut self.writer, v) + .map_err(Error::from) + // self.call_to_string(&v) } fn serialize_u64(self, v: u64) -> Result<()> { - self.call_to_string(&v) + self.formatter + .write_u64(&mut self.writer, v) + .map_err(Error::from) + // self.call_to_string(&v) } fn serialize_f32(self, v: f32) -> Result<()> { - match v.classify() { - FpCategory::Nan => self.output += "null", - FpCategory::Infinite => { - let infinity = if v.is_sign_negative() { - "-9e999" - } else { - "9e999" - }; - self.output += infinity - } - _ => self.output += &v.to_string(), - } - Ok(()) + self.formatter + .write_f32(&mut self.writer, v) + .map_err(Error::from) } fn serialize_f64(self, v: f64) -> Result<()> { - match v.classify() { - FpCategory::Nan => self.output += "null", - FpCategory::Infinite => { - let infinity = if v.is_sign_negative() { - "-9e999" - } else { - "9e999" - }; - self.output += infinity - } - _ => { - let str = &format!("{:.1}", v); - self.output += str - } - } - Ok(()) + self.formatter + .write_f64(&mut self.writer, v) + .map_err(Error::from) } fn serialize_char(self, v: char) -> Result<()> { @@ -120,10 +148,10 @@ impl ser::Serializer for &mut Serializer { } fn serialize_str(self, v: &str) -> Result<()> { - self.output += "\""; - self.output += &escape(v); - self.output += "\""; - Ok(()) + // self.output += "\""; + // self.output += &escape(v); + // self.output += "\""; + format_escaped_str(&mut self.writer, &mut self.formatter, v).map_err(Error::from) } fn serialize_bytes(self, _v: &[u8]) -> Result<()> { @@ -142,8 +170,9 @@ impl ser::Serializer for &mut Serializer { } fn serialize_unit(self) -> Result<()> { - self.output += "null"; - Ok(()) + self.formatter + .write_null(&mut self.writer) + .map_err(Error::from) } fn serialize_unit_struct(self, _name: &'static str) -> Result<()> { @@ -176,17 +205,47 @@ impl ser::Serializer for &mut Serializer { where T: ?Sized + Serialize, { - self.output += "{"; - variant.serialize(&mut *self)?; // TODO drop the quotes where possible - self.output += ":"; + self.formatter + .begin_object(&mut self.writer) + .map_err(Error::from)?; + self.formatter + .begin_object_key(&mut self.writer, true) + .map_err(Error::from)?; + self.serialize_str(variant)?; + self.formatter + .end_object_key(&mut self.writer) + .map_err(Error::from)?; + self.formatter + .begin_object_value(&mut self.writer) + .map_err(Error::from)?; value.serialize(&mut *self)?; - self.output += "}"; - Ok(()) + self.formatter + .end_object_value(&mut self.writer) + .map_err(Error::from)?; + self.formatter + .end_object(&mut self.writer) + .map_err(Error::from) } - fn serialize_seq(self, _len: Option) -> Result { - self.output += "["; - Ok(self) + fn serialize_seq(self, len: Option) -> Result { + self.formatter + .begin_array(&mut self.writer) + .map_err(Error::from)?; + + if len == Some(0) { + self.formatter + .end_array(&mut self.writer) + .map_err(Error::from)?; + Ok(Map { + ser: self, + state: State::Empty, + }) + } else { + Ok(Map { + ser: self, + state: State::First, + }) + } } fn serialize_tuple(self, len: usize) -> Result { @@ -206,17 +265,34 @@ impl ser::Serializer for &mut Serializer { _name: &'static str, _variant_index: u32, variant: &'static str, - _len: usize, + len: usize, ) -> Result { - self.output += "{"; - variant.serialize(&mut *self)?; - self.output += ":["; - Ok(self) + self.formatter.begin_object(&mut self.writer)?; + self.formatter.begin_object_key(&mut self.writer, true)?; + self.serialize_str(variant)?; + self.formatter.end_object_key(&mut self.writer)?; + self.formatter.begin_object_value(&mut self.writer)?; + self.serialize_seq(Some(len)) } - fn serialize_map(self, _len: Option) -> Result { - self.output += "{"; - Ok(self) + fn serialize_map(self, len: Option) -> Result { + self.formatter + .begin_object(&mut self.writer) + .map_err(Error::from)?; + if len == Some(0) { + self.formatter + .end_object(&mut self.writer) + .map_err(Error::from)?; + Ok(Map { + ser: self, + state: State::Empty, + }) + } else { + Ok(Map { + ser: self, + state: State::First, + }) + } } fn serialize_struct(self, _name: &'static str, len: usize) -> Result { @@ -228,16 +304,30 @@ impl ser::Serializer for &mut Serializer { _name: &'static str, _variant_index: u32, variant: &'static str, - _len: usize, + len: usize, ) -> Result { - self.output += "{"; - variant.serialize(&mut *self)?; - self.output += ":{"; - Ok(self) + self.formatter + .begin_object(&mut self.writer) + .map_err(Error::from)?; + self.formatter + .begin_object_key(&mut self.writer, true) + .map_err(Error::from)?; + self.serialize_str(variant).map_err(Error::from)?; + self.formatter + .end_object_key(&mut self.writer) + .map_err(Error::from)?; + self.formatter + .begin_object_value(&mut self.writer) + .map_err(Error::from)?; + self.serialize_map(Some(len)) } } -impl ser::SerializeSeq for &mut Serializer { +impl<'a, W, F> ser::SerializeSeq for Map<'a, W, F> +where + W: io::Write, + F: Formatter, +{ type Ok = (); type Error = Error; @@ -245,19 +335,36 @@ impl ser::SerializeSeq for &mut Serializer { where T: ?Sized + Serialize, { - if !self.output.ends_with('[') { - self.output += ","; + self.ser + .formatter + .begin_array_value(&mut self.ser.writer, self.state == State::First) + .map_err(Error::from)?; + + self.state = State::Rest; + value.serialize(&mut *self.ser).map_err(Error::from)?; + self.ser + .formatter + .end_array_value(&mut self.ser.writer) + .map_err(Error::from) + } + + fn end(self) -> Result<()> { + match self.state { + State::Empty => Ok(()), + _ => self + .ser + .formatter + .end_array(&mut self.ser.writer) + .map_err(Error::from), } - value.serialize(&mut **self) - } - - fn end(self) -> Result<()> { - self.output += "]"; - Ok(()) } } -impl ser::SerializeTuple for &mut Serializer { +impl<'a, W, F> ser::SerializeTuple for Map<'a, W, F> +where + W: io::Write, + F: Formatter, +{ type Ok = (); type Error = Error; @@ -273,7 +380,11 @@ impl ser::SerializeTuple for &mut Serializer { } } -impl ser::SerializeTupleStruct for &mut Serializer { +impl<'a, W, F> ser::SerializeTupleStruct for Map<'a, W, F> +where + W: io::Write, + F: Formatter, +{ type Ok = (); type Error = Error; @@ -289,7 +400,11 @@ impl ser::SerializeTupleStruct for &mut Serializer { } } -impl ser::SerializeTupleVariant for &mut Serializer { +impl<'a, W, F> ser::SerializeTupleVariant for Map<'a, W, F> +where + W: io::Write, + F: Formatter, +{ type Ok = (); type Error = Error; @@ -301,12 +416,30 @@ impl ser::SerializeTupleVariant for &mut Serializer { } fn end(self) -> Result<()> { - self.output += "]}"; - Ok(()) + match self.state { + State::Empty => {} + _ => self + .ser + .formatter + .end_array(&mut self.ser.writer) + .map_err(Error::from)?, + }; + self.ser + .formatter + .end_object_value(&mut self.ser.writer) + .map_err(Error::from)?; + self.ser + .formatter + .end_object(&mut self.ser.writer) + .map_err(Error::from) } } -impl ser::SerializeMap for &mut Serializer { +impl<'a, W, F> ser::SerializeMap for Map<'a, W, F> +where + W: io::Write, + F: Formatter, +{ type Ok = (); type Error = Error; @@ -314,27 +447,54 @@ impl ser::SerializeMap for &mut Serializer { where T: ?Sized + Serialize, { - if !self.output.ends_with('{') { - self.output += ","; - } - key.serialize(&mut **self) + self.ser + .formatter + .begin_object_key(&mut self.ser.writer, self.state == State::First) + .map_err(Error::from)?; + self.state = State::Rest; + + key.serialize(&mut *self.ser)?; + + self.ser + .formatter + .end_object_key(&mut self.ser.writer) + .map_err(Error::from) } fn serialize_value(&mut self, value: &T) -> Result<()> where T: ?Sized + Serialize, { - self.output += ":"; - value.serialize(&mut **self) + self.ser + .formatter + .begin_object_value(&mut self.ser.writer) + .map_err(Error::from)?; + + value.serialize(&mut *self.ser)?; + + self.ser + .formatter + .end_object_value(&mut self.ser.writer) + .map_err(Error::from) } fn end(self) -> Result<()> { - self.output += "}"; - Ok(()) + match self.state { + State::Empty => Ok(()), + _ => self + .ser + .formatter + .end_object(&mut self.ser.writer) + .map_err(Error::from), + } } } -impl ser::SerializeStruct for &mut Serializer { +impl<'a, W, F> ser::SerializeStruct for Map<'a, W, F> +where + W: io::Write, + F: Formatter, +{ type Ok = (); type Error = Error; @@ -342,6 +502,7 @@ impl ser::SerializeStruct for &mut Serializer { where T: ?Sized + Serialize, { + // TODO see here later ser::SerializeMap::serialize_key(self, key)?; ser::SerializeMap::serialize_value(self, value) } @@ -351,7 +512,11 @@ impl ser::SerializeStruct for &mut Serializer { } } -impl ser::SerializeStructVariant for &mut Serializer { +impl<'a, W, F> ser::SerializeStructVariant for Map<'a, W, F> +where + W: io::Write, + F: Formatter, +{ type Ok = (); type Error = Error; @@ -363,22 +528,670 @@ impl ser::SerializeStructVariant for &mut Serializer { } fn end(self) -> Result<()> { - self.output += "}}"; + match self.state { + State::Empty => {} + _ => self + .ser + .formatter + .end_object(&mut self.ser.writer) + .map_err(Error::from)?, + }; + self.ser + .formatter + .end_object_value(&mut self.ser.writer) + .map_err(Error::from)?; + self.ser + .formatter + .end_object(&mut self.ser.writer) + .map_err(Error::from) + } +} + +pub fn to_writer(writer: W, value: &T) -> Result<()> +where + W: io::Write, + T: ?Sized + Serialize, +{ + let mut ser = Serializer::new(writer); + value.serialize(&mut ser) +} + +pub fn to_vec(value: &T) -> Result> +where + T: ?Sized + Serialize, +{ + let mut writer = Vec::with_capacity(128); + to_writer(&mut writer, value)?; + Ok(writer) +} + +/// Represents a character escape code in a type-safe manner. +pub enum CharEscape { + /// An escaped quote `"` + Quote, + /// An escaped reverse solidus `\` + ReverseSolidus, + /// An escaped solidus `/` + Solidus, + /// An escaped backspace character (usually escaped as `\b`) + Backspace, + /// An escaped form feed character (usually escaped as `\f`) + FormFeed, + /// An escaped line feed character (usually escaped as `\n`) + LineFeed, + /// An escaped carriage return character (usually escaped as `\r`) + CarriageReturn, + /// An escaped tab character (usually escaped as `\t`) + Tab, + /// An escaped ASCII plane control character (usually escaped as + /// `\u00XX` where `XX` are two hex characters) + AsciiControl(u8), +} + +impl CharEscape { + fn from_escape_table(escape: u8, byte: u8) -> CharEscape { + match escape { + self::BB => CharEscape::Backspace, + self::TT => CharEscape::Tab, + self::NN => CharEscape::LineFeed, + self::FF => CharEscape::FormFeed, + self::RR => CharEscape::CarriageReturn, + self::QU => CharEscape::Quote, + self::BS => CharEscape::ReverseSolidus, + self::UU => CharEscape::AsciiControl(byte), + _ => unreachable!(), + } + } +} + +const BB: u8 = b'b'; // \x08 +const TT: u8 = b't'; // \x09 +const NN: u8 = b'n'; // \x0A +const FF: u8 = b'f'; // \x0C +const RR: u8 = b'r'; // \x0D +const QU: u8 = b'"'; // \x22 +const BS: u8 = b'\\'; // \x5C +const UU: u8 = b'u'; // \x00...\x1F except the ones above +const __: u8 = 0; + +pub trait Formatter { + /// Writes a `null` value to the specified writer. + fn write_null(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(b"null") + } + + /// Writes a `true` or `false` value to the specified writer. + fn write_bool(&mut self, writer: &mut W, value: bool) -> io::Result<()> + where + W: ?Sized + io::Write, + { + let s = if value { + b"true" as &[u8] + } else { + b"false" as &[u8] + }; + writer.write_all(s) + } + + /// Writes an integer value like `-123` to the specified writer. + fn write_i8(&mut self, writer: &mut W, value: i8) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(value.to_string().as_bytes()) + } + + /// Writes an integer value like `-123` to the specified writer. + fn write_i16(&mut self, writer: &mut W, value: i16) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(value.to_string().as_bytes()) + } + + /// Writes an integer value like `-123` to the specified writer. + fn write_i32(&mut self, writer: &mut W, value: i32) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(value.to_string().as_bytes()) + } + + /// Writes an integer value like `-123` to the specified writer. + fn write_i64(&mut self, writer: &mut W, value: i64) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(value.to_string().as_bytes()) + } + + /// Writes an integer value like `-123` to the specified writer. + fn write_i128(&mut self, writer: &mut W, value: i128) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(value.to_string().as_bytes()) + } + + /// Writes an integer value like `123` to the specified writer. + + fn write_u8(&mut self, writer: &mut W, value: u8) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(value.to_string().as_bytes()) + } + + /// Writes an integer value like `123` to the specified writer. + + fn write_u16(&mut self, writer: &mut W, value: u16) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(value.to_string().as_bytes()) + } + + /// Writes an integer value like `123` to the specified writer. + + fn write_u32(&mut self, writer: &mut W, value: u32) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(value.to_string().as_bytes()) + } + + /// Writes an integer value like `123` to the specified writer. + + fn write_u64(&mut self, writer: &mut W, value: u64) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(value.to_string().as_bytes()) + } + + /// Writes an integer value like `123` to the specified writer. + + fn write_u128(&mut self, writer: &mut W, value: u128) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(value.to_string().as_bytes()) + } + + /// Writes a floating point value like `-31.26e+12` to the specified writer. + + fn write_f32(&mut self, writer: &mut W, value: f32) -> io::Result<()> + where + W: ?Sized + io::Write, + { + match value.classify() { + FpCategory::Nan => { + self.write_null(writer)?; + } + FpCategory::Infinite => { + let infinity = if value.is_sign_negative() { + "-9e999" + } else { + "9e999" + }; + writer.write_all(infinity.as_bytes())?; + } + _ => { + writer.write_all(value.to_string().as_bytes())?; + } + } + Ok(()) + } + + /// Writes a floating point value like `-31.26e+12` to the specified writer. + + fn write_f64(&mut self, writer: &mut W, value: f64) -> io::Result<()> + where + W: ?Sized + io::Write, + { + match value.classify() { + FpCategory::Nan => { + self.write_null(writer)?; + } + FpCategory::Infinite => { + let infinity = if value.is_sign_negative() { + "-9e999" + } else { + "9e999" + }; + writer.write_all(infinity.as_bytes())?; + } + _ => { + // let mut buffer = ryu::Buffer::new(); + // let s = buffer.format_finite(value); + + // TODO this the previous implementation present in the package + // However, serde_json does it differently above. + // Not sure if there if its done like this because of the precision + let s = &format!("{:.1}", value); + writer.write_all(s.as_bytes())?; + } + } + Ok(()) + } + + /// Writes a number that has already been rendered to a string. + + fn write_number_str(&mut self, writer: &mut W, value: &str) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(value.as_bytes()) + } + + /// Called before each series of `write_string_fragment` and + /// `write_char_escape`. Writes a `"` to the specified writer. + + fn begin_string(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(b"\"") + } + + /// Called after each series of `write_string_fragment` and + /// `write_char_escape`. Writes a `"` to the specified writer. + fn end_string(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(b"\"") + } + + /// Writes a string fragment that doesn't need any escaping to the + /// specified writer. + + fn write_string_fragment(&mut self, writer: &mut W, fragment: &str) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(fragment.as_bytes()) + } + + /// Writes a character escape code to the specified writer. + fn write_char_escape(&mut self, writer: &mut W, char_escape: CharEscape) -> io::Result<()> + where + W: ?Sized + io::Write, + { + use self::CharEscape::*; + + let s = match char_escape { + Quote => b"\\\"", + ReverseSolidus => b"\\\\", + Solidus => b"\\/", + Backspace => b"\\b", + FormFeed => b"\\f", + LineFeed => b"\\n", + CarriageReturn => b"\\r", + Tab => b"\\t", + AsciiControl(byte) => { + static HEX_DIGITS: [u8; 16] = *b"0123456789abcdef"; + let bytes = &[ + b'\\', + b'u', + b'0', + b'0', + HEX_DIGITS[(byte >> 4) as usize], + HEX_DIGITS[(byte & 0xF) as usize], + ]; + return writer.write_all(bytes); + } + }; + + writer.write_all(s) + } + + /// Writes the representation of a byte array. Formatters can choose whether + /// to represent bytes as a JSON array of integers (the default), or some + /// JSON string encoding like hex or base64. + fn write_byte_array(&mut self, writer: &mut W, value: &[u8]) -> io::Result<()> + where + W: ?Sized + io::Write, + { + self.begin_array(writer)?; + let mut first = true; + for byte in value { + self.begin_array_value(writer, first)?; + self.write_u8(writer, *byte)?; + self.end_array_value(writer)?; + first = false; + } + self.end_array(writer) + } + + /// Called before every array. Writes a `[` to the specified + /// writer. + + fn begin_array(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(b"[") + } + + /// Called after every array. Writes a `]` to the specified + /// writer. + + fn end_array(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(b"]") + } + + /// Called before every array value. Writes a `,` if needed to + /// the specified writer. + + fn begin_array_value(&mut self, writer: &mut W, first: bool) -> io::Result<()> + where + W: ?Sized + io::Write, + { + if first { + Ok(()) + } else { + writer.write_all(b",") + } + } + + /// Called after every array value. + + fn end_array_value(&mut self, _writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + Ok(()) + } + + /// Called before every object. Writes a `{` to the specified + /// writer. + + fn begin_object(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(b"{") + } + + /// Called after every object. Writes a `}` to the specified + /// writer. + + fn end_object(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(b"}") + } + + /// Called before every object key. + + fn begin_object_key(&mut self, writer: &mut W, first: bool) -> io::Result<()> + where + W: ?Sized + io::Write, + { + if first { + Ok(()) + } else { + writer.write_all(b",") + } + } + + /// Called after every object key. A `:` should be written to the + /// specified writer by either this method or + /// `begin_object_value`. + + fn end_object_key(&mut self, _writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + Ok(()) + } + + /// Called before every object value. A `:` should be written to + /// the specified writer by either this method or + /// `end_object_key`. + + fn begin_object_value(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(b":") + } + + /// Called after every object value. + + fn end_object_value(&mut self, _writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + Ok(()) + } + + /// Writes a raw JSON fragment that doesn't need any escaping to the + /// specified writer. + + fn write_raw_fragment(&mut self, writer: &mut W, fragment: &str) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(fragment.as_bytes()) + } +} + +fn format_escaped_str(writer: &mut W, formatter: &mut F, value: &str) -> io::Result<()> +where + W: ?Sized + io::Write, + F: ?Sized + Formatter, +{ + formatter.begin_string(writer)?; + format_escaped_str_contents(writer, formatter, value)?; + formatter.end_string(writer) +} + +fn format_escaped_str_contents( + 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, &byte) in bytes.iter().enumerate() { + let escape = self::ESCAPE[byte as usize]; + if escape == 0 { + continue; + } + + if start < i { + formatter.write_string_fragment(writer, &value[start..i])?; + } + + let char_escape = CharEscape::from_escape_table(escape, byte); + formatter.write_char_escape(writer, char_escape)?; + + start = i + 1; + } + + if start == bytes.len() { + return Ok(()); + } + + formatter.write_string_fragment(writer, &value[start..]) +} + +// Lookup table of escape sequences. A value of b'x' at index i means that byte +// i is escaped as "\x" in JSON. A value of 0 means that byte i is not escaped. +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, BB, TT, NN, UU, FF, RR, 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 +]; + +/// This structure compacts a JSON value with no extra whitespace. +#[derive(Clone, Debug)] +pub struct CompactFormatter; + +impl Formatter for CompactFormatter {} + +/// This structure pretty prints a JSON value to make it human readable. +#[derive(Clone, Debug)] +pub struct PrettyFormatter<'a> { + current_indent: usize, + has_value: bool, + indent: &'a [u8], +} + +impl<'a> PrettyFormatter<'a> { + /// Construct a pretty printer formatter that defaults to using two spaces for indentation. + pub fn new() -> Self { + PrettyFormatter::with_indent(b" ") + } + + /// Construct a pretty printer formatter that uses the `indent` string for indentation. + pub fn with_indent(indent: &'a [u8]) -> Self { + PrettyFormatter { + current_indent: 0, + has_value: false, + indent, + } + } +} + +impl<'a> Default for PrettyFormatter<'a> { + fn default() -> Self { + PrettyFormatter::new() + } +} + +impl<'a> Formatter for PrettyFormatter<'a> { + #[inline] + fn begin_array(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + self.current_indent += 1; + self.has_value = false; + writer.write_all(b"[") + } + + #[inline] + fn end_array(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + self.current_indent -= 1; + + if self.has_value { + writer.write_all(b"\n")?; + indent(writer, self.current_indent, self.indent)?; + } + + writer.write_all(b"]") + } + + #[inline] + fn begin_array_value(&mut self, writer: &mut W, first: bool) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(if first { b"\n" } else { b",\n" })?; + indent(writer, self.current_indent, self.indent) + } + + #[inline] + fn end_array_value(&mut self, _writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + self.has_value = true; + Ok(()) + } + + #[inline] + fn begin_object(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + self.current_indent += 1; + self.has_value = false; + writer.write_all(b"{") + } + + #[inline] + fn end_object(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + self.current_indent -= 1; + + if self.has_value { + writer.write_all(b"\n")?; + indent(writer, self.current_indent, self.indent)?; + } + + writer.write_all(b"}") + } + + #[inline] + fn begin_object_key(&mut self, writer: &mut W, first: bool) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(if first { b"\n" } else { b",\n" })?; + indent(writer, self.current_indent, self.indent) + } + + #[inline] + fn begin_object_value(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(b": ") + } + + #[inline] + fn end_object_value(&mut self, _writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + self.has_value = true; Ok(()) } } -fn escape(v: &str) -> String { - v.chars() - .flat_map(|c| match c { - '"' => vec!['\\', c], - '\n' => vec!['\\', 'n'], - '\r' => vec!['\\', 'r'], - '\t' => vec!['\\', 't'], - '\\' => vec!['\\', '\\'], - '\u{0008}' => vec!['\\', 'b'], - '\u{000c}' => vec!['\\', 'f'], - c => vec![c], - }) - .collect() -} +fn indent(wr: &mut W, n: usize, s: &[u8]) -> io::Result<()> +where + W: ?Sized + io::Write, +{ + for _ in 0..n { + wr.write_all(s)?; + } + + Ok(()) +} \ No newline at end of file