json-encoder: report error when hash map key is not string or numeric
This commit is contained in:
parent
bd8a43c668
commit
f015a3b871
@ -202,7 +202,7 @@ use self::InternalStackElement::*;
|
||||
use std;
|
||||
use std::collections::{HashMap, BTreeMap};
|
||||
use std::{char, f64, fmt, io, num, str};
|
||||
use std::mem::{swap, transmute};
|
||||
use std::mem::{swap};
|
||||
use std::num::{Float, Int};
|
||||
use std::num::FpCategory as Fp;
|
||||
use std::str::FromStr;
|
||||
@ -275,6 +275,12 @@ pub enum DecoderError {
|
||||
ApplicationError(string::String)
|
||||
}
|
||||
|
||||
#[derive(Copy, Show)]
|
||||
pub enum EncoderError {
|
||||
FmtError(fmt::Error),
|
||||
BadHashmapKey,
|
||||
}
|
||||
|
||||
/// Returns a readable error string for a given error code.
|
||||
pub fn error_str(error: ErrorCode) -> &'static str {
|
||||
match error {
|
||||
@ -334,10 +340,19 @@ impl std::error::Error for DecoderError {
|
||||
fn detail(&self) -> Option<std::string::String> { Some(format!("{:?}", self)) }
|
||||
}
|
||||
|
||||
pub type EncodeResult = fmt::Result;
|
||||
impl std::error::Error for EncoderError {
|
||||
fn description(&self) -> &str { "encoder error" }
|
||||
fn detail(&self) -> Option<std::string::String> { Some(format!("{:?}", self)) }
|
||||
}
|
||||
|
||||
impl std::error::FromError<fmt::Error> for EncoderError {
|
||||
fn from_error(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) }
|
||||
}
|
||||
|
||||
pub type EncodeResult = Result<(), EncoderError>;
|
||||
pub type DecodeResult<T> = Result<T, DecoderError>;
|
||||
|
||||
fn escape_str(wr: &mut fmt::Writer, v: &str) -> fmt::Result {
|
||||
fn escape_str(wr: &mut fmt::Writer, v: &str) -> EncodeResult {
|
||||
try!(wr.write_str("\""));
|
||||
|
||||
let mut start = 0;
|
||||
@ -395,17 +410,18 @@ fn escape_str(wr: &mut fmt::Writer, v: &str) -> fmt::Result {
|
||||
try!(wr.write_str(&v[start..]));
|
||||
}
|
||||
|
||||
wr.write_str("\"")
|
||||
try!(wr.write_str("\""));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn escape_char(writer: &mut fmt::Writer, v: char) -> fmt::Result {
|
||||
fn escape_char(writer: &mut fmt::Writer, v: char) -> EncodeResult {
|
||||
let mut buf = [0; 4];
|
||||
let n = v.encode_utf8(&mut buf).unwrap();
|
||||
let buf = unsafe { str::from_utf8_unchecked(&buf[..n]) };
|
||||
escape_str(writer, buf)
|
||||
}
|
||||
|
||||
fn spaces(wr: &mut fmt::Writer, mut n: uint) -> fmt::Result {
|
||||
fn spaces(wr: &mut fmt::Writer, mut n: uint) -> EncodeResult {
|
||||
const BUF: &'static str = " ";
|
||||
|
||||
while n >= BUF.len() {
|
||||
@ -414,10 +430,9 @@ fn spaces(wr: &mut fmt::Writer, mut n: uint) -> fmt::Result {
|
||||
}
|
||||
|
||||
if n > 0 {
|
||||
wr.write_str(&BUF[..n])
|
||||
} else {
|
||||
Ok(())
|
||||
try!(wr.write_str(&BUF[..n]));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fmt_number_or_null(v: f64) -> string::String {
|
||||
@ -431,43 +446,62 @@ fn fmt_number_or_null(v: f64) -> string::String {
|
||||
/// A structure for implementing serialization to JSON.
|
||||
pub struct Encoder<'a> {
|
||||
writer: &'a mut (fmt::Writer+'a),
|
||||
is_emitting_map_key: bool,
|
||||
}
|
||||
|
||||
impl<'a> Encoder<'a> {
|
||||
/// Creates a new JSON encoder whose output will be written to the writer
|
||||
/// specified.
|
||||
pub fn new(writer: &'a mut fmt::Writer) -> Encoder<'a> {
|
||||
Encoder { writer: writer }
|
||||
Encoder { writer: writer, is_emitting_map_key: false, }
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! emit_enquoted_if_mapkey {
|
||||
($enc:ident,$e:expr) => {
|
||||
if $enc.is_emitting_map_key {
|
||||
try!(write!($enc.writer, "\"{}\"", $e));
|
||||
Ok(())
|
||||
} else {
|
||||
try!(write!($enc.writer, "{}", $e));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ::Encoder for Encoder<'a> {
|
||||
type Error = fmt::Error;
|
||||
type Error = EncoderError;
|
||||
|
||||
fn emit_nil(&mut self) -> EncodeResult { write!(self.writer, "null") }
|
||||
fn emit_nil(&mut self) -> EncodeResult {
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
try!(write!(self.writer, "null"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_uint(&mut self, v: uint) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_u64(&mut self, v: u64) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_u32(&mut self, v: u32) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_u16(&mut self, v: u16) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_u8(&mut self, v: u8) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_uint(&mut self, v: uint) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_u8(&mut self, v: u8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
|
||||
fn emit_int(&mut self, v: int) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_i64(&mut self, v: i64) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_i32(&mut self, v: i32) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_i16(&mut self, v: i16) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_i8(&mut self, v: i8) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_int(&mut self, v: int) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_i8(&mut self, v: i8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
|
||||
fn emit_bool(&mut self, v: bool) -> EncodeResult {
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
if v {
|
||||
write!(self.writer, "true")
|
||||
try!(write!(self.writer, "true"));
|
||||
} else {
|
||||
write!(self.writer, "false")
|
||||
try!(write!(self.writer, "false"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_f64(&mut self, v: f64) -> EncodeResult {
|
||||
write!(self.writer, "{}", fmt_number_or_null(v))
|
||||
emit_enquoted_if_mapkey!(self, fmt_number_or_null(v))
|
||||
}
|
||||
fn emit_f32(&mut self, v: f32) -> EncodeResult {
|
||||
self.emit_f64(v as f64)
|
||||
@ -483,6 +517,7 @@ impl<'a> ::Encoder for Encoder<'a> {
|
||||
fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
f(self)
|
||||
}
|
||||
|
||||
@ -496,6 +531,7 @@ impl<'a> ::Encoder for Encoder<'a> {
|
||||
// enums are encoded as strings or objects
|
||||
// Bunny => "Bunny"
|
||||
// Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]}
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
if cnt == 0 {
|
||||
escape_str(self.writer, name)
|
||||
} else {
|
||||
@ -503,13 +539,15 @@ impl<'a> ::Encoder for Encoder<'a> {
|
||||
try!(escape_str(self.writer, name));
|
||||
try!(write!(self.writer, ",\"fields\":["));
|
||||
try!(f(self));
|
||||
write!(self.writer, "]}}")
|
||||
try!(write!(self.writer, "]}}"));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_enum_variant_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
if idx != 0 {
|
||||
try!(write!(self.writer, ","));
|
||||
}
|
||||
@ -523,6 +561,7 @@ impl<'a> ::Encoder for Encoder<'a> {
|
||||
f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
self.emit_enum_variant(name, id, cnt, f)
|
||||
}
|
||||
|
||||
@ -532,20 +571,24 @@ impl<'a> ::Encoder for Encoder<'a> {
|
||||
f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
self.emit_enum_variant_arg(idx, f)
|
||||
}
|
||||
|
||||
fn emit_struct<F>(&mut self, _: &str, _: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
try!(write!(self.writer, "{{"));
|
||||
try!(f(self));
|
||||
write!(self.writer, "}}")
|
||||
try!(write!(self.writer, "}}"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_struct_field<F>(&mut self, name: &str, idx: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
if idx != 0 { try!(write!(self.writer, ",")); }
|
||||
try!(escape_str(self.writer, name));
|
||||
try!(write!(self.writer, ":"));
|
||||
@ -555,48 +598,60 @@ impl<'a> ::Encoder for Encoder<'a> {
|
||||
fn emit_tuple<F>(&mut self, len: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
self.emit_seq(len, f)
|
||||
}
|
||||
fn emit_tuple_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
self.emit_seq_elt(idx, f)
|
||||
}
|
||||
|
||||
fn emit_tuple_struct<F>(&mut self, _name: &str, len: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
self.emit_seq(len, f)
|
||||
}
|
||||
fn emit_tuple_struct_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
self.emit_seq_elt(idx, f)
|
||||
}
|
||||
|
||||
fn emit_option<F>(&mut self, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
f(self)
|
||||
}
|
||||
fn emit_option_none(&mut self) -> EncodeResult { self.emit_nil() }
|
||||
fn emit_option_none(&mut self) -> EncodeResult {
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
self.emit_nil()
|
||||
}
|
||||
fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
f(self)
|
||||
}
|
||||
|
||||
fn emit_seq<F>(&mut self, _len: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
try!(write!(self.writer, "["));
|
||||
try!(f(self));
|
||||
write!(self.writer, "]")
|
||||
try!(write!(self.writer, "]"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_seq_elt<F>(&mut self, idx: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
if idx != 0 {
|
||||
try!(write!(self.writer, ","));
|
||||
}
|
||||
@ -606,34 +661,28 @@ impl<'a> ::Encoder for Encoder<'a> {
|
||||
fn emit_map<F>(&mut self, _len: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
try!(write!(self.writer, "{{"));
|
||||
try!(f(self));
|
||||
write!(self.writer, "}}")
|
||||
try!(write!(self.writer, "}}"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_map_elt_key<F>(&mut self, idx: uint, mut f: F) -> EncodeResult where
|
||||
F: FnMut(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
if idx != 0 { try!(write!(self.writer, ",")) }
|
||||
// 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 = Vec::new();
|
||||
// FIXME(14302) remove the transmute and unsafe block.
|
||||
unsafe {
|
||||
let mut check_encoder = Encoder::new(&mut buf);
|
||||
try!(f(transmute(&mut check_encoder)));
|
||||
}
|
||||
let out = str::from_utf8(&buf[]).unwrap();
|
||||
let needs_wrapping = out.char_at(0) != '"' && out.char_at_reverse(out.len()) != '"';
|
||||
if needs_wrapping { try!(write!(self.writer, "\"")); }
|
||||
self.is_emitting_map_key = true;
|
||||
try!(f(self));
|
||||
if needs_wrapping { try!(write!(self.writer, "\"")); }
|
||||
self.is_emitting_map_key = false;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_map_elt_val<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
try!(write!(self.writer, ":"));
|
||||
f(self)
|
||||
}
|
||||
@ -645,12 +694,18 @@ pub struct PrettyEncoder<'a> {
|
||||
writer: &'a mut (fmt::Writer+'a),
|
||||
curr_indent: uint,
|
||||
indent: uint,
|
||||
is_emitting_map_key: bool,
|
||||
}
|
||||
|
||||
impl<'a> PrettyEncoder<'a> {
|
||||
/// Creates a new encoder whose output will be written to the specified writer
|
||||
pub fn new(writer: &'a mut fmt::Writer) -> PrettyEncoder<'a> {
|
||||
PrettyEncoder { writer: writer, curr_indent: 0, indent: 2, }
|
||||
PrettyEncoder {
|
||||
writer: writer,
|
||||
curr_indent: 0,
|
||||
indent: 2,
|
||||
is_emitting_map_key: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the number of spaces to indent for each level.
|
||||
@ -664,32 +719,38 @@ impl<'a> PrettyEncoder<'a> {
|
||||
}
|
||||
|
||||
impl<'a> ::Encoder for PrettyEncoder<'a> {
|
||||
type Error = fmt::Error;
|
||||
type Error = EncoderError;
|
||||
|
||||
fn emit_nil(&mut self) -> EncodeResult { write!(self.writer, "null") }
|
||||
fn emit_nil(&mut self) -> EncodeResult {
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
try!(write!(self.writer, "null"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_uint(&mut self, v: uint) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_u64(&mut self, v: u64) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_u32(&mut self, v: u32) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_u16(&mut self, v: u16) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_u8(&mut self, v: u8) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_uint(&mut self, v: uint) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_u8(&mut self, v: u8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
|
||||
fn emit_int(&mut self, v: int) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_i64(&mut self, v: i64) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_i32(&mut self, v: i32) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_i16(&mut self, v: i16) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_i8(&mut self, v: i8) -> EncodeResult { write!(self.writer, "{}", v) }
|
||||
fn emit_int(&mut self, v: int) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
fn emit_i8(&mut self, v: i8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
|
||||
fn emit_bool(&mut self, v: bool) -> EncodeResult {
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
if v {
|
||||
write!(self.writer, "true")
|
||||
try!(write!(self.writer, "true"));
|
||||
} else {
|
||||
write!(self.writer, "false")
|
||||
try!(write!(self.writer, "false"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_f64(&mut self, v: f64) -> EncodeResult {
|
||||
write!(self.writer, "{}", fmt_number_or_null(v))
|
||||
emit_enquoted_if_mapkey!(self, fmt_number_or_null(v))
|
||||
}
|
||||
fn emit_f32(&mut self, v: f32) -> EncodeResult {
|
||||
self.emit_f64(v as f64)
|
||||
@ -705,6 +766,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
|
||||
fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
f(self)
|
||||
}
|
||||
|
||||
@ -716,6 +778,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
|
||||
-> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
if cnt == 0 {
|
||||
escape_str(self.writer, name)
|
||||
} else {
|
||||
@ -735,13 +798,15 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
|
||||
self.curr_indent -= self.indent;
|
||||
try!(write!(self.writer, "]\n"));
|
||||
try!(spaces(self.writer, self.curr_indent));
|
||||
write!(self.writer, "}}")
|
||||
try!(write!(self.writer, "}}"));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_enum_variant_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
if idx != 0 {
|
||||
try!(write!(self.writer, ",\n"));
|
||||
}
|
||||
@ -756,6 +821,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
|
||||
f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
self.emit_enum_variant(name, id, cnt, f)
|
||||
}
|
||||
|
||||
@ -765,6 +831,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
|
||||
f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
self.emit_enum_variant_arg(idx, f)
|
||||
}
|
||||
|
||||
@ -772,8 +839,9 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
|
||||
fn emit_struct<F>(&mut self, _: &str, len: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
if len == 0 {
|
||||
write!(self.writer, "{{}}")
|
||||
try!(write!(self.writer, "{{}}"));
|
||||
} else {
|
||||
try!(write!(self.writer, "{{"));
|
||||
self.curr_indent += self.indent;
|
||||
@ -781,13 +849,15 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
|
||||
self.curr_indent -= self.indent;
|
||||
try!(write!(self.writer, "\n"));
|
||||
try!(spaces(self.writer, self.curr_indent));
|
||||
write!(self.writer, "}}")
|
||||
try!(write!(self.writer, "}}"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_struct_field<F>(&mut self, name: &str, idx: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
if idx == 0 {
|
||||
try!(write!(self.writer, "\n"));
|
||||
} else {
|
||||
@ -802,42 +872,52 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
|
||||
fn emit_tuple<F>(&mut self, len: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
self.emit_seq(len, f)
|
||||
}
|
||||
fn emit_tuple_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
self.emit_seq_elt(idx, f)
|
||||
}
|
||||
|
||||
fn emit_tuple_struct<F>(&mut self, _: &str, len: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
self.emit_seq(len, f)
|
||||
}
|
||||
fn emit_tuple_struct_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
self.emit_seq_elt(idx, f)
|
||||
}
|
||||
|
||||
fn emit_option<F>(&mut self, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
f(self)
|
||||
}
|
||||
fn emit_option_none(&mut self) -> EncodeResult { self.emit_nil() }
|
||||
fn emit_option_none(&mut self) -> EncodeResult {
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
self.emit_nil()
|
||||
}
|
||||
fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
f(self)
|
||||
}
|
||||
|
||||
fn emit_seq<F>(&mut self, len: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
if len == 0 {
|
||||
write!(self.writer, "[]")
|
||||
try!(write!(self.writer, "[]"));
|
||||
} else {
|
||||
try!(write!(self.writer, "["));
|
||||
self.curr_indent += self.indent;
|
||||
@ -845,13 +925,15 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
|
||||
self.curr_indent -= self.indent;
|
||||
try!(write!(self.writer, "\n"));
|
||||
try!(spaces(self.writer, self.curr_indent));
|
||||
write!(self.writer, "]")
|
||||
try!(write!(self.writer, "]"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_seq_elt<F>(&mut self, idx: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
if idx == 0 {
|
||||
try!(write!(self.writer, "\n"));
|
||||
} else {
|
||||
@ -864,8 +946,9 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
|
||||
fn emit_map<F>(&mut self, len: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
if len == 0 {
|
||||
write!(self.writer, "{{}}")
|
||||
try!(write!(self.writer, "{{}}"));
|
||||
} else {
|
||||
try!(write!(self.writer, "{{"));
|
||||
self.curr_indent += self.indent;
|
||||
@ -873,38 +956,31 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
|
||||
self.curr_indent -= self.indent;
|
||||
try!(write!(self.writer, "\n"));
|
||||
try!(spaces(self.writer, self.curr_indent));
|
||||
write!(self.writer, "}}")
|
||||
try!(write!(self.writer, "}}"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_map_elt_key<F>(&mut self, idx: uint, mut f: F) -> EncodeResult where
|
||||
F: FnMut(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
if idx == 0 {
|
||||
try!(write!(self.writer, "\n"));
|
||||
} else {
|
||||
try!(write!(self.writer, ",\n"));
|
||||
}
|
||||
try!(spaces(self.writer, self.curr_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 = Vec::new();
|
||||
// FIXME(14302) remove the transmute and unsafe block.
|
||||
unsafe {
|
||||
let mut check_encoder = PrettyEncoder::new(&mut buf);
|
||||
try!(f(transmute(&mut check_encoder)));
|
||||
}
|
||||
let out = str::from_utf8(&buf[]).unwrap();
|
||||
let needs_wrapping = out.char_at(0) != '"' && out.char_at_reverse(out.len()) != '"';
|
||||
if needs_wrapping { try!(write!(self.writer, "\"")); }
|
||||
self.is_emitting_map_key = true;
|
||||
try!(f(self));
|
||||
if needs_wrapping { try!(write!(self.writer, "\"")); }
|
||||
self.is_emitting_map_key = false;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_map_elt_val<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
|
||||
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
|
||||
{
|
||||
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
|
||||
try!(write!(self.writer, ": "));
|
||||
f(self)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user