Auto merge of #19490 - oli-obk:json_non_string_key_maps, r=alexcrichton

importing object type string key maps is still supported
writing them should be explicit, and can be done as follows

```rust
let some_tree_map : TreeMap<String, Json> = ...;
Json::Object(some_tree_map).to_writer(&mut writer);
```

related to #8335, #9028, #9142
This commit is contained in:
bors 2015-01-19 21:37:52 +00:00
commit 7f8c687fdf
3 changed files with 201 additions and 91 deletions

View File

@ -1059,8 +1059,8 @@ pub mod writer {
self.end_tag() self.end_tag()
} }
fn emit_map_elt_key<F>(&mut self, _idx: uint, mut f: F) -> EncodeResult where fn emit_map_elt_key<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
F: FnMut(&mut Encoder<'a, W>) -> EncodeResult, F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
{ {
try!(self.start_tag(EsMapKey as uint)); try!(self.start_tag(EsMapKey as uint));

View File

@ -202,7 +202,7 @@ use self::InternalStackElement::*;
use std; use std;
use std::collections::{HashMap, BTreeMap}; use std::collections::{HashMap, BTreeMap};
use std::{char, f64, fmt, io, num, str}; 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::{Float, Int};
use std::num::FpCategory as Fp; use std::num::FpCategory as Fp;
use std::str::FromStr; use std::str::FromStr;
@ -275,6 +275,12 @@ pub enum DecoderError {
ApplicationError(string::String) ApplicationError(string::String)
} }
#[derive(Copy, Show)]
pub enum EncoderError {
FmtError(fmt::Error),
BadHashmapKey,
}
/// Returns a readable error string for a given error code. /// Returns a readable error string for a given error code.
pub fn error_str(error: ErrorCode) -> &'static str { pub fn error_str(error: ErrorCode) -> &'static str {
match error { match error {
@ -334,10 +340,19 @@ impl std::error::Error for DecoderError {
fn detail(&self) -> Option<std::string::String> { Some(format!("{:?}", self)) } 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>; 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("\"")); try!(wr.write_str("\""));
let mut start = 0; 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..])); 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 mut buf = [0; 4];
let n = v.encode_utf8(&mut buf).unwrap(); let n = v.encode_utf8(&mut buf).unwrap();
let buf = unsafe { str::from_utf8_unchecked(&buf[..n]) }; let buf = unsafe { str::from_utf8_unchecked(&buf[..n]) };
escape_str(writer, buf) 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 = " "; const BUF: &'static str = " ";
while n >= BUF.len() { while n >= BUF.len() {
@ -414,10 +430,9 @@ fn spaces(wr: &mut fmt::Writer, mut n: uint) -> fmt::Result {
} }
if n > 0 { if n > 0 {
wr.write_str(&BUF[..n]) try!(wr.write_str(&BUF[..n]));
} else {
Ok(())
} }
Ok(())
} }
fn fmt_number_or_null(v: f64) -> string::String { 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. /// A structure for implementing serialization to JSON.
pub struct Encoder<'a> { pub struct Encoder<'a> {
writer: &'a mut (fmt::Writer+'a), writer: &'a mut (fmt::Writer+'a),
is_emitting_map_key: bool,
} }
impl<'a> Encoder<'a> { impl<'a> Encoder<'a> {
/// Creates a new JSON encoder whose output will be written to the writer /// Creates a new JSON encoder whose output will be written to the writer
/// specified. /// specified.
pub fn new(writer: &'a mut fmt::Writer) -> Encoder<'a> { 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> { 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_uint(&mut self, v: uint) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u64(&mut self, v: u64) -> EncodeResult { write!(self.writer, "{}", v) } fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u32(&mut self, v: u32) -> EncodeResult { write!(self.writer, "{}", v) } fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u16(&mut self, v: u16) -> EncodeResult { write!(self.writer, "{}", v) } fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u8(&mut self, v: u8) -> EncodeResult { write!(self.writer, "{}", 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_int(&mut self, v: int) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_i64(&mut self, v: i64) -> EncodeResult { write!(self.writer, "{}", v) } fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_i32(&mut self, v: i32) -> EncodeResult { write!(self.writer, "{}", v) } fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_i16(&mut self, v: i16) -> EncodeResult { write!(self.writer, "{}", v) } fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_i8(&mut self, v: i8) -> EncodeResult { write!(self.writer, "{}", v) } fn emit_i8(&mut self, v: i8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_bool(&mut self, v: bool) -> EncodeResult { fn emit_bool(&mut self, v: bool) -> EncodeResult {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if v { if v {
write!(self.writer, "true") try!(write!(self.writer, "true"));
} else { } else {
write!(self.writer, "false") try!(write!(self.writer, "false"));
} }
Ok(())
} }
fn emit_f64(&mut self, v: f64) -> EncodeResult { 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 { fn emit_f32(&mut self, v: f32) -> EncodeResult {
self.emit_f64(v as f64) 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 fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
f(self) f(self)
} }
@ -496,6 +531,7 @@ impl<'a> ::Encoder for Encoder<'a> {
// enums are encoded as strings or objects // enums are encoded as strings or objects
// Bunny => "Bunny" // Bunny => "Bunny"
// Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]} // Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]}
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if cnt == 0 { if cnt == 0 {
escape_str(self.writer, name) escape_str(self.writer, name)
} else { } else {
@ -503,13 +539,15 @@ impl<'a> ::Encoder for Encoder<'a> {
try!(escape_str(self.writer, name)); try!(escape_str(self.writer, name));
try!(write!(self.writer, ",\"fields\":[")); try!(write!(self.writer, ",\"fields\":["));
try!(f(self)); 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 fn emit_enum_variant_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if idx != 0 { if idx != 0 {
try!(write!(self.writer, ",")); try!(write!(self.writer, ","));
} }
@ -523,6 +561,7 @@ impl<'a> ::Encoder for Encoder<'a> {
f: F) -> EncodeResult where f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
self.emit_enum_variant(name, id, cnt, f) self.emit_enum_variant(name, id, cnt, f)
} }
@ -532,20 +571,24 @@ impl<'a> ::Encoder for Encoder<'a> {
f: F) -> EncodeResult where f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
self.emit_enum_variant_arg(idx, f) self.emit_enum_variant_arg(idx, f)
} }
fn emit_struct<F>(&mut self, _: &str, _: uint, f: F) -> EncodeResult where fn emit_struct<F>(&mut self, _: &str, _: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
try!(write!(self.writer, "{{")); try!(write!(self.writer, "{{"));
try!(f(self)); 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 fn emit_struct_field<F>(&mut self, name: &str, idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if idx != 0 { try!(write!(self.writer, ",")); } if idx != 0 { try!(write!(self.writer, ",")); }
try!(escape_str(self.writer, name)); try!(escape_str(self.writer, name));
try!(write!(self.writer, ":")); 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 fn emit_tuple<F>(&mut self, len: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
self.emit_seq(len, f) self.emit_seq(len, f)
} }
fn emit_tuple_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where fn emit_tuple_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
self.emit_seq_elt(idx, f) self.emit_seq_elt(idx, f)
} }
fn emit_tuple_struct<F>(&mut self, _name: &str, len: uint, f: F) -> EncodeResult where fn emit_tuple_struct<F>(&mut self, _name: &str, len: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
self.emit_seq(len, f) self.emit_seq(len, f)
} }
fn emit_tuple_struct_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where fn emit_tuple_struct_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
self.emit_seq_elt(idx, f) self.emit_seq_elt(idx, f)
} }
fn emit_option<F>(&mut self, f: F) -> EncodeResult where fn emit_option<F>(&mut self, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
f(self) 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 fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
f(self) f(self)
} }
fn emit_seq<F>(&mut self, _len: uint, f: F) -> EncodeResult where fn emit_seq<F>(&mut self, _len: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
try!(write!(self.writer, "[")); try!(write!(self.writer, "["));
try!(f(self)); try!(f(self));
write!(self.writer, "]") try!(write!(self.writer, "]"));
Ok(())
} }
fn emit_seq_elt<F>(&mut self, idx: uint, f: F) -> EncodeResult where fn emit_seq_elt<F>(&mut self, idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if idx != 0 { if idx != 0 {
try!(write!(self.writer, ",")); 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 fn emit_map<F>(&mut self, _len: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
try!(write!(self.writer, "{{")); try!(write!(self.writer, "{{"));
try!(f(self)); 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 fn emit_map_elt_key<F>(&mut self, idx: uint, f: F) -> EncodeResult where
F: FnMut(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if idx != 0 { try!(write!(self.writer, ",")) } if idx != 0 { try!(write!(self.writer, ",")) }
// ref #12967, make sure to wrap a key in double quotes, self.is_emitting_map_key = true;
// 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, "\"")); }
try!(f(self)); try!(f(self));
if needs_wrapping { try!(write!(self.writer, "\"")); } self.is_emitting_map_key = false;
Ok(()) Ok(())
} }
fn emit_map_elt_val<F>(&mut self, _idx: uint, f: F) -> EncodeResult where fn emit_map_elt_val<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult, F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
try!(write!(self.writer, ":")); try!(write!(self.writer, ":"));
f(self) f(self)
} }
@ -645,12 +694,18 @@ pub struct PrettyEncoder<'a> {
writer: &'a mut (fmt::Writer+'a), writer: &'a mut (fmt::Writer+'a),
curr_indent: uint, curr_indent: uint,
indent: uint, indent: uint,
is_emitting_map_key: bool,
} }
impl<'a> PrettyEncoder<'a> { impl<'a> PrettyEncoder<'a> {
/// Creates a new encoder whose output will be written to the specified writer /// Creates a new encoder whose output will be written to the specified writer
pub fn new(writer: &'a mut fmt::Writer) -> PrettyEncoder<'a> { 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. /// Set the number of spaces to indent for each level.
@ -664,32 +719,38 @@ impl<'a> PrettyEncoder<'a> {
} }
impl<'a> ::Encoder for 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_uint(&mut self, v: uint) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u64(&mut self, v: u64) -> EncodeResult { write!(self.writer, "{}", v) } fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u32(&mut self, v: u32) -> EncodeResult { write!(self.writer, "{}", v) } fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u16(&mut self, v: u16) -> EncodeResult { write!(self.writer, "{}", v) } fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u8(&mut self, v: u8) -> EncodeResult { write!(self.writer, "{}", 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_int(&mut self, v: int) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_i64(&mut self, v: i64) -> EncodeResult { write!(self.writer, "{}", v) } fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_i32(&mut self, v: i32) -> EncodeResult { write!(self.writer, "{}", v) } fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_i16(&mut self, v: i16) -> EncodeResult { write!(self.writer, "{}", v) } fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_i8(&mut self, v: i8) -> EncodeResult { write!(self.writer, "{}", v) } fn emit_i8(&mut self, v: i8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_bool(&mut self, v: bool) -> EncodeResult { fn emit_bool(&mut self, v: bool) -> EncodeResult {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if v { if v {
write!(self.writer, "true") try!(write!(self.writer, "true"));
} else { } else {
write!(self.writer, "false") try!(write!(self.writer, "false"));
} }
Ok(())
} }
fn emit_f64(&mut self, v: f64) -> EncodeResult { 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 { fn emit_f32(&mut self, v: f32) -> EncodeResult {
self.emit_f64(v as f64) 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 fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
f(self) f(self)
} }
@ -716,6 +778,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
-> EncodeResult where -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if cnt == 0 { if cnt == 0 {
escape_str(self.writer, name) escape_str(self.writer, name)
} else { } else {
@ -735,13 +798,15 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
self.curr_indent -= self.indent; self.curr_indent -= self.indent;
try!(write!(self.writer, "]\n")); try!(write!(self.writer, "]\n"));
try!(spaces(self.writer, self.curr_indent)); 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 fn emit_enum_variant_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if idx != 0 { if idx != 0 {
try!(write!(self.writer, ",\n")); try!(write!(self.writer, ",\n"));
} }
@ -756,6 +821,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
f: F) -> EncodeResult where f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
self.emit_enum_variant(name, id, cnt, f) self.emit_enum_variant(name, id, cnt, f)
} }
@ -765,6 +831,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
f: F) -> EncodeResult where f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
self.emit_enum_variant_arg(idx, f) 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 fn emit_struct<F>(&mut self, _: &str, len: uint, f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if len == 0 { if len == 0 {
write!(self.writer, "{{}}") try!(write!(self.writer, "{{}}"));
} else { } else {
try!(write!(self.writer, "{{")); try!(write!(self.writer, "{{"));
self.curr_indent += self.indent; self.curr_indent += self.indent;
@ -781,13 +849,15 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
self.curr_indent -= self.indent; self.curr_indent -= self.indent;
try!(write!(self.writer, "\n")); try!(write!(self.writer, "\n"));
try!(spaces(self.writer, self.curr_indent)); 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 fn emit_struct_field<F>(&mut self, name: &str, idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if idx == 0 { if idx == 0 {
try!(write!(self.writer, "\n")); try!(write!(self.writer, "\n"));
} else { } else {
@ -802,42 +872,52 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
fn emit_tuple<F>(&mut self, len: uint, f: F) -> EncodeResult where fn emit_tuple<F>(&mut self, len: uint, f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
self.emit_seq(len, f) self.emit_seq(len, f)
} }
fn emit_tuple_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where fn emit_tuple_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
self.emit_seq_elt(idx, f) self.emit_seq_elt(idx, f)
} }
fn emit_tuple_struct<F>(&mut self, _: &str, len: uint, f: F) -> EncodeResult where fn emit_tuple_struct<F>(&mut self, _: &str, len: uint, f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
self.emit_seq(len, f) self.emit_seq(len, f)
} }
fn emit_tuple_struct_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where fn emit_tuple_struct_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
self.emit_seq_elt(idx, f) self.emit_seq_elt(idx, f)
} }
fn emit_option<F>(&mut self, f: F) -> EncodeResult where fn emit_option<F>(&mut self, f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
f(self) 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 fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
f(self) f(self)
} }
fn emit_seq<F>(&mut self, len: uint, f: F) -> EncodeResult where fn emit_seq<F>(&mut self, len: uint, f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if len == 0 { if len == 0 {
write!(self.writer, "[]") try!(write!(self.writer, "[]"));
} else { } else {
try!(write!(self.writer, "[")); try!(write!(self.writer, "["));
self.curr_indent += self.indent; self.curr_indent += self.indent;
@ -845,13 +925,15 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
self.curr_indent -= self.indent; self.curr_indent -= self.indent;
try!(write!(self.writer, "\n")); try!(write!(self.writer, "\n"));
try!(spaces(self.writer, self.curr_indent)); 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 fn emit_seq_elt<F>(&mut self, idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if idx == 0 { if idx == 0 {
try!(write!(self.writer, "\n")); try!(write!(self.writer, "\n"));
} else { } else {
@ -864,8 +946,9 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
fn emit_map<F>(&mut self, len: uint, f: F) -> EncodeResult where fn emit_map<F>(&mut self, len: uint, f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if len == 0 { if len == 0 {
write!(self.writer, "{{}}") try!(write!(self.writer, "{{}}"));
} else { } else {
try!(write!(self.writer, "{{")); try!(write!(self.writer, "{{"));
self.curr_indent += self.indent; self.curr_indent += self.indent;
@ -873,38 +956,31 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
self.curr_indent -= self.indent; self.curr_indent -= self.indent;
try!(write!(self.writer, "\n")); try!(write!(self.writer, "\n"));
try!(spaces(self.writer, self.curr_indent)); 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 fn emit_map_elt_key<F>(&mut self, idx: uint, f: F) -> EncodeResult where
F: FnMut(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if idx == 0 { if idx == 0 {
try!(write!(self.writer, "\n")); try!(write!(self.writer, "\n"));
} else { } else {
try!(write!(self.writer, ",\n")); try!(write!(self.writer, ",\n"));
} }
try!(spaces(self.writer, self.curr_indent)); try!(spaces(self.writer, self.curr_indent));
// ref #12967, make sure to wrap a key in double quotes, self.is_emitting_map_key = true;
// 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, "\"")); }
try!(f(self)); try!(f(self));
if needs_wrapping { try!(write!(self.writer, "\"")); } self.is_emitting_map_key = false;
Ok(()) Ok(())
} }
fn emit_map_elt_val<F>(&mut self, _idx: uint, f: F) -> EncodeResult where fn emit_map_elt_val<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
{ {
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
try!(write!(self.writer, ": ")); try!(write!(self.writer, ": "));
f(self) f(self)
} }
@ -2436,7 +2512,10 @@ struct FormatShim<'a, 'b: 'a> {
impl<'a, 'b> fmt::Writer for FormatShim<'a, 'b> { impl<'a, 'b> fmt::Writer for FormatShim<'a, 'b> {
fn write_str(&mut self, s: &str) -> fmt::Result { fn write_str(&mut self, s: &str) -> fmt::Result {
self.inner.write_str(s) match self.inner.write_str(s) {
Ok(_) => Ok(()),
Err(_) => Err(fmt::Error)
}
} }
} }
@ -2445,7 +2524,10 @@ impl fmt::String for Json {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut shim = FormatShim { inner: f }; let mut shim = FormatShim { inner: f };
let mut encoder = Encoder::new(&mut shim); let mut encoder = Encoder::new(&mut shim);
self.encode(&mut encoder) match self.encode(&mut encoder) {
Ok(_) => Ok(()),
Err(_) => Err(fmt::Error)
}
} }
} }
@ -2454,7 +2536,10 @@ impl<'a> fmt::String for PrettyJson<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut shim = FormatShim { inner: f }; let mut shim = FormatShim { inner: f };
let mut encoder = PrettyEncoder::new(&mut shim); let mut encoder = PrettyEncoder::new(&mut shim);
self.inner.encode(&mut encoder) match self.inner.encode(&mut encoder) {
Ok(_) => Ok(()),
Err(_) => Err(fmt::Error)
}
} }
} }
@ -2463,7 +2548,10 @@ impl<'a, T: Encodable> fmt::String for AsJson<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut shim = FormatShim { inner: f }; let mut shim = FormatShim { inner: f };
let mut encoder = Encoder::new(&mut shim); let mut encoder = Encoder::new(&mut shim);
self.inner.encode(&mut encoder) match self.inner.encode(&mut encoder) {
Ok(_) => Ok(()),
Err(_) => Err(fmt::Error)
}
} }
} }
@ -2484,7 +2572,10 @@ impl<'a, T: Encodable> fmt::String for AsPrettyJson<'a, T> {
Some(n) => encoder.set_indent(n), Some(n) => encoder.set_indent(n),
None => {} None => {}
} }
self.inner.encode(&mut encoder) match self.inner.encode(&mut encoder) {
Ok(_) => Ok(()),
Err(_) => Err(fmt::Error)
}
} }
} }
@ -2507,7 +2598,7 @@ mod tests {
use super::DecoderError::*; use super::DecoderError::*;
use super::JsonEvent::*; use super::JsonEvent::*;
use super::{Json, from_str, DecodeResult, DecoderError, JsonEvent, Parser, use super::{Json, from_str, DecodeResult, DecoderError, JsonEvent, Parser,
StackElement, Stack, Decoder}; StackElement, Stack, Decoder, Encoder, EncoderError};
use std::{i64, u64, f32, f64, io}; use std::{i64, u64, f32, f64, io};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::num::Float; use std::num::Float;
@ -3816,6 +3907,25 @@ mod tests {
assert_eq!(None::<int>.to_json(), Null); assert_eq!(None::<int>.to_json(), Null);
} }
#[test]
fn test_encode_hashmap_with_arbitrary_key() {
use std::str::from_utf8;
use std::io::Writer;
use std::collections::HashMap;
use std::fmt;
#[derive(PartialEq, Eq, Hash, RustcEncodable)]
struct ArbitraryType(uint);
let mut hm: HashMap<ArbitraryType, bool> = HashMap::new();
hm.insert(ArbitraryType(1), true);
let mut mem_buf = Vec::new();
let mut encoder = Encoder::new(&mut mem_buf as &mut fmt::Writer);
let result = hm.encode(&mut encoder);
match result.unwrap_err() {
EncoderError::BadHashmapKey => (),
_ => panic!("expected bad hash map key")
}
}
#[bench] #[bench]
fn bench_streaming_small(b: &mut Bencher) { fn bench_streaming_small(b: &mut Bencher) {
b.iter( || { b.iter( || {

View File

@ -98,7 +98,7 @@ pub trait Encoder {
fn emit_map<F>(&mut self, len: uint, f: F) -> Result<(), Self::Error> fn emit_map<F>(&mut self, len: uint, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>; where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
fn emit_map_elt_key<F>(&mut self, idx: uint, f: F) -> Result<(), Self::Error> fn emit_map_elt_key<F>(&mut self, idx: uint, f: F) -> Result<(), Self::Error>
where F: FnMut(&mut Self) -> Result<(), Self::Error>; where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
fn emit_map_elt_val<F>(&mut self, idx: uint, f: F) -> Result<(), Self::Error> fn emit_map_elt_val<F>(&mut self, idx: uint, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>; where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
} }