Skip to content

Commit 83f9f07

Browse files
committed
serialize: Remove allocations from escaping strs and indenting spaces
1 parent 04ac2b0 commit 83f9f07

File tree

1 file changed

+63
-38
lines changed

1 file changed

+63
-38
lines changed

src/libserialize/json.rs

Lines changed: 63 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -256,22 +256,38 @@ fn io_error_to_error(io: io::IoError) -> ParserError {
256256
pub type EncodeResult = io::IoResult<()>;
257257
pub type DecodeResult<T> = Result<T, DecoderError>;
258258

259-
fn escape_str(s: &str) -> String {
260-
let mut escaped = String::from_str("\"");
261-
for c in s.chars() {
262-
match c {
263-
'"' => escaped.push_str("\\\""),
264-
'\\' => escaped.push_str("\\\\"),
265-
'\x08' => escaped.push_str("\\b"),
266-
'\x0c' => escaped.push_str("\\f"),
267-
'\n' => escaped.push_str("\\n"),
268-
'\r' => escaped.push_str("\\r"),
269-
'\t' => escaped.push_str("\\t"),
270-
_ => escaped.push_char(c),
271-
}
272-
};
273-
escaped.push_char('"');
274-
escaped
259+
fn escape_bytes(writer: &mut io::Writer, s: &[u8]) -> Result<(), io::IoError> {
260+
try!(writer.write_str("\""));
261+
for byte in s.iter() {
262+
match *byte {
263+
b'"' => try!(writer.write_str("\\\"")),
264+
b'\\' => try!(writer.write_str("\\\\")),
265+
b'\x08' => try!(writer.write_str("\\b")),
266+
b'\x0c' => try!(writer.write_str("\\f")),
267+
b'\n' => try!(writer.write_str("\\n")),
268+
b'\r' => try!(writer.write_str("\\r")),
269+
b'\t' => try!(writer.write_str("\\t")),
270+
_ => try!(writer.write_u8(*byte)),
271+
}
272+
}
273+
writer.write_str("\"")
274+
}
275+
276+
fn escape_str(writer: &mut io::Writer, v: &str) -> Result<(), io::IoError> {
277+
escape_bytes(writer, v.as_bytes())
278+
}
279+
280+
fn escape_char(writer: &mut io::Writer, v: char) -> Result<(), io::IoError> {
281+
let mut buf = [0, .. 4];
282+
v.encode_utf8(buf);
283+
escape_bytes(writer, buf)
284+
}
285+
286+
fn spaces(writer: &mut io::Writer, n: uint) -> Result<(), io::IoError> {
287+
for _ in range(0, n) {
288+
try!(writer.write_str(" "));
289+
}
290+
Ok(())
275291
}
276292

277293
fn fmt_number_or_null(v: f64) -> String {
@@ -281,10 +297,6 @@ fn fmt_number_or_null(v: f64) -> String {
281297
}
282298
}
283299

284-
fn spaces(n: uint) -> String {
285-
String::from_char(n, ' ')
286-
}
287-
288300
/// A structure for implementing serialization to JSON.
289301
pub struct Encoder<'a> {
290302
writer: &'a mut io::Writer,
@@ -348,10 +360,10 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
348360
fn emit_f32(&mut self, v: f32) -> EncodeResult { self.emit_f64(v as f64) }
349361

350362
fn emit_char(&mut self, v: char) -> EncodeResult {
351-
self.emit_str(str::from_char(v).as_slice())
363+
escape_char(self.writer, v)
352364
}
353365
fn emit_str(&mut self, v: &str) -> EncodeResult {
354-
write!(self.writer, "{}", escape_str(v))
366+
escape_str(self.writer, v)
355367
}
356368

357369
fn emit_enum(&mut self, _name: &str, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
@@ -367,10 +379,10 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
367379
// Bunny => "Bunny"
368380
// Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]}
369381
if cnt == 0 {
370-
write!(self.writer, "{}", escape_str(name))
382+
escape_str(self.writer, name)
371383
} else {
372384
try!(write!(self.writer, "{{\"variant\":"));
373-
try!(write!(self.writer, "{}", escape_str(name)));
385+
try!(escape_str(self.writer, name));
374386
try!(write!(self.writer, ",\"fields\":["));
375387
try!(f(self));
376388
write!(self.writer, "]}}")
@@ -415,7 +427,8 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
415427
idx: uint,
416428
f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
417429
if idx != 0 { try!(write!(self.writer, ",")); }
418-
try!(write!(self.writer, "{}:", escape_str(name)));
430+
try!(escape_str(self.writer, name));
431+
try!(write!(self.writer, ":"));
419432
f(self)
420433
}
421434

@@ -541,10 +554,10 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
541554
}
542555

543556
fn emit_char(&mut self, v: char) -> EncodeResult {
544-
self.emit_str(str::from_char(v).as_slice())
557+
escape_char(self.writer, v)
545558
}
546559
fn emit_str(&mut self, v: &str) -> EncodeResult {
547-
write!(self.writer, "{}", escape_str(v))
560+
escape_str(self.writer, v)
548561
}
549562

550563
fn emit_enum(&mut self,
@@ -559,14 +572,18 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
559572
cnt: uint,
560573
f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
561574
if cnt == 0 {
562-
write!(self.writer, "{}", escape_str(name))
575+
escape_str(self.writer, name)
563576
} else {
564577
self.indent += 2;
565-
try!(write!(self.writer, "[\n{}{},\n", spaces(self.indent),
566-
escape_str(name)));
578+
try!(write!(self.writer, "[\n"));
579+
try!(spaces(self.writer, self.indent));
580+
try!(escape_str(self.writer, name));
581+
try!(write!(self.writer, ",\n"));
567582
try!(f(self));
568583
self.indent -= 2;
569-
write!(self.writer, "\n{}]", spaces(self.indent))
584+
try!(write!(self.writer, "\n"));
585+
try!(spaces(self.writer, self.indent));
586+
write!(self.writer, "]")
570587
}
571588
}
572589

@@ -576,7 +593,7 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
576593
if idx != 0 {
577594
try!(write!(self.writer, ",\n"));
578595
}
579-
try!(write!(self.writer, "{}", spaces(self.indent)));
596+
try!(spaces(self.writer, self.indent));
580597
f(self)
581598
}
582599

@@ -607,7 +624,9 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
607624
self.indent += 2;
608625
try!(f(self));
609626
self.indent -= 2;
610-
write!(self.writer, "\n{}}}", spaces(self.indent))
627+
try!(write!(self.writer, "\n"));
628+
try!(spaces(self.writer, self.indent));
629+
write!(self.writer, "}}")
611630
}
612631
}
613632

