diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 832bc9c4e10..49f929d4658 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -256,22 +256,38 @@ fn io_error_to_error(io: io::IoError) -> ParserError { pub type EncodeResult = io::IoResult<()>; pub type DecodeResult = Result; -fn escape_str(s: &str) -> String { - let mut escaped = String::from_str("\""); - for c in s.chars() { - match c { - '"' => escaped.push_str("\\\""), - '\\' => escaped.push_str("\\\\"), - '\x08' => escaped.push_str("\\b"), - '\x0c' => escaped.push_str("\\f"), - '\n' => escaped.push_str("\\n"), - '\r' => escaped.push_str("\\r"), - '\t' => escaped.push_str("\\t"), - _ => escaped.push_char(c), +fn escape_bytes(writer: &mut io::Writer, s: &[u8]) -> Result<(), io::IoError> { + try!(writer.write_str("\"")); + for byte in s.iter() { + match *byte { + b'"' => try!(writer.write_str("\\\"")), + b'\\' => try!(writer.write_str("\\\\")), + b'\x08' => try!(writer.write_str("\\b")), + b'\x0c' => try!(writer.write_str("\\f")), + b'\n' => try!(writer.write_str("\\n")), + b'\r' => try!(writer.write_str("\\r")), + b'\t' => try!(writer.write_str("\\t")), + _ => try!(writer.write_u8(*byte)), } - }; - escaped.push_char('"'); - escaped + } + writer.write_str("\"") +} + +fn escape_str(writer: &mut io::Writer, v: &str) -> Result<(), io::IoError> { + escape_bytes(writer, v.as_bytes()) +} + +fn escape_char(writer: &mut io::Writer, v: char) -> Result<(), io::IoError> { + let mut buf = [0, .. 4]; + v.encode_utf8(buf); + escape_bytes(writer, buf) +} + +fn spaces(writer: &mut io::Writer, n: uint) -> Result<(), io::IoError> { + for _ in range(0, n) { + try!(writer.write_str(" ")); + } + Ok(()) } fn fmt_number_or_null(v: f64) -> String { @@ -281,10 +297,6 @@ fn fmt_number_or_null(v: f64) -> String { } } -fn spaces(n: uint) -> String { - String::from_char(n, ' ') -} - /// A structure for implementing serialization to JSON. pub struct Encoder<'a> { writer: &'a mut io::Writer, @@ -348,10 +360,10 @@ impl<'a> ::Encoder for Encoder<'a> { fn emit_f32(&mut self, v: f32) -> EncodeResult { self.emit_f64(v as f64) } fn emit_char(&mut self, v: char) -> EncodeResult { - self.emit_str(str::from_char(v).as_slice()) + escape_char(self.writer, v) } fn emit_str(&mut self, v: &str) -> EncodeResult { - write!(self.writer, "{}", escape_str(v)) + escape_str(self.writer, v) } fn emit_enum(&mut self, _name: &str, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult { @@ -367,10 +379,10 @@ impl<'a> ::Encoder for Encoder<'a> { // Bunny => "Bunny" // Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]} if cnt == 0 { - write!(self.writer, "{}", escape_str(name)) + escape_str(self.writer, name) } else { try!(write!(self.writer, "{{\"variant\":")); - try!(write!(self.writer, "{}", escape_str(name))); + try!(escape_str(self.writer, name)); try!(write!(self.writer, ",\"fields\":[")); try!(f(self)); write!(self.writer, "]}}") @@ -415,7 +427,8 @@ impl<'a> ::Encoder for Encoder<'a> { idx: uint, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult { if idx != 0 { try!(write!(self.writer, ",")); } - try!(write!(self.writer, "{}:", escape_str(name))); + try!(escape_str(self.writer, name)); + try!(write!(self.writer, ":")); f(self) } @@ -541,10 +554,10 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { } fn emit_char(&mut self, v: char) -> EncodeResult { - self.emit_str(str::from_char(v).as_slice()) + escape_char(self.writer, v) } fn emit_str(&mut self, v: &str) -> EncodeResult { - write!(self.writer, "{}", escape_str(v)) + escape_str(self.writer, v) } fn emit_enum(&mut self, @@ -559,14 +572,18 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { cnt: uint, f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult { if cnt == 0 { - write!(self.writer, "{}", escape_str(name)) + escape_str(self.writer, name) } else { self.indent += 2; - try!(write!(self.writer, "[\n{}{},\n", spaces(self.indent), - escape_str(name))); + try!(write!(self.writer, "[\n")); + try!(spaces(self.writer, self.indent)); + try!(escape_str(self.writer, name)); + try!(write!(self.writer, ",\n")); try!(f(self)); self.indent -= 2; - write!(self.writer, "\n{}]", spaces(self.indent)) + try!(write!(self.writer, "\n")); + try!(spaces(self.writer, self.indent)); + write!(self.writer, "]") } } @@ -576,7 +593,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { if idx != 0 { try!(write!(self.writer, ",\n")); } - try!(write!(self.writer, "{}", spaces(self.indent))); + try!(spaces(self.writer, self.indent)); f(self) } @@ -607,7 +624,9 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { self.indent += 2; try!(f(self)); self.indent -= 2; - write!(self.writer, "\n{}}}", spaces(self.indent)) + try!(write!(self.writer, "\n")); + try!(spaces(self.writer, self.indent)); + write!(self.writer, "}}") } } @@ -620,7 +639,9 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { } else { try!(write!(self.writer, ",\n")); } - try!(write!(self.writer, "{}{}: ", spaces(self.indent), escape_str(name))); + try!(spaces(self.writer, self.indent)); + try!(escape_str(self.writer, name)); + try!(write!(self.writer, ": ")); f(self) } @@ -665,7 +686,9 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { self.indent += 2; try!(f(self)); self.indent -= 2; - write!(self.writer, "\n{}]", spaces(self.indent)) + try!(write!(self.writer, "\n")); + try!(spaces(self.writer, self.indent)); + write!(self.writer, "]") } } @@ -677,7 +700,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { } else { try!(write!(self.writer, ",\n")); } - try!(write!(self.writer, "{}", spaces(self.indent))); + try!(spaces(self.writer, self.indent)); f(self) } @@ -691,7 +714,9 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { self.indent += 2; try!(f(self)); self.indent -= 2; - write!(self.writer, "\n{}}}", spaces(self.indent)) + try!(write!(self.writer, "\n")); + try!(spaces(self.writer, self.indent)); + write!(self.writer, "}}") } } @@ -703,7 +728,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { } else { try!(write!(self.writer, ",\n")); } - try!(write!(self.writer, "{}", spaces(self.indent))); + try!(spaces(self.writer, self.indent)); // ref #12967, make sure to wrap a key in double quotes, // in the event that its of a type that omits them (eg numbers) let mut buf = MemWriter::new();