Skip to content

Commit 4d217cc

Browse files
author
Oliver Schneider
committed
Allow reporting of json-encoder-errors and implement for bad hash map keys
1 parent 350a8f5 commit 4d217cc

File tree

1 file changed

+63
-36
lines changed

1 file changed

+63
-36
lines changed

src/libserialize/json.rs

+63-36
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,12 @@ pub enum DecoderError {
267267
ApplicationError(string::String)
268268
}
269269

270+
#[deriving(Clone, PartialEq, Show)]
271+
pub enum EncoderError {
272+
IoError(io::IoError),
273+
BadHashmapKey
274+
}
275+
270276
/// Returns a readable error string for a given error code.
271277
pub fn error_str(error: ErrorCode) -> &'static str {
272278
match error {
@@ -302,7 +308,7 @@ pub fn decode<T: ::Decodable<Decoder, DecoderError>>(s: &str) -> DecodeResult<T>
302308
}
303309

304310
/// Shortcut function to encode a `T` into a JSON `String`
305-
pub fn encode<'a, T: Encodable<Encoder<'a>, io::IoError>>(object: &T) -> string::String {
311+
pub fn encode<'a, T: Encodable<Encoder<'a>, EncoderError>>(object: &T) -> string::String {
306312
let buff = Encoder::buffer_encode(object);
307313
string::String::from_utf8(buff).unwrap()
308314
}
@@ -322,10 +328,19 @@ impl std::error::Error for DecoderError {
322328
fn detail(&self) -> Option<std::string::String> { Some(self.to_string()) }
323329
}
324330

325-
pub type EncodeResult = io::IoResult<()>;
331+
impl std::error::Error for EncoderError {
332+
fn description(&self) -> &str { "encoder error" }
333+
fn detail(&self) -> Option<std::string::String> { Some(self.to_string()) }
334+
}
335+
336+
impl std::error::FromError<io::IoError> for EncoderError {
337+
fn from_error(err: io::IoError) -> EncoderError { EncoderError::IoError(err) }
338+
}
339+
340+
pub type EncodeResult = Result<(), EncoderError>;
326341
pub type DecodeResult<T> = Result<T, DecoderError>;
327342

328-
pub fn escape_bytes(wr: &mut io::Writer, bytes: &[u8]) -> Result<(), io::IoError> {
343+
pub fn escape_bytes(wr: &mut io::Writer, bytes: &[u8]) -> EncodeResult {
329344
try!(wr.write_str("\""));
330345

331346
let mut start = 0;
@@ -383,20 +398,21 @@ pub fn escape_bytes(wr: &mut io::Writer, bytes: &[u8]) -> Result<(), io::IoError
383398
try!(wr.write(bytes[start..]));
384399
}
385400

386-
wr.write_str("\"")
401+
try!(wr.write_str("\""));
402+
Ok(())
387403
}
388404

389-
fn escape_str(writer: &mut io::Writer, v: &str) -> Result<(), io::IoError> {
405+
fn escape_str(writer: &mut io::Writer, v: &str) -> EncodeResult {
390406
escape_bytes(writer, v.as_bytes())
391407
}
392408

393-
fn escape_char(writer: &mut io::Writer, v: char) -> Result<(), io::IoError> {
409+
fn escape_char(writer: &mut io::Writer, v: char) -> EncodeResult {
394410
let mut buf = [0, .. 4];
395411
let len = v.encode_utf8(&mut buf).unwrap();
396412
escape_bytes(writer, buf[mut ..len])
397413
}
398414

399-
fn spaces(wr: &mut io::Writer, mut n: uint) -> Result<(), io::IoError> {
415+
fn spaces(wr: &mut io::Writer, mut n: uint) -> EncodeResult {
400416
const LEN: uint = 16;
401417
static BUF: [u8, ..LEN] = [b' ', ..LEN];
402418

@@ -406,10 +422,9 @@ fn spaces(wr: &mut io::Writer, mut n: uint) -> Result<(), io::IoError> {
406422
}
407423

408424
if n > 0 {
409-
wr.write(BUF[..n])
410-
} else {
411-
Ok(())
425+
try!(wr.write(BUF[..n]));
412426
}
427+
Ok(())
413428
}
414429

415430
fn fmt_number_or_null(v: f64) -> string::String {
@@ -441,7 +456,7 @@ impl<'a> Encoder<'a> {
441456
}
442457

443458
/// Encode the specified struct into a json [u8]
444-
pub fn buffer_encode<T: Encodable<Encoder<'a>, io::IoError>>(object: &T) -> Vec<u8> {
459+
pub fn buffer_encode<T: Encodable<Encoder<'a>, EncoderError>>(object: &T) -> Vec<u8> {
445460
//Serialize the object in a string using a writer
446461
let mut m = Vec::new();
447462
// FIXME(14302) remove the transmute and unsafe block.
@@ -458,15 +473,17 @@ macro_rules! emit_enquoted_if_mapkey {
458473
($enc:ident,$e:expr) => {
459474
if $enc.emitting_map_key == EmittingMapKeyState::Emitting {
460475
$enc.emitting_map_key = EmittingMapKeyState::EmittedValidMapKey;
461-
write!($enc.writer, "\"{}\"", $e)
476+
try!(write!($enc.writer, "\"{}\"", $e));
477+
Ok(())
462478
} else {
463-
write!($enc.writer, "{}", $e)
479+
try!(write!($enc.writer, "{}", $e));
480+
Ok(())
464481
}
465482
}
466483
}
467484

468-
impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
469-
fn emit_nil(&mut self) -> EncodeResult { write!(self.writer, "null") }
485+
impl<'a> ::Encoder<EncoderError> for Encoder<'a> {
486+
fn emit_nil(&mut self) -> EncodeResult { try!(write!(self.writer, "null")); Ok(()) }
470487

471488
fn emit_uint(&mut self, v: uint) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
472489
fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
@@ -482,10 +499,11 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
482499

483500
fn emit_bool(&mut self, v: bool) -> EncodeResult {
484501
if v {
485-
write!(self.writer, "true")
502+
try!(write!(self.writer, "true"));
486503
} else {
487-
write!(self.writer, "false")
504+
try!(write!(self.writer, "false"));
488505
}
506+
Ok(())
489507
}
490508

491509
fn emit_f64(&mut self, v: f64) -> EncodeResult {
@@ -527,7 +545,8 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
527545
try!(escape_str(self.writer, name));
528546
try!(write!(self.writer, ",\"fields\":["));
529547
try!(f(self));
530-
write!(self.writer, "]}}")
548+
try!(write!(self.writer, "]}}"));
549+
Ok(())
531550
}
532551
}
533552

@@ -564,7 +583,8 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
564583
{
565584
try!(write!(self.writer, "{{"));
566585
try!(f(self));
567-
write!(self.writer, "}}")
586+
try!(write!(self.writer, "}}"));
587+
Ok(())
568588
}
569589

570590
fn emit_struct_field<F>(&mut self, name: &str, idx: uint, f: F) -> EncodeResult where
@@ -615,7 +635,8 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
615635
{
616636
try!(write!(self.writer, "["));
617637
try!(f(self));
618-
write!(self.writer, "]")
638+
try!(write!(self.writer, "]"));
639+
Ok(())
619640
}
620641

621642
fn emit_seq_elt<F>(&mut self, idx: uint, f: F) -> EncodeResult where
@@ -632,7 +653,8 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
632653
{
633654
try!(write!(self.writer, "{{"));
634655
try!(f(self));
635-
write!(self.writer, "}}")
656+
try!(write!(self.writer, "}}"));
657+
Ok(())
636658
}
637659

638660
fn emit_map_elt_key<F>(&mut self, idx: uint, f: F) -> EncodeResult where
@@ -643,10 +665,10 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
643665
try!(f(self));
644666
if self.emitting_map_key == EmittingMapKeyState::EmittedValidMapKey {
645667
self.emitting_map_key = EmittingMapKeyState::NotEmitting;
668+
Ok(())
646669
} else {
647-
panic!("did not emit a valid map key, aborting encoding");
670+
Err(EncoderError::BadHashmapKey)
648671
}
649-
Ok(())
650672
}
651673

652674
fn emit_map_elt_val<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
@@ -687,8 +709,8 @@ impl<'a> PrettyEncoder<'a> {
687709
}
688710
}
689711

690-
impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
691-
fn emit_nil(&mut self) -> EncodeResult { write!(self.writer, "null") }
712+
impl<'a> ::Encoder<EncoderError> for PrettyEncoder<'a> {
713+
fn emit_nil(&mut self) -> EncodeResult { try!(write!(self.writer, "null")); Ok(()) }
692714

693715
fn emit_uint(&mut self, v: uint) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
694716
fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
@@ -704,10 +726,11 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
704726

705727
fn emit_bool(&mut self, v: bool) -> EncodeResult {
706728
if v {
707-
write!(self.writer, "true")
729+
try!(write!(self.writer, "true"));
708730
} else {
709-
write!(self.writer, "false")
731+
try!(write!(self.writer, "false"));
710732
}
733+
Ok(())
711734
}
712735

713736
fn emit_f64(&mut self, v: f64) -> EncodeResult {
@@ -759,7 +782,8 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
759782
self.curr_indent -= self.indent;
760783
try!(write!(self.writer, "]\n"));
761784
try!(spaces(self.writer, self.curr_indent));
762-
write!(self.writer, "}}")
785+
try!(write!(self.writer, "}}"));
786+
Ok(())
763787
}
764788
}
765789

@@ -797,16 +821,17 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
797821
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
798822
{
799823
if len == 0 {
800-
write!(self.writer, "{{}}")
824+
try!(write!(self.writer, "{{}}"));
801825
} else {
802826
try!(write!(self.writer, "{{"));
803827
self.curr_indent += self.indent;
804828
try!(f(self));
805829
self.curr_indent -= self.indent;
806830
try!(write!(self.writer, "\n"));
807831
try!(spaces(self.writer, self.curr_indent));
808-
write!(self.writer, "}}")
832+
try!(write!(self.writer, "}}"));
809833
}
834+
Ok(())
810835
}
811836

812837
fn emit_struct_field<F>(&mut self, name: &str, idx: uint, f: F) -> EncodeResult where
@@ -861,16 +886,17 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
861886
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
862887
{
863888
if len == 0 {
864-
write!(self.writer, "[]")
889+
try!(write!(self.writer, "[]"));
865890
} else {
866891
try!(write!(self.writer, "["));
867892
self.curr_indent += self.indent;
868893
try!(f(self));
869894
self.curr_indent -= self.indent;
870895
try!(write!(self.writer, "\n"));
871896
try!(spaces(self.writer, self.curr_indent));
872-
write!(self.writer, "]")
897+
try!(write!(self.writer, "]"));
873898
}
899+
Ok(())
874900
}
875901

876902
fn emit_seq_elt<F>(&mut self, idx: uint, f: F) -> EncodeResult where
@@ -889,16 +915,17 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
889915
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
890916
{
891917
if len == 0 {
892-
write!(self.writer, "{{}}")
918+
try!(write!(self.writer, "{{}}"));
893919
} else {
894920
try!(write!(self.writer, "{{"));
895921
self.curr_indent += self.indent;
896922
try!(f(self));
897923
self.curr_indent -= self.indent;
898924
try!(write!(self.writer, "\n"));
899925
try!(spaces(self.writer, self.curr_indent));
900-
write!(self.writer, "}}")
926+
try!(write!(self.writer, "}}"));
901927
}
928+
Ok(())
902929
}
903930

904931
fn emit_map_elt_key<F>(&mut self, idx: uint, f: F) -> EncodeResult where
@@ -914,10 +941,10 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
914941
try!(f(self));
915942
if self.emitting_map_key == EmittingMapKeyState::EmittedValidMapKey {
916943
self.emitting_map_key = EmittingMapKeyState::NotEmitting;
944+
Ok(())
917945
} else {
918-
panic!("did not emit a valid map key, aborting encoding");
946+
Err(EncoderError::BadHashmapKey)
919947
}
920-
Ok(())
921948
}
922949

923950
fn emit_map_elt_val<F>(&mut self, _idx: uint, f: F) -> EncodeResult where

0 commit comments

Comments
 (0)