@@ -620,7 +639,9 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
620639
} else {
621640
try!(write!(self.writer, ",\n"));
622641
}
623-
try!(write!(self.writer, "{}{}: ", spaces(self.indent), escape_str(name)));
642+
try!(spaces(self.writer, self.indent));
643+
try!(escape_str(self.writer, name));
644+
try!(write!(self.writer, ": "));
624645
f(self)
625646
}
626647

@@ -665,7 +686,9 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
665686
self.indent += 2;
666687
try!(f(self));
667688
self.indent -= 2;
668-
write!(self.writer, "\n{}]", spaces(self.indent))
689+
try!(write!(self.writer, "\n"));
690+
try!(spaces(self.writer, self.indent));
691+
write!(self.writer, "]")
669692
}
670693
}
671694

@@ -677,7 +700,7 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
677700
} else {
678701
try!(write!(self.writer, ",\n"));
679702
}
680-
try!(write!(self.writer, "{}", spaces(self.indent)));
703+
try!(spaces(self.writer, self.indent));
681704
f(self)
682705
}
683706

@@ -691,7 +714,9 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
691714
self.indent += 2;
692715
try!(f(self));
693716
self.indent -= 2;
694-
write!(self.writer, "\n{}}}", spaces(self.indent))
717+
try!(write!(self.writer, "\n"));
718+
try!(spaces(self.writer, self.indent));
719+
write!(self.writer, "}}")
695720
}
696721
}
697722

@@ -703,7 +728,7 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
703728
} else {
704729
try!(write!(self.writer, ",\n"));
705730
}
706-
try!(write!(self.writer, "{}", spaces(self.indent)));
731+
try!(spaces(self.writer, self.indent));
707732
// ref #12967, make sure to wrap a key in double quotes,
708733
// in the event that its of a type that omits them (eg numbers)
709734
let mut buf = MemWriter::new();

0 commit comments

Comments
 (0)