pub type EncodeResult = io::IoResult<()>;
pub type DecodeResult<T> = Result<T, DecoderError>;
-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),
- }
- };
- escaped.push_char('"');
- escaped
+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)),
+ }
+ }
+ 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 {
}
}
-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,
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 {
// 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, "]}}")
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)
}
}
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,
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, "]")
}
}
if idx != 0 {
try!(write!(self.writer, ",\n"));
}
- try!(write!(self.writer, "{}", spaces(self.indent)));
+ try!(spaces(self.writer, self.indent));
f(self)
}
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, "}}")
}
}
} 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)
}
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, "]")
}
}
} else {
try!(write!(self.writer, ",\n"));
}
- try!(write!(self.writer, "{}", spaces(self.indent)));
+ try!(spaces(self.writer, self.indent));
f(self)
}
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, "}}")
}
}
} 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();