mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-13 11:21:01 +00:00
Split json compact and pretty serializer. Recover 20MB/s
This commit is contained in:
+143
-92
@@ -6,41 +6,33 @@ use std::string::FromUtf8Error;
|
|||||||
use ser;
|
use ser;
|
||||||
|
|
||||||
/// A structure for implementing serialization to JSON.
|
/// A structure for implementing serialization to JSON.
|
||||||
pub struct Serializer<W> {
|
pub struct Serializer<W, F=CompactFormatter> {
|
||||||
writer: W,
|
writer: W,
|
||||||
format: Format,
|
formatter: F,
|
||||||
current_indent: usize,
|
|
||||||
indent: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, PartialEq)]
|
impl<W> Serializer<W>
|
||||||
enum Format {
|
where W: io::Write,
|
||||||
Compact,
|
{
|
||||||
Pretty,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W: io::Write> Serializer<W> {
|
|
||||||
/// Creates a new JSON visitr whose output will be written to the writer
|
/// Creates a new JSON visitr whose output will be written to the writer
|
||||||
/// specified.
|
/// specified.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(writer: W) -> Serializer<W> {
|
pub fn new(writer: W) -> Serializer<W> {
|
||||||
Serializer {
|
Serializer::new_with_formatter(writer, CompactFormatter)
|
||||||
writer: writer,
|
|
||||||
format: Format::Compact,
|
|
||||||
current_indent: 0,
|
|
||||||
indent: 0,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W, F> Serializer<W, F>
|
||||||
|
where W: io::Write,
|
||||||
|
F: Formatter,
|
||||||
|
{
|
||||||
/// Creates a new JSON visitr whose output will be written to the writer
|
/// Creates a new JSON visitr whose output will be written to the writer
|
||||||
/// specified.
|
/// specified.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_pretty(writer: W) -> Serializer<W> {
|
pub fn new_with_formatter(writer: W, formatter: F) -> Serializer<W, F> {
|
||||||
Serializer {
|
Serializer {
|
||||||
writer: writer,
|
writer: writer,
|
||||||
format: Format::Pretty,
|
formatter: formatter,
|
||||||
current_indent: 0,
|
|
||||||
indent: 2,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,49 +41,11 @@ impl<W: io::Write> Serializer<W> {
|
|||||||
pub fn into_inner(self) -> W {
|
pub fn into_inner(self) -> W {
|
||||||
self.writer
|
self.writer
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_sep(&mut self, first: bool) -> io::Result<()> {
|
|
||||||
match self.format {
|
|
||||||
Format::Compact => {
|
|
||||||
if first {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
self.writer.write_all(b",")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Format::Pretty => {
|
|
||||||
if first {
|
|
||||||
self.current_indent += self.indent;
|
|
||||||
try!(self.writer.write_all(b"\n"));
|
|
||||||
} else {
|
|
||||||
try!(self.writer.write_all(b",\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
spaces(&mut self.writer, self.current_indent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_colon(&mut self) -> io::Result<()> {
|
|
||||||
match self.format {
|
|
||||||
Format::Compact => self.writer.write_all(b":"),
|
|
||||||
Format::Pretty => self.writer.write_all(b": "),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_end(&mut self, current_indent: usize, s: &[u8]) -> io::Result<()> {
|
|
||||||
if self.format == Format::Pretty && current_indent != self.current_indent {
|
|
||||||
self.current_indent -= self.indent;
|
|
||||||
try!(self.writer.write(b"\n"));
|
|
||||||
try!(spaces(&mut self.writer, self.current_indent));
|
|
||||||
}
|
|
||||||
|
|
||||||
self.writer.write_all(s)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W> ser::Serializer for Serializer<W>
|
impl<W, F> ser::Serializer for Serializer<W, F>
|
||||||
where W: io::Write,
|
where W: io::Write,
|
||||||
|
F: Formatter,
|
||||||
{
|
{
|
||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
|
|
||||||
@@ -193,48 +147,50 @@ impl<W> ser::Serializer for Serializer<W>
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum_unit(&mut self, _name: &str, variant: &str) -> io::Result<()> {
|
fn visit_enum_unit(&mut self, _name: &str, variant: &str) -> io::Result<()> {
|
||||||
let current_indent = self.current_indent;
|
try!(self.formatter.open(&mut self.writer, b'{'));
|
||||||
|
try!(self.formatter.comma(&mut self.writer, true));
|
||||||
try!(self.writer.write_all(b"{"));
|
|
||||||
try!(self.serialize_sep(true));
|
|
||||||
try!(self.visit_str(variant));
|
try!(self.visit_str(variant));
|
||||||
try!(self.serialize_colon());
|
try!(self.formatter.colon(&mut self.writer));
|
||||||
try!(self.writer.write_all(b"[]"));
|
try!(self.writer.write_all(b"[]"));
|
||||||
self.serialize_end(current_indent, b"}")
|
self.formatter.close(&mut self.writer, b'}')
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_seq<V>(&mut self, mut visitor: V) -> io::Result<()>
|
fn visit_seq<V>(&mut self, mut visitor: V) -> io::Result<()>
|
||||||
where V: ser::SeqVisitor,
|
where V: ser::SeqVisitor,
|
||||||
{
|
{
|
||||||
let current_indent = self.current_indent;
|
match visitor.len() {
|
||||||
|
Some(len) if len == 0 => {
|
||||||
|
self.writer.write_all(b"[]")
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
try!(self.formatter.open(&mut self.writer, b'['));
|
||||||
|
|
||||||
try!(self.writer.write_all(b"["));
|
while let Some(()) = try!(visitor.visit(self)) { }
|
||||||
|
|
||||||
while let Some(()) = try!(visitor.visit(self)) { }
|
self.formatter.close(&mut self.writer, b']')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.serialize_end(current_indent, b"]")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum_seq<V>(&mut self, _name: &str, variant: &str, visitor: V) -> io::Result<()>
|
fn visit_enum_seq<V>(&mut self, _name: &str, variant: &str, visitor: V) -> io::Result<()>
|
||||||
where V: ser::SeqVisitor,
|
where V: ser::SeqVisitor,
|
||||||
{
|
{
|
||||||
let current_indent = self.current_indent;
|
try!(self.formatter.open(&mut self.writer, b'{'));
|
||||||
|
try!(self.formatter.comma(&mut self.writer, true));
|
||||||
try!(self.writer.write_all(b"{"));
|
|
||||||
try!(self.serialize_sep(true));
|
|
||||||
try!(self.visit_str(variant));
|
try!(self.visit_str(variant));
|
||||||
try!(self.serialize_colon());
|
try!(self.formatter.colon(&mut self.writer));
|
||||||
try!(self.visit_seq(visitor));
|
try!(self.visit_seq(visitor));
|
||||||
self.serialize_end(current_indent, b"}")
|
self.formatter.close(&mut self.writer, b'}')
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_seq_elt<T>(&mut self, first: bool, value: T) -> io::Result<()>
|
fn visit_seq_elt<T>(&mut self, first: bool, value: T) -> io::Result<()>
|
||||||
where T: ser::Serialize,
|
where T: ser::Serialize,
|
||||||
{
|
{
|
||||||
try!(self.serialize_sep(first));
|
try!(self.formatter.comma(&mut self.writer, first));
|
||||||
|
|
||||||
value.serialize(self)
|
value.serialize(self)
|
||||||
}
|
}
|
||||||
@@ -243,27 +199,31 @@ impl<W> ser::Serializer for Serializer<W>
|
|||||||
fn visit_map<V>(&mut self, mut visitor: V) -> io::Result<()>
|
fn visit_map<V>(&mut self, mut visitor: V) -> io::Result<()>
|
||||||
where V: ser::MapVisitor,
|
where V: ser::MapVisitor,
|
||||||
{
|
{
|
||||||
let current_indent = self.current_indent;
|
match visitor.len() {
|
||||||
|
Some(len) if len == 0 => {
|
||||||
|
self.writer.write_all(b"{}")
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
try!(self.formatter.open(&mut self.writer, b'{'));
|
||||||
|
|
||||||
try!(self.writer.write_all(b"{"));
|
while let Some(()) = try!(visitor.visit(self)) { }
|
||||||
|
|
||||||
while let Some(()) = try!(visitor.visit(self)) { }
|
self.formatter.close(&mut self.writer, b'}')
|
||||||
|
}
|
||||||
self.serialize_end(current_indent, b"}")
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum_map<V>(&mut self, _name: &str, variant: &str, visitor: V) -> io::Result<()>
|
fn visit_enum_map<V>(&mut self, _name: &str, variant: &str, visitor: V) -> io::Result<()>
|
||||||
where V: ser::MapVisitor,
|
where V: ser::MapVisitor,
|
||||||
{
|
{
|
||||||
let current_indent = self.current_indent;
|
try!(self.formatter.open(&mut self.writer, b'{'));
|
||||||
|
try!(self.formatter.comma(&mut self.writer, true));
|
||||||
try!(self.writer.write_all(b"{"));
|
|
||||||
try!(self.serialize_sep(true));
|
|
||||||
try!(self.visit_str(variant));
|
try!(self.visit_str(variant));
|
||||||
try!(self.serialize_colon());
|
try!(self.formatter.colon(&mut self.writer));
|
||||||
try!(self.visit_map(visitor));
|
try!(self.visit_map(visitor));
|
||||||
self.serialize_end(current_indent, b"}")
|
|
||||||
|
self.formatter.close(&mut self.writer, b'}')
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -271,13 +231,101 @@ impl<W> ser::Serializer for Serializer<W>
|
|||||||
where K: ser::Serialize,
|
where K: ser::Serialize,
|
||||||
V: ser::Serialize,
|
V: ser::Serialize,
|
||||||
{
|
{
|
||||||
try!(self.serialize_sep(first));
|
try!(self.formatter.comma(&mut self.writer, first));
|
||||||
try!(key.serialize(self));
|
try!(key.serialize(self));
|
||||||
try!(self.serialize_colon());
|
try!(self.formatter.colon(&mut self.writer));
|
||||||
value.serialize(self)
|
value.serialize(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Formatter {
|
||||||
|
fn open<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
|
||||||
|
where W: io::Write;
|
||||||
|
|
||||||
|
fn comma<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
|
||||||
|
where W: io::Write;
|
||||||
|
|
||||||
|
fn colon<W>(&mut self, writer: &mut W) -> io::Result<()>
|
||||||
|
where W: io::Write;
|
||||||
|
|
||||||
|
fn close<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
|
||||||
|
where W: io::Write;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CompactFormatter;
|
||||||
|
|
||||||
|
impl Formatter for CompactFormatter {
|
||||||
|
fn open<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
|
||||||
|
where W: io::Write,
|
||||||
|
{
|
||||||
|
writer.write_all(&[ch])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn comma<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
|
||||||
|
where W: io::Write,
|
||||||
|
{
|
||||||
|
if first {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
writer.write_all(b",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn colon<W>(&mut self, writer: &mut W) -> io::Result<()>
|
||||||
|
where W: io::Write,
|
||||||
|
{
|
||||||
|
writer.write_all(b":")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
|
||||||
|
where W: io::Write,
|
||||||
|
{
|
||||||
|
writer.write_all(&[ch])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PrettyFormatter {
|
||||||
|
current_indent: usize,
|
||||||
|
indent: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Formatter for PrettyFormatter {
|
||||||
|
fn open<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
|
||||||
|
where W: io::Write,
|
||||||
|
{
|
||||||
|
self.current_indent += self.indent;
|
||||||
|
writer.write_all(&[ch])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn comma<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
|
||||||
|
where W: io::Write,
|
||||||
|
{
|
||||||
|
if first {
|
||||||
|
try!(writer.write_all(b"\n"));
|
||||||
|
} else {
|
||||||
|
try!(writer.write_all(b",\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
spaces(writer, self.current_indent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn colon<W>(&mut self, writer: &mut W) -> io::Result<()>
|
||||||
|
where W: io::Write,
|
||||||
|
{
|
||||||
|
writer.write_all(b": ")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
|
||||||
|
where W: io::Write,
|
||||||
|
{
|
||||||
|
self.current_indent -= self.indent;
|
||||||
|
try!(writer.write(b"\n"));
|
||||||
|
try!(spaces(writer, self.current_indent));
|
||||||
|
|
||||||
|
writer.write_all(&[ch])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn escape_bytes<W>(wr: &mut W, bytes: &[u8]) -> io::Result<()>
|
pub fn escape_bytes<W>(wr: &mut W, bytes: &[u8]) -> io::Result<()>
|
||||||
where W: io::Write
|
where W: io::Write
|
||||||
@@ -366,7 +414,10 @@ pub fn to_writer_pretty<W, T>(writer: &mut W, value: &T) -> io::Result<()>
|
|||||||
where W: io::Write,
|
where W: io::Write,
|
||||||
T: ser::Serialize,
|
T: ser::Serialize,
|
||||||
{
|
{
|
||||||
let mut ser = Serializer::new_pretty(writer);
|
let mut ser = Serializer::new_with_formatter(writer, PrettyFormatter {
|
||||||
|
current_indent: 0,
|
||||||
|
indent: 2,
|
||||||
|
});
|
||||||
try!(value.serialize(&mut ser));
|
try!(value.serialize(&mut ser));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user