]> git.lizzy.rs Git - rust.git/commitdiff
serialize: use Result
authorSean McArthur <sean.monstar@gmail.com>
Tue, 18 Mar 2014 17:58:26 +0000 (10:58 -0700)
committerSean McArthur <sean.monstar@gmail.com>
Fri, 28 Mar 2014 00:41:55 +0000 (17:41 -0700)
All of Decoder and Encoder's methods now return a Result.

Encodable.encode() and Decodable.decode() return a Result as well.

fixes #12292

27 files changed:
src/librustc/driver/driver.rs
src/librustc/metadata/decoder.rs
src/librustc/metadata/encoder.rs
src/librustc/middle/astencode.rs
src/librustdoc/lib.rs
src/libserialize/collection_impls.rs
src/libserialize/collection_impls_old.rs [new file with mode: 0644]
src/libserialize/ebml.rs
src/libserialize/ebml_old.rs [new file with mode: 0644]
src/libserialize/json.rs
src/libserialize/json_old.rs [new file with mode: 0644]
src/libserialize/lib.rs
src/libserialize/serialize.rs
src/libserialize/serialize_old.rs [new file with mode: 0644]
src/libsyntax/ast.rs
src/libsyntax/codemap.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/deriving/decodable.rs
src/libsyntax/ext/deriving/encodable.rs
src/libsyntax/owned_slice.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/token.rs
src/libtest/lib.rs
src/libuuid/lib.rs
src/libworkcache/lib.rs
src/test/run-pass/issue-4016.rs
src/test/run-pass/issue-4036.rs

index 9ee0bb4a107cde182efdad45ff2e5faa6828f71a..610764f17ad70f7d1cb3a6526d62c1ba69f6247f 100644 (file)
@@ -168,6 +168,18 @@ fn filestem(&self) -> ~str {
     }
 }
 
+// FIXME: remove unwrap_ after snapshot
+#[cfg(stage0)]
+fn unwrap_<T>(t: T) -> T {
+    t
+}
+
+#[cfg(not(stage0))]
+fn unwrap_<T, E>(r: Result<T, E>) -> T {
+    r.unwrap()
+}
+
+
 pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
     -> ast::Crate {
     let krate = time(sess.time_passes(), "parsing", (), |_| {
@@ -187,7 +199,8 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
     if sess.opts.debugging_opts & session::AST_JSON_NOEXPAND != 0 {
         let mut stdout = io::BufferedWriter::new(io::stdout());
         let mut json = json::PrettyEncoder::new(&mut stdout);
-        krate.encode(&mut json);
+        // unwrapping so IoError isn't ignored
+        unwrap_(krate.encode(&mut json));
     }
 
     if sess.show_span() {
@@ -262,7 +275,8 @@ pub fn phase_2_configure_and_expand(sess: &Session,
     if sess.opts.debugging_opts & session::AST_JSON != 0 {
         let mut stdout = io::BufferedWriter::new(io::stdout());
         let mut json = json::PrettyEncoder::new(&mut stdout);
-        krate.encode(&mut json);
+        // unwrapping so IoError isn't ignored
+        unwrap_(krate.encode(&mut json));
     }
 
     (krate, map)
index 0ea47d28551127e709ff1378c1301328806cbee0..f61e85f3f3f9db407fc1b5e2defa25400da25292 100644 (file)
 
 pub type Cmd = @crate_metadata;
 
+// FIXME: remove unwrap_ after a snapshot
+#[cfg(stage0)]
+fn unwrap_<T>(t: T) -> T {
+    t
+}
+
+#[cfg(not(stage0))]
+fn unwrap_<T, E>(r: Result<T, E>) -> T {
+    r.unwrap()
+}
+
 // A function that takes a def_id relative to the crate being searched and
 // returns a def_id relative to the compilation environment, i.e. if we hit a
 // def_id for an item defined in another crate, somebody needs to figure out
@@ -59,7 +70,7 @@ fn lookup_hash<'a>(d: ebml::Doc<'a>, eq_fn: |&[u8]| -> bool,
     let table = reader::get_doc(index, tag_index_table);
     let hash_pos = table.start + (hash % 256 * 4) as uint;
     let pos = u64_from_be_bytes(d.data, hash_pos, 4) as uint;
-    let tagged_doc = reader::doc_at(d.data, pos);
+    let tagged_doc = unwrap_(reader::doc_at(d.data, pos));
 
     let belt = tag_index_buckets_bucket_elt;
 
@@ -67,7 +78,7 @@ fn lookup_hash<'a>(d: ebml::Doc<'a>, eq_fn: |&[u8]| -> bool,
     reader::tagged_docs(tagged_doc.doc, belt, |elt| {
         let pos = u64_from_be_bytes(elt.data, elt.start, 4) as uint;
         if eq_fn(elt.data.slice(elt.start + 4, elt.end)) {
-            ret = Some(reader::doc_at(d.data, pos).doc);
+            ret = Some(unwrap_(reader::doc_at(d.data, pos)).doc);
             false
         } else {
             true
@@ -853,7 +864,7 @@ pub fn get_item_variances(cdata: Cmd, id: ast::NodeId) -> ty::ItemVariances {
     let item_doc = lookup_item(id, data);
     let variance_doc = reader::get_doc(item_doc, tag_item_variances);
     let mut decoder = reader::Decoder(variance_doc);
-    Decodable::decode(&mut decoder)
+    unwrap_(Decodable::decode(&mut decoder))
 }
 
 pub fn get_provided_trait_methods(intr: @IdentInterner, cdata: Cmd,
index be1a7abe51d02302d586f396006c4cbca68c490a..5b47f1f56216bbb0caf01c89a779db6079b0478e 100644 (file)
@@ -62,8 +62,15 @@ pub enum InlinedItemRef<'a> {
     IIForeignRef(&'a ast::ForeignItem)
 }
 
+// FIXME: remove this Encoder type after a snapshot
+#[cfg(stage0)]
+pub type Encoder<'a> = writer::Encoder<'a>;
+
+#[cfg(not(stage0))]
+pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
+
 pub type EncodeInlinedItem<'a> = 'a |ecx: &EncodeContext,
-                                     ebml_w: &mut writer::Encoder,
+                                     ebml_w: &mut Encoder,
                                      ii: InlinedItemRef|;
 
 pub struct EncodeParams<'a> {
@@ -106,15 +113,15 @@ pub struct EncodeContext<'a> {
     type_abbrevs: abbrev_map,
 }
 
-fn encode_name(ebml_w: &mut writer::Encoder, name: Name) {
+fn encode_name(ebml_w: &mut Encoder, name: Name) {
     ebml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
 }
 
-fn encode_impl_type_basename(ebml_w: &mut writer::Encoder, name: Ident) {
+fn encode_impl_type_basename(ebml_w: &mut Encoder, name: Ident) {
     ebml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
 }
 
-pub fn encode_def_id(ebml_w: &mut writer::Encoder, id: DefId) {
+pub fn encode_def_id(ebml_w: &mut Encoder, id: DefId) {
     ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
 }
 
@@ -124,7 +131,7 @@ struct entry<T> {
     pos: u64
 }
 
-fn encode_trait_ref(ebml_w: &mut writer::Encoder,
+fn encode_trait_ref(ebml_w: &mut Encoder,
                     ecx: &EncodeContext,
                     trait_ref: &ty::TraitRef,
                     tag: uint) {
@@ -140,7 +147,7 @@ fn encode_trait_ref(ebml_w: &mut writer::Encoder,
     ebml_w.end_tag();
 }
 
-fn encode_impl_vtables(ebml_w: &mut writer::Encoder,
+fn encode_impl_vtables(ebml_w: &mut Encoder,
                        ecx: &EncodeContext,
                        vtables: &typeck::impl_res) {
     ebml_w.start_tag(tag_item_impl_vtables);
@@ -150,7 +157,7 @@ fn encode_impl_vtables(ebml_w: &mut writer::Encoder,
 }
 
 // Item info table encoding
-fn encode_family(ebml_w: &mut writer::Encoder, c: char) {
+fn encode_family(ebml_w: &mut Encoder, c: char) {
     ebml_w.start_tag(tag_items_data_item_family);
     ebml_w.writer.write(&[c as u8]);
     ebml_w.end_tag();
@@ -160,7 +167,7 @@ pub fn def_to_str(did: DefId) -> ~str {
     format!("{}:{}", did.krate, did.node)
 }
 
-fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder,
+fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
                              ecx: &EncodeContext,
                              params: &[ty::TypeParameterDef],
                              tag: uint) {
@@ -177,7 +184,7 @@ fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder,
     }
 }
 
-fn encode_region_param_defs(ebml_w: &mut writer::Encoder,
+fn encode_region_param_defs(ebml_w: &mut Encoder,
                             params: &[ty::RegionParameterDef]) {
     for param in params.iter() {
         ebml_w.start_tag(tag_region_param_def);
@@ -193,7 +200,7 @@ fn encode_region_param_defs(ebml_w: &mut writer::Encoder,
     }
 }
 
-fn encode_item_variances(ebml_w: &mut writer::Encoder,
+fn encode_item_variances(ebml_w: &mut Encoder,
                          ecx: &EncodeContext,
                          id: ast::NodeId) {
     let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
@@ -202,7 +209,7 @@ fn encode_item_variances(ebml_w: &mut writer::Encoder,
     ebml_w.end_tag();
 }
 
-fn encode_bounds_and_type(ebml_w: &mut writer::Encoder,
+fn encode_bounds_and_type(ebml_w: &mut Encoder,
                           ecx: &EncodeContext,
                           tpt: &ty::ty_param_bounds_and_ty) {
     encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs(),
@@ -211,7 +218,7 @@ fn encode_bounds_and_type(ebml_w: &mut writer::Encoder,
     encode_type(ecx, ebml_w, tpt.ty);
 }
 
-fn encode_variant_id(ebml_w: &mut writer::Encoder, vid: DefId) {
+fn encode_variant_id(ebml_w: &mut Encoder, vid: DefId) {
     ebml_w.start_tag(tag_items_data_item_variant);
     let s = def_to_str(vid);
     ebml_w.writer.write(s.as_bytes());
@@ -219,7 +226,7 @@ fn encode_variant_id(ebml_w: &mut writer::Encoder, vid: DefId) {
 }
 
 pub fn write_type(ecx: &EncodeContext,
-                  ebml_w: &mut writer::Encoder,
+                  ebml_w: &mut Encoder,
                   typ: ty::t) {
     let ty_str_ctxt = &tyencode::ctxt {
         diag: ecx.diag,
@@ -231,7 +238,7 @@ pub fn write_type(ecx: &EncodeContext,
 }
 
 pub fn write_vstore(ecx: &EncodeContext,
-                    ebml_w: &mut writer::Encoder,
+                    ebml_w: &mut Encoder,
                     vstore: ty::vstore) {
     let ty_str_ctxt = &tyencode::ctxt {
         diag: ecx.diag,
@@ -243,7 +250,7 @@ pub fn write_vstore(ecx: &EncodeContext,
 }
 
 fn encode_type(ecx: &EncodeContext,
-               ebml_w: &mut writer::Encoder,
+               ebml_w: &mut Encoder,
                typ: ty::t) {
     ebml_w.start_tag(tag_items_data_item_type);
     write_type(ecx, ebml_w, typ);
@@ -251,7 +258,7 @@ fn encode_type(ecx: &EncodeContext,
 }
 
 fn encode_method_fty(ecx: &EncodeContext,
-                     ebml_w: &mut writer::Encoder,
+                     ebml_w: &mut Encoder,
                      typ: &ty::BareFnTy) {
     ebml_w.start_tag(tag_item_method_fty);
 
@@ -267,7 +274,7 @@ fn encode_method_fty(ecx: &EncodeContext,
 }
 
 fn encode_symbol(ecx: &EncodeContext,
-                 ebml_w: &mut writer::Encoder,
+                 ebml_w: &mut Encoder,
                  id: NodeId) {
     ebml_w.start_tag(tag_items_data_item_symbol);
     match ecx.item_symbols.borrow().find(&id) {
@@ -284,7 +291,7 @@ fn encode_symbol(ecx: &EncodeContext,
 }
 
 fn encode_disr_val(_: &EncodeContext,
-                   ebml_w: &mut writer::Encoder,
+                   ebml_w: &mut Encoder,
                    disr_val: ty::Disr) {
     ebml_w.start_tag(tag_disr_val);
     let s = disr_val.to_str();
@@ -292,14 +299,14 @@ fn encode_disr_val(_: &EncodeContext,
     ebml_w.end_tag();
 }
 
-fn encode_parent_item(ebml_w: &mut writer::Encoder, id: DefId) {
+fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
     ebml_w.start_tag(tag_items_data_parent_item);
     let s = def_to_str(id);
     ebml_w.writer.write(s.as_bytes());
     ebml_w.end_tag();
 }
 
-fn encode_struct_fields(ebml_w: &mut writer::Encoder,
+fn encode_struct_fields(ebml_w: &mut Encoder,
                         def: @StructDef) {
     for f in def.fields.iter() {
         match f.node.kind {
@@ -321,7 +328,7 @@ fn encode_struct_fields(ebml_w: &mut writer::Encoder,
 }
 
 fn encode_enum_variant_info(ecx: &EncodeContext,
-                            ebml_w: &mut writer::Encoder,
+                            ebml_w: &mut Encoder,
                             id: NodeId,
                             variants: &[P<Variant>],
                             index: @RefCell<Vec<entry<i64>> >,
@@ -378,7 +385,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
     }
 }
 
-fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut writer::Encoder,
+fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut Encoder,
                                                mut path: PI) {
     ebml_w.start_tag(tag_path);
     ebml_w.wr_tagged_u32(tag_path_len, path.clone().len() as u32);
@@ -392,7 +399,7 @@ fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut writer::Encoder,
     ebml_w.end_tag();
 }
 
-fn encode_reexported_static_method(ebml_w: &mut writer::Encoder,
+fn encode_reexported_static_method(ebml_w: &mut Encoder,
                                    exp: &middle::resolve::Export2,
                                    method_def_id: DefId,
                                    method_ident: Ident) {
@@ -409,7 +416,7 @@ fn encode_reexported_static_method(ebml_w: &mut writer::Encoder,
 }
 
 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
-                                         ebml_w: &mut writer::Encoder,
+                                         ebml_w: &mut Encoder,
                                          exp: &middle::resolve::Export2)
                                          -> bool {
     match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
@@ -429,7 +436,7 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
 }
 
 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
-                                          ebml_w: &mut writer::Encoder,
+                                          ebml_w: &mut Encoder,
                                           exp: &middle::resolve::Export2)
                                           -> bool {
     match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
@@ -447,7 +454,7 @@ fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
 }
 
 fn encode_reexported_static_methods(ecx: &EncodeContext,
-                                    ebml_w: &mut writer::Encoder,
+                                    ebml_w: &mut Encoder,
                                     mod_path: PathElems,
                                     exp: &middle::resolve::Export2) {
     match ecx.tcx.map.find(exp.def_id.node) {
@@ -527,7 +534,7 @@ fn each_auxiliary_node_id(item: @Item, callback: |NodeId| -> bool) -> bool {
 }
 
 fn encode_reexports(ecx: &EncodeContext,
-                    ebml_w: &mut writer::Encoder,
+                    ebml_w: &mut Encoder,
                     id: NodeId,
                     path: PathElems) {
     debug!("(encoding info for module) encoding reexports for {}", id);
@@ -560,7 +567,7 @@ fn encode_reexports(ecx: &EncodeContext,
 }
 
 fn encode_info_for_mod(ecx: &EncodeContext,
-                       ebml_w: &mut writer::Encoder,
+                       ebml_w: &mut Encoder,
                        md: &Mod,
                        id: NodeId,
                        path: PathElems,
@@ -613,7 +620,7 @@ fn encode_info_for_mod(ecx: &EncodeContext,
     ebml_w.end_tag();
 }
 
-fn encode_struct_field_family(ebml_w: &mut writer::Encoder,
+fn encode_struct_field_family(ebml_w: &mut Encoder,
                               visibility: Visibility) {
     encode_family(ebml_w, match visibility {
         Public => 'g',
@@ -622,7 +629,7 @@ fn encode_struct_field_family(ebml_w: &mut writer::Encoder,
     });
 }
 
-fn encode_visibility(ebml_w: &mut writer::Encoder, visibility: Visibility) {
+fn encode_visibility(ebml_w: &mut Encoder, visibility: Visibility) {
     ebml_w.start_tag(tag_items_data_item_visibility);
     let ch = match visibility {
         Public => 'y',
@@ -633,7 +640,7 @@ fn encode_visibility(ebml_w: &mut writer::Encoder, visibility: Visibility) {
     ebml_w.end_tag();
 }
 
-fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::ExplicitSelf_) {
+fn encode_explicit_self(ebml_w: &mut Encoder, explicit_self: ast::ExplicitSelf_) {
     ebml_w.start_tag(tag_item_trait_method_explicit_self);
 
     // Encode the base self type.
@@ -650,7 +657,7 @@ fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::Explic
 
     ebml_w.end_tag();
 
-    fn encode_mutability(ebml_w: &mut writer::Encoder,
+    fn encode_mutability(ebml_w: &mut Encoder,
                          m: ast::Mutability) {
         match m {
             MutImmutable => { ebml_w.writer.write(&[ 'i' as u8 ]); }
@@ -659,13 +666,13 @@ fn encode_mutability(ebml_w: &mut writer::Encoder,
     }
 }
 
-fn encode_method_sort(ebml_w: &mut writer::Encoder, sort: char) {
+fn encode_method_sort(ebml_w: &mut Encoder, sort: char) {
     ebml_w.start_tag(tag_item_trait_method_sort);
     ebml_w.writer.write(&[ sort as u8 ]);
     ebml_w.end_tag();
 }
 
-fn encode_provided_source(ebml_w: &mut writer::Encoder,
+fn encode_provided_source(ebml_w: &mut Encoder,
                           source_opt: Option<DefId>) {
     for source in source_opt.iter() {
         ebml_w.start_tag(tag_item_method_provided_source);
@@ -677,7 +684,7 @@ fn encode_provided_source(ebml_w: &mut writer::Encoder,
 
 /* Returns an index of items in this class */
 fn encode_info_for_struct(ecx: &EncodeContext,
-                          ebml_w: &mut writer::Encoder,
+                          ebml_w: &mut Encoder,
                           fields: &[StructField],
                           global_index: @RefCell<Vec<entry<i64>> >)
                           -> Vec<entry<i64>> {
@@ -712,7 +719,7 @@ fn encode_info_for_struct(ecx: &EncodeContext,
 }
 
 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
-                               ebml_w: &mut writer::Encoder,
+                               ebml_w: &mut Encoder,
                                name: ast::Ident,
                                ctor_id: NodeId,
                                index: @RefCell<Vec<entry<i64>> >,
@@ -746,7 +753,7 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext,
 }
 
 fn encode_method_ty_fields(ecx: &EncodeContext,
-                           ebml_w: &mut writer::Encoder,
+                           ebml_w: &mut Encoder,
                            method_ty: &ty::Method) {
     encode_def_id(ebml_w, method_ty.def_id);
     encode_name(ebml_w, method_ty.ident.name);
@@ -767,7 +774,7 @@ fn encode_method_ty_fields(ecx: &EncodeContext,
 }
 
 fn encode_info_for_method(ecx: &EncodeContext,
-                          ebml_w: &mut writer::Encoder,
+                          ebml_w: &mut Encoder,
                           m: &ty::Method,
                           impl_path: PathElems,
                           is_default_impl: bool,
@@ -836,7 +843,7 @@ fn should_inline(attrs: &[Attribute]) -> bool {
 
 // Encodes the inherent implementations of a structure, enumeration, or trait.
 fn encode_inherent_implementations(ecx: &EncodeContext,
-                                   ebml_w: &mut writer::Encoder,
+                                   ebml_w: &mut Encoder,
                                    def_id: DefId) {
     match ecx.tcx.inherent_impls.borrow().find(&def_id) {
         None => {}
@@ -852,7 +859,7 @@ fn encode_inherent_implementations(ecx: &EncodeContext,
 
 // Encodes the implementations of a trait defined in this crate.
 fn encode_extension_implementations(ecx: &EncodeContext,
-                                    ebml_w: &mut writer::Encoder,
+                                    ebml_w: &mut Encoder,
                                     trait_def_id: DefId) {
     match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
         None => {}
@@ -867,14 +874,14 @@ fn encode_extension_implementations(ecx: &EncodeContext,
 }
 
 fn encode_info_for_item(ecx: &EncodeContext,
-                        ebml_w: &mut writer::Encoder,
+                        ebml_w: &mut Encoder,
                         item: &Item,
                         index: @RefCell<Vec<entry<i64>> >,
                         path: PathElems,
                         vis: ast::Visibility) {
     let tcx = ecx.tcx;
 
-    fn add_to_index(item: &Item, ebml_w: &writer::Encoder,
+    fn add_to_index(item: &Item, ebml_w: &Encoder,
                      index: @RefCell<Vec<entry<i64>> >) {
         index.borrow_mut().push(entry {
             val: item.id as i64,
@@ -1211,7 +1218,7 @@ fn add_to_index(item: &Item, ebml_w: &writer::Encoder,
 }
 
 fn encode_info_for_foreign_item(ecx: &EncodeContext,
-                                ebml_w: &mut writer::Encoder,
+                                ebml_w: &mut Encoder,
                                 nitem: &ForeignItem,
                                 index: @RefCell<Vec<entry<i64>> >,
                                 path: PathElems,
@@ -1253,7 +1260,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
 fn my_visit_expr(_e: &Expr) { }
 
 fn my_visit_item(i: &Item,
-                 ebml_w: &mut writer::Encoder,
+                 ebml_w: &mut Encoder,
                  ecx_ptr: *int,
                  index: @RefCell<Vec<entry<i64>> >) {
     let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
@@ -1265,7 +1272,7 @@ fn my_visit_item(i: &Item,
 }
 
 fn my_visit_foreign_item(ni: &ForeignItem,
-                         ebml_w: &mut writer::Encoder,
+                         ebml_w: &mut Encoder,
                          ecx_ptr:*int,
                          index: @RefCell<Vec<entry<i64>> >) {
     // See above
@@ -1286,7 +1293,7 @@ fn my_visit_foreign_item(ni: &ForeignItem,
 }
 
 struct EncodeVisitor<'a,'b> {
-    ebml_w_for_visit_item: &'a mut writer::Encoder<'b>,
+    ebml_w_for_visit_item: &'a mut Encoder<'b>,
     ecx_ptr:*int,
     index: @RefCell<Vec<entry<i64>> >,
 }
@@ -1313,7 +1320,7 @@ fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
 }
 
 fn encode_info_for_items(ecx: &EncodeContext,
-                         ebml_w: &mut writer::Encoder,
+                         ebml_w: &mut Encoder,
                          krate: &Crate)
                          -> Vec<entry<i64>> {
     let index = @RefCell::new(Vec::new());
@@ -1369,7 +1376,7 @@ fn create_index<T:Clone + Hash + 'static>(
 }
 
 fn encode_index<T:'static>(
-                ebml_w: &mut writer::Encoder,
+                ebml_w: &mut Encoder,
                 buckets: Vec<@Vec<entry<T>> > ,
                 write_fn: |&mut MemWriter, &T|) {
     ebml_w.start_tag(tag_index);
@@ -1407,7 +1414,7 @@ fn write_i64(writer: &mut MemWriter, &n: &i64) {
     wr.write_be_u32(n as u32);
 }
 
-fn encode_meta_item(ebml_w: &mut writer::Encoder, mi: @MetaItem) {
+fn encode_meta_item(ebml_w: &mut Encoder, mi: @MetaItem) {
     match mi.node {
       MetaWord(ref name) => {
         ebml_w.start_tag(tag_meta_item_word);
@@ -1444,7 +1451,7 @@ fn encode_meta_item(ebml_w: &mut writer::Encoder, mi: @MetaItem) {
     }
 }
 
-fn encode_attributes(ebml_w: &mut writer::Encoder, attrs: &[Attribute]) {
+fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
     ebml_w.start_tag(tag_attributes);
     for attr in attrs.iter() {
         ebml_w.start_tag(tag_attribute);
@@ -1480,7 +1487,7 @@ fn synthesize_crateid_attr(ecx: &EncodeContext) -> Attribute {
     attrs
 }
 
-fn encode_crate_deps(ebml_w: &mut writer::Encoder, cstore: &cstore::CStore) {
+fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
     fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
         // Pull the cnums and name,vers,hash out of cstore
         let mut deps = Vec::new();
@@ -1518,7 +1525,7 @@ fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
     ebml_w.end_tag();
 }
 
-fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
+fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
     ebml_w.start_tag(tag_lang_items);
 
     for (i, def_id) in ecx.tcx.lang_items.items() {
@@ -1548,7 +1555,7 @@ fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
     ebml_w.end_tag();   // tag_lang_items
 }
 
-fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
+fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
     ebml_w.start_tag(tag_native_libraries);
 
     for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
@@ -1574,7 +1581,7 @@ fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
     ebml_w.end_tag();
 }
 
-fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
+fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
     match *ecx.tcx.sess.macro_registrar_fn.borrow() {
         Some(did) => {
             ebml_w.start_tag(tag_macro_registrar_fn);
@@ -1587,7 +1594,7 @@ fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut writer::Encoder)
 
 struct MacroDefVisitor<'a, 'b> {
     ecx: &'a EncodeContext<'a>,
-    ebml_w: &'a mut writer::Encoder<'b>
+    ebml_w: &'a mut Encoder<'b>
 }
 
 impl<'a, 'b> Visitor<()> for MacroDefVisitor<'a, 'b> {
@@ -1608,7 +1615,7 @@ fn visit_item(&mut self, item: &Item, _: ()) {
 
 fn encode_macro_defs(ecx: &EncodeContext,
                      krate: &Crate,
-                     ebml_w: &mut writer::Encoder) {
+                     ebml_w: &mut Encoder) {
     ebml_w.start_tag(tag_exported_macros);
     {
         let mut visitor = MacroDefVisitor {
@@ -1622,7 +1629,7 @@ fn encode_macro_defs(ecx: &EncodeContext,
 
 struct ImplVisitor<'a,'b> {
     ecx: &'a EncodeContext<'a>,
-    ebml_w: &'a mut writer::Encoder<'b>,
+    ebml_w: &'a mut Encoder<'b>,
 }
 
 impl<'a,'b> Visitor<()> for ImplVisitor<'a,'b> {
@@ -1660,7 +1667,7 @@ fn visit_item(&mut self, item: &Item, _: ()) {
 /// * Implementations of traits not defined in this crate.
 fn encode_impls(ecx: &EncodeContext,
                 krate: &Crate,
-                ebml_w: &mut writer::Encoder) {
+                ebml_w: &mut Encoder) {
     ebml_w.start_tag(tag_impls);
 
     {
@@ -1676,7 +1683,7 @@ fn encode_impls(ecx: &EncodeContext,
 
 fn encode_misc_info(ecx: &EncodeContext,
                     krate: &Crate,
-                    ebml_w: &mut writer::Encoder) {
+                    ebml_w: &mut Encoder) {
     ebml_w.start_tag(tag_misc_info);
     ebml_w.start_tag(tag_misc_info_crate_items);
     for &item in krate.module.items.iter() {
@@ -1699,7 +1706,7 @@ fn encode_misc_info(ecx: &EncodeContext,
     ebml_w.end_tag();
 }
 
-fn encode_crate_dep(ebml_w: &mut writer::Encoder,
+fn encode_crate_dep(ebml_w: &mut Encoder,
                     dep: decoder::CrateDep) {
     ebml_w.start_tag(tag_crate_dep);
     ebml_w.start_tag(tag_crate_dep_crateid);
@@ -1711,13 +1718,13 @@ fn encode_crate_dep(ebml_w: &mut writer::Encoder,
     ebml_w.end_tag();
 }
 
-fn encode_hash(ebml_w: &mut writer::Encoder, hash: &Svh) {
+fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
     ebml_w.start_tag(tag_crate_hash);
     ebml_w.writer.write(hash.as_str().as_bytes());
     ebml_w.end_tag();
 }
 
-fn encode_crate_id(ebml_w: &mut writer::Encoder, crate_id: &CrateId) {
+fn encode_crate_id(ebml_w: &mut Encoder, crate_id: &CrateId) {
     ebml_w.start_tag(tag_crate_crateid);
     ebml_w.writer.write(crate_id.to_str().as_bytes());
     ebml_w.end_tag();
index 94947b95cd38f9833e280b4e5d07a1d91e2dfc94..fd72a5f838a6e9463ca01e9fe415bc9c52f4861c 100644 (file)
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 #[allow(non_camel_case_types)];
+// FIXME: remove this after snapshot, and Results are handled
+#[allow(unused_must_use)];
 
 use c = metadata::common;
 use cstore = metadata::cstore;
@@ -36,6 +38,9 @@
 use std::cast;
 use std::cell::RefCell;
 use std::io::Seek;
+// FIXME: remove this attr after snapshot
+#[cfg(not(stage0))]
+use std::io::MemWriter;
 use std::rc::Rc;
 
 use serialize::ebml::reader;
@@ -76,11 +81,41 @@ trait tr_intern {
     fn tr_intern(&self, xcx: &ExtendedDecodeContext) -> ast::DefId;
 }
 
+// FIXME: remove this Encoder type after snapshot
+#[cfg(stage0)]
+pub type Encoder<'a> = writer::Encoder<'a>;
+
+#[cfg(not(stage0))]
+pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
+
+// FIXME: remove unwrap_ and wrap_ after snapshot
+#[cfg(stage0)]
+fn unwrap_<T>(t: T) -> T {
+    t
+}
+
+#[cfg(not(stage0))]
+fn unwrap_<T, E>(r: Result<T, E>) -> T {
+    r.unwrap()
+}
+
+#[cfg(stage0)]
+fn wrap_<T>(t: T) -> T {
+    t
+}
+
+#[cfg(not(stage0))]
+fn wrap_<T, E>(t: T) -> Result<T, E> {
+    Ok(t)
+}
+
+
+
 // ______________________________________________________________________
 // Top-level methods.
 
 pub fn encode_inlined_item(ecx: &e::EncodeContext,
-                           ebml_w: &mut writer::Encoder,
+                           ebml_w: &mut Encoder,
                            ii: e::InlinedItemRef,
                            maps: &Maps) {
     let id = match ii {
@@ -106,7 +141,7 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
            ebml_w.writer.tell());
 }
 
-pub fn encode_exported_macro(ebml_w: &mut writer::Encoder, i: &ast::Item) {
+pub fn encode_exported_macro(ebml_w: &mut Encoder, i: &ast::Item) {
     match i.node {
         ast::ItemMac(..) => encode_ast(ebml_w, ast::IIItem(@i.clone())),
         _ => fail!("expected a macro")
@@ -136,7 +171,7 @@ pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
             path_as_str.as_ref().map(|x| x.as_slice())
         });
         let mut ast_dsr = reader::Decoder(ast_doc);
-        let from_id_range = Decodable::decode(&mut ast_dsr);
+        let from_id_range = unwrap_(Decodable::decode(&mut ast_dsr));
         let to_id_range = reserve_id_range(&dcx.tcx.sess, from_id_range);
         let xcx = &ExtendedDecodeContext {
             dcx: dcx,
@@ -272,27 +307,50 @@ trait def_id_encoder_helpers {
     fn emit_def_id(&mut self, did: ast::DefId);
 }
 
+#[cfg(stage0)]
 impl<S:serialize::Encoder> def_id_encoder_helpers for S {
     fn emit_def_id(&mut self, did: ast::DefId) {
         did.encode(self)
     }
 }
 
+#[cfg(not(stage0))]
+impl<S:serialize::Encoder<E>, E> def_id_encoder_helpers for S {
+    fn emit_def_id(&mut self, did: ast::DefId) {
+        unwrap_(did.encode(self))
+    }
+}
+
 trait def_id_decoder_helpers {
     fn read_def_id(&mut self, xcx: &ExtendedDecodeContext) -> ast::DefId;
     fn read_def_id_noxcx(&mut self,
                          cdata: @cstore::crate_metadata) -> ast::DefId;
 }
 
+#[cfg(stage0)]
 impl<D:serialize::Decoder> def_id_decoder_helpers for D {
     fn read_def_id(&mut self, xcx: &ExtendedDecodeContext) -> ast::DefId {
-        let did: ast::DefId = Decodable::decode(self);
+        let did: ast::DefId = unwrap_(Decodable::decode(self));
         did.tr(xcx)
     }
 
     fn read_def_id_noxcx(&mut self,
                          cdata: @cstore::crate_metadata) -> ast::DefId {
-        let did: ast::DefId = Decodable::decode(self);
+        let did: ast::DefId = unwrap_(Decodable::decode(self));
+        decoder::translate_def_id(cdata, did)
+    }
+}
+
+#[cfg(not(stage0))]
+impl<D:serialize::Decoder<E>, E> def_id_decoder_helpers for D {
+    fn read_def_id(&mut self, xcx: &ExtendedDecodeContext) -> ast::DefId {
+        let did: ast::DefId = unwrap_(Decodable::decode(self));
+        did.tr(xcx)
+    }
+
+    fn read_def_id_noxcx(&mut self,
+                         cdata: @cstore::crate_metadata) -> ast::DefId {
+        let did: ast::DefId = unwrap_(Decodable::decode(self));
         decoder::translate_def_id(cdata, did)
     }
 }
@@ -312,7 +370,7 @@ fn read_def_id_noxcx(&mut self,
 // We also have to adjust the spans: for now we just insert a dummy span,
 // but eventually we should add entries to the local codemap as required.
 
-fn encode_ast(ebml_w: &mut writer::Encoder, item: ast::InlinedItem) {
+fn encode_ast(ebml_w: &mut Encoder, item: ast::InlinedItem) {
     ebml_w.start_tag(c::tag_tree as uint);
     item.encode(ebml_w);
     ebml_w.end_tag();
@@ -372,7 +430,7 @@ fn simplify_ast(ii: e::InlinedItemRef) -> ast::InlinedItem {
 fn decode_ast(par_doc: ebml::Doc) -> ast::InlinedItem {
     let chi_doc = par_doc.get(c::tag_tree as uint);
     let mut d = reader::Decoder(chi_doc);
-    Decodable::decode(&mut d)
+    unwrap_(Decodable::decode(&mut d))
 }
 
 struct AstRenumberer<'a> {
@@ -418,7 +476,7 @@ fn renumber_and_map_ast(xcx: &ExtendedDecodeContext,
 
 fn decode_def(xcx: &ExtendedDecodeContext, doc: ebml::Doc) -> ast::Def {
     let mut dsr = reader::Decoder(doc);
-    let def: ast::Def = Decodable::decode(&mut dsr);
+    let def: ast::Def = unwrap_(Decodable::decode(&mut dsr));
     def.tr(xcx)
 }
 
@@ -525,8 +583,8 @@ fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::BoundRegion {
 // ______________________________________________________________________
 // Encoding and decoding of freevar information
 
-fn encode_freevar_entry(ebml_w: &mut writer::Encoder, fv: @freevar_entry) {
-    (*fv).encode(ebml_w)
+fn encode_freevar_entry(ebml_w: &mut Encoder, fv: @freevar_entry) {
+    unwrap_((*fv).encode(ebml_w))
 }
 
 trait ebml_decoder_helper {
@@ -537,7 +595,7 @@ fn read_freevar_entry(&mut self, xcx: &ExtendedDecodeContext)
 impl<'a> ebml_decoder_helper for reader::Decoder<'a> {
     fn read_freevar_entry(&mut self, xcx: &ExtendedDecodeContext)
                           -> freevar_entry {
-        let fv: freevar_entry = Decodable::decode(self);
+        let fv: freevar_entry = unwrap_(Decodable::decode(self));
         fv.tr(xcx)
     }
 }
@@ -562,7 +620,7 @@ fn read_capture_var(&mut self, xcx: &ExtendedDecodeContext)
 impl<'a> capture_var_helper for reader::Decoder<'a> {
     fn read_capture_var(&mut self, xcx: &ExtendedDecodeContext)
                         -> moves::CaptureVar {
-        let cvar: moves::CaptureVar = Decodable::decode(self);
+        let cvar: moves::CaptureVar = unwrap_(Decodable::decode(self));
         cvar.tr(xcx)
     }
 }
@@ -585,45 +643,45 @@ trait read_method_callee_helper {
 }
 
 fn encode_method_callee(ecx: &e::EncodeContext,
-                        ebml_w: &mut writer::Encoder,
+                        ebml_w: &mut Encoder,
                         autoderef: u32,
                         method: &MethodCallee) {
-    ebml_w.emit_struct("MethodCallee", 4, |ebml_w| {
+    unwrap_(ebml_w.emit_struct("MethodCallee", 4, |ebml_w| {
         ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| {
-            autoderef.encode(ebml_w);
+            autoderef.encode(ebml_w)
         });
         ebml_w.emit_struct_field("origin", 1u, |ebml_w| {
-            method.origin.encode(ebml_w);
+            method.origin.encode(ebml_w)
         });
         ebml_w.emit_struct_field("ty", 2u, |ebml_w| {
-            ebml_w.emit_ty(ecx, method.ty);
+            wrap_(ebml_w.emit_ty(ecx, method.ty))
         });
         ebml_w.emit_struct_field("substs", 3u, |ebml_w| {
-            ebml_w.emit_substs(ecx, &method.substs);
-        });
-    })
+            wrap_(ebml_w.emit_substs(ecx, &method.substs))
+        })
+    }));
 }
 
 impl<'a> read_method_callee_helper for reader::Decoder<'a> {
     fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> (u32, MethodCallee) {
-        self.read_struct("MethodCallee", 4, |this| {
-            let autoderef = this.read_struct_field("autoderef", 0, |this| {
+        unwrap_(self.read_struct("MethodCallee", 4, |this| {
+            let autoderef = unwrap_(this.read_struct_field("autoderef", 0, |this| {
                 Decodable::decode(this)
-            });
-            (autoderef, MethodCallee {
-                origin: this.read_struct_field("origin", 1, |this| {
+            }));
+            wrap_((autoderef, MethodCallee {
+                origin: unwrap_(this.read_struct_field("origin", 1, |this| {
                     let method_origin: MethodOrigin =
-                        Decodable::decode(this);
-                    method_origin.tr(xcx)
-                }),
-                ty: this.read_struct_field("ty", 2, |this| {
-                    this.read_ty(xcx)
-                }),
-                substs: this.read_struct_field("substs", 3, |this| {
-                    this.read_substs(xcx)
-                })
-            })
-        })
+                        unwrap_(Decodable::decode(this));
+                    wrap_(method_origin.tr(xcx))
+                })),
+                ty: unwrap_(this.read_struct_field("ty", 2, |this| {
+                    wrap_(this.read_ty(xcx))
+                })),
+                substs: unwrap_(this.read_struct_field("substs", 3, |this| {
+                    wrap_(this.read_substs(xcx))
+                }))
+            }))
+        }))
     }
 }
 
@@ -655,70 +713,70 @@ fn tr(&self, xcx: &ExtendedDecodeContext) -> MethodOrigin {
 // Encoding and decoding vtable_res
 
 fn encode_vtable_res_with_key(ecx: &e::EncodeContext,
-                              ebml_w: &mut writer::Encoder,
+                              ebml_w: &mut Encoder,
                               autoderef: u32,
                               dr: typeck::vtable_res) {
-    ebml_w.emit_struct("VtableWithKey", 2, |ebml_w| {
+    unwrap_(ebml_w.emit_struct("VtableWithKey", 2, |ebml_w| {
         ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| {
-            autoderef.encode(ebml_w);
+            autoderef.encode(ebml_w)
         });
         ebml_w.emit_struct_field("vtable_res", 1u, |ebml_w| {
-            encode_vtable_res(ecx, ebml_w, dr);
-        });
-    })
+            wrap_(encode_vtable_res(ecx, ebml_w, dr))
+        })
+    }))
 }
 
 pub fn encode_vtable_res(ecx: &e::EncodeContext,
-                     ebml_w: &mut writer::Encoder,
+                     ebml_w: &mut Encoder,
                      dr: typeck::vtable_res) {
     // can't autogenerate this code because automatic code of
     // ty::t doesn't work, and there is no way (atm) to have
     // hand-written encoding routines combine with auto-generated
     // ones.  perhaps we should fix this.
-    ebml_w.emit_from_vec(dr.as_slice(), |ebml_w, param_tables| {
-        encode_vtable_param_res(ecx, ebml_w, *param_tables);
-    })
+    unwrap_(ebml_w.emit_from_vec(dr.as_slice(), |ebml_w, param_tables| {
+        wrap_(encode_vtable_param_res(ecx, ebml_w, *param_tables))
+    }))
 }
 
 pub fn encode_vtable_param_res(ecx: &e::EncodeContext,
-                     ebml_w: &mut writer::Encoder,
+                     ebml_w: &mut Encoder,
                      param_tables: typeck::vtable_param_res) {
-    ebml_w.emit_from_vec(param_tables.as_slice(), |ebml_w, vtable_origin| {
-        encode_vtable_origin(ecx, ebml_w, vtable_origin)
-    })
+    unwrap_(ebml_w.emit_from_vec(param_tables.as_slice(), |ebml_w, vtable_origin| {
+        wrap_(encode_vtable_origin(ecx, ebml_w, vtable_origin))
+    }))
 }
 
 
 pub fn encode_vtable_origin(ecx: &e::EncodeContext,
-                        ebml_w: &mut writer::Encoder,
+                        ebml_w: &mut Encoder,
                         vtable_origin: &typeck::vtable_origin) {
-    ebml_w.emit_enum("vtable_origin", |ebml_w| {
+    unwrap_(ebml_w.emit_enum("vtable_origin", |ebml_w| {
         match *vtable_origin {
           typeck::vtable_static(def_id, ref tys, vtable_res) => {
             ebml_w.emit_enum_variant("vtable_static", 0u, 3u, |ebml_w| {
                 ebml_w.emit_enum_variant_arg(0u, |ebml_w| {
-                    ebml_w.emit_def_id(def_id)
+                    wrap_(ebml_w.emit_def_id(def_id))
                 });
                 ebml_w.emit_enum_variant_arg(1u, |ebml_w| {
-                    ebml_w.emit_tys(ecx, tys.as_slice());
+                    wrap_(ebml_w.emit_tys(ecx, tys.as_slice()))
                 });
                 ebml_w.emit_enum_variant_arg(2u, |ebml_w| {
-                    encode_vtable_res(ecx, ebml_w, vtable_res);
+                    wrap_(encode_vtable_res(ecx, ebml_w, vtable_res))
                 })
             })
           }
           typeck::vtable_param(pn, bn) => {
             ebml_w.emit_enum_variant("vtable_param", 1u, 2u, |ebml_w| {
                 ebml_w.emit_enum_variant_arg(0u, |ebml_w| {
-                    pn.encode(ebml_w);
+                    pn.encode(ebml_w)
                 });
                 ebml_w.emit_enum_variant_arg(1u, |ebml_w| {
-                    ebml_w.emit_uint(bn);
+                    ebml_w.emit_uint(bn)
                 })
             })
           }
         }
-    })
+    }))
 }
 
 pub trait vtable_decoder_helpers {
@@ -742,21 +800,21 @@ fn read_vtable_res_with_key(&mut self,
                                 tcx: &ty::ctxt,
                                 cdata: @cstore::crate_metadata)
                                 -> (u32, typeck::vtable_res) {
-        self.read_struct("VtableWithKey", 2, |this| {
-            let autoderef = this.read_struct_field("autoderef", 0, |this| {
+        unwrap_(self.read_struct("VtableWithKey", 2, |this| {
+            let autoderef = unwrap_(this.read_struct_field("autoderef", 0, |this| {
                 Decodable::decode(this)
-            });
-            (autoderef, this.read_struct_field("vtable_res", 1, |this| {
-                this.read_vtable_res(tcx, cdata)
-            }))
-        })
+            }));
+            wrap_((autoderef, unwrap_(this.read_struct_field("vtable_res", 1, |this| {
+                wrap_(this.read_vtable_res(tcx, cdata))
+            }))))
+        }))
     }
 
     fn read_vtable_res(&mut self,
                        tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
                       -> typeck::vtable_res {
-        @self.read_to_vec(|this|
-                          this.read_vtable_param_res(tcx, cdata))
+        @unwrap_(self.read_to_vec(|this|
+                          wrap_(this.read_vtable_param_res(tcx, cdata))))
              .move_iter()
              .collect()
     }
@@ -764,8 +822,8 @@ fn read_vtable_res(&mut self,
     fn read_vtable_param_res(&mut self,
                              tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
                       -> typeck::vtable_param_res {
-        @self.read_to_vec(|this|
-                          this.read_vtable_origin(tcx, cdata))
+        @unwrap_(self.read_to_vec(|this|
+                          wrap_(this.read_vtable_origin(tcx, cdata))))
              .move_iter()
              .collect()
     }
@@ -773,40 +831,40 @@ fn read_vtable_param_res(&mut self,
     fn read_vtable_origin(&mut self,
                           tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
         -> typeck::vtable_origin {
-        self.read_enum("vtable_origin", |this| {
+        unwrap_(self.read_enum("vtable_origin", |this| {
             this.read_enum_variant(["vtable_static",
                                     "vtable_param",
                                     "vtable_self"],
                                    |this, i| {
-                match i {
+                wrap_(match i {
                   0 => {
                     typeck::vtable_static(
-                        this.read_enum_variant_arg(0u, |this| {
-                            this.read_def_id_noxcx(cdata)
-                        }),
-                        this.read_enum_variant_arg(1u, |this| {
-                            this.read_tys_noxcx(tcx, cdata)
-                        }),
-                        this.read_enum_variant_arg(2u, |this| {
-                            this.read_vtable_res(tcx, cdata)
-                        })
+                        unwrap_(this.read_enum_variant_arg(0u, |this| {
+                            wrap_(this.read_def_id_noxcx(cdata))
+                        })),
+                        unwrap_(this.read_enum_variant_arg(1u, |this| {
+                            wrap_(this.read_tys_noxcx(tcx, cdata))
+                        })),
+                        unwrap_(this.read_enum_variant_arg(2u, |this| {
+                            wrap_(this.read_vtable_res(tcx, cdata))
+                        }))
                     )
                   }
                   1 => {
                     typeck::vtable_param(
-                        this.read_enum_variant_arg(0u, |this| {
+                        unwrap_(this.read_enum_variant_arg(0u, |this| {
                             Decodable::decode(this)
-                        }),
-                        this.read_enum_variant_arg(1u, |this| {
+                        })),
+                        unwrap_(this.read_enum_variant_arg(1u, |this| {
                             this.read_uint()
-                        })
+                        }))
                     )
                   }
                   // hard to avoid - user input
                   _ => fail!("bad enum variant")
-                }
+                })
             })
-        })
+        }))
     }
 }
 
@@ -842,27 +900,27 @@ fn emit_tpbt(&mut self,
     fn emit_auto_adjustment(&mut self, ecx: &e::EncodeContext, adj: &ty::AutoAdjustment);
 }
 
-impl<'a> ebml_writer_helpers for writer::Encoder<'a> {
+impl<'a> ebml_writer_helpers for Encoder<'a> {
     fn emit_ty(&mut self, ecx: &e::EncodeContext, ty: ty::t) {
-        self.emit_opaque(|this| e::write_type(ecx, this, ty))
+        self.emit_opaque(|this| wrap_(e::write_type(ecx, this, ty)));
     }
 
     fn emit_vstore(&mut self, ecx: &e::EncodeContext, vstore: ty::vstore) {
-        self.emit_opaque(|this| e::write_vstore(ecx, this, vstore))
+        self.emit_opaque(|this| wrap_(e::write_vstore(ecx, this, vstore)));
     }
 
     fn emit_tys(&mut self, ecx: &e::EncodeContext, tys: &[ty::t]) {
-        self.emit_from_vec(tys, |this, ty| this.emit_ty(ecx, *ty))
+        self.emit_from_vec(tys, |this, ty| wrap_(this.emit_ty(ecx, *ty)));
     }
 
     fn emit_type_param_def(&mut self,
                            ecx: &e::EncodeContext,
                            type_param_def: &ty::TypeParameterDef) {
         self.emit_opaque(|this| {
-            tyencode::enc_type_param_def(this.writer,
+            wrap_(tyencode::enc_type_param_def(this.writer,
                                          &ecx.ty_str_ctxt(),
-                                         type_param_def)
-        })
+                                         type_param_def))
+        });
     }
 
     fn emit_tpbt(&mut self,
@@ -874,22 +932,24 @@ fn emit_tpbt(&mut self,
                     this.emit_struct_field("type_param_defs", 0, |this| {
                         this.emit_from_vec(tpbt.generics.type_param_defs(),
                                            |this, type_param_def| {
-                            this.emit_type_param_def(ecx, type_param_def);
+                            wrap_(this.emit_type_param_def(ecx, type_param_def))
                         })
                     });
                     this.emit_struct_field("region_param_defs", 1, |this| {
-                        tpbt.generics.region_param_defs().encode(this);
+                        tpbt.generics.region_param_defs().encode(this)
                     })
                 })
             });
             this.emit_struct_field("ty", 1, |this| {
-                this.emit_ty(ecx, tpbt.ty);
+                wrap_(this.emit_ty(ecx, tpbt.ty))
             })
-        })
+        });
     }
 
     fn emit_substs(&mut self, ecx: &e::EncodeContext, substs: &ty::substs) {
-        self.emit_opaque(|this| tyencode::enc_substs(this.writer, &ecx.ty_str_ctxt(), substs))
+        self.emit_opaque(|this| wrap_(tyencode::enc_substs(this.writer,
+                                                           &ecx.ty_str_ctxt(),
+                                                           substs)));
     }
 
     fn emit_auto_adjustment(&mut self, ecx: &e::EncodeContext, adj: &ty::AutoAdjustment) {
@@ -898,14 +958,14 @@ fn emit_auto_adjustment(&mut self, ecx: &e::EncodeContext, adj: &ty::AutoAdjustm
                 ty::AutoAddEnv(region, sigil) => {
                     this.emit_enum_variant("AutoAddEnv", 0, 2, |this| {
                         this.emit_enum_variant_arg(0, |this| region.encode(this));
-                        this.emit_enum_variant_arg(1, |this| sigil.encode(this));
-                    });
+                        this.emit_enum_variant_arg(1, |this| sigil.encode(this))
+                    })
                 }
 
                 ty::AutoDerefRef(ref auto_deref_ref) => {
                     this.emit_enum_variant("AutoDerefRef", 1, 1, |this| {
-                        this.emit_enum_variant_arg(0, |this| auto_deref_ref.encode(this));
-                    });
+                        this.emit_enum_variant_arg(0, |this| auto_deref_ref.encode(this))
+                    })
                 }
 
                 ty::AutoObject(sigil, region, m, b, def_id, ref substs) => {
@@ -915,8 +975,8 @@ fn emit_auto_adjustment(&mut self, ecx: &e::EncodeContext, adj: &ty::AutoAdjustm
                         this.emit_enum_variant_arg(2, |this| m.encode(this));
                         this.emit_enum_variant_arg(3, |this| b.encode(this));
                         this.emit_enum_variant_arg(4, |this| def_id.encode(this));
-                        this.emit_enum_variant_arg(5, |this| this.emit_substs(ecx, substs));
-                    });
+                        this.emit_enum_variant_arg(5, |this| wrap_(this.emit_substs(ecx, substs)))
+                    })
                 }
             }
         });
@@ -928,23 +988,23 @@ trait write_tag_and_id {
     fn id(&mut self, id: ast::NodeId);
 }
 
-impl<'a> write_tag_and_id for writer::Encoder<'a> {
+impl<'a> write_tag_and_id for Encoder<'a> {
     fn tag(&mut self,
            tag_id: c::astencode_tag,
-           f: |&mut writer::Encoder<'a>|) {
+           f: |&mut Encoder<'a>|) {
         self.start_tag(tag_id as uint);
         f(self);
         self.end_tag();
     }
 
     fn id(&mut self, id: ast::NodeId) {
-        self.wr_tagged_u64(c::tag_table_id as uint, id as u64)
+        self.wr_tagged_u64(c::tag_table_id as uint, id as u64);
     }
 }
 
 struct SideTableEncodingIdVisitor<'a,'b> {
     ecx_ptr: *libc::c_void,
-    new_ebml_w: &'a mut writer::Encoder<'b>,
+    new_ebml_w: &'a mut Encoder<'b>,
     maps: &'a Maps,
 }
 
@@ -969,7 +1029,7 @@ fn visit_id(&self, id: ast::NodeId) {
 
 fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
                              maps: &Maps,
-                             ebml_w: &mut writer::Encoder,
+                             ebml_w: &mut Encoder,
                              ii: &ast::InlinedItem) {
     ebml_w.start_tag(c::tag_table as uint);
     let mut new_ebml_w = unsafe {
@@ -991,7 +1051,7 @@ fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
 
 fn encode_side_tables_for_id(ecx: &e::EncodeContext,
                              maps: &Maps,
-                             ebml_w: &mut writer::Encoder,
+                             ebml_w: &mut Encoder,
                              id: ast::NodeId) {
     let tcx = ecx.tcx;
 
@@ -1000,7 +1060,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
     for def in tcx.def_map.borrow().find(&id).iter() {
         ebml_w.tag(c::tag_table_def, |ebml_w| {
             ebml_w.id(id);
-            ebml_w.tag(c::tag_table_val, |ebml_w| (*def).encode(ebml_w));
+            ebml_w.tag(c::tag_table_val, |ebml_w| unwrap_((*def).encode(ebml_w)));
         })
     }
 
@@ -1027,8 +1087,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
             ebml_w.id(id);
             ebml_w.tag(c::tag_table_val, |ebml_w| {
                 ebml_w.emit_from_vec(fv.as_slice(), |ebml_w, fv_entry| {
-                    encode_freevar_entry(ebml_w, *fv_entry)
-                })
+                    wrap_(encode_freevar_entry(ebml_w, *fv_entry))
+                });
             })
         })
     }
@@ -1112,8 +1172,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
             ebml_w.id(id);
             ebml_w.tag(c::tag_table_val, |ebml_w| {
                 ebml_w.emit_from_vec(cap_vars.as_slice(), |ebml_w, cap_var| {
-                    cap_var.encode(ebml_w);
-                })
+                    cap_var.encode(ebml_w)
+                });
             })
         })
     }
@@ -1158,20 +1218,20 @@ fn read_tys_noxcx(&mut self,
 impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
     fn read_ty_noxcx(&mut self,
                      tcx: &ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t {
-        self.read_opaque(|_, doc| {
-            tydecode::parse_ty_data(
+        unwrap_(self.read_opaque(|_, doc| {
+            wrap_(tydecode::parse_ty_data(
                 doc.data,
                 cdata.cnum,
                 doc.start,
                 tcx,
-                |_, id| decoder::translate_def_id(cdata, id))
-        })
+                |_, id| decoder::translate_def_id(cdata, id)))
+        }))
     }
 
     fn read_tys_noxcx(&mut self,
                       tcx: &ty::ctxt,
                       cdata: @cstore::crate_metadata) -> Vec<ty::t> {
-        self.read_to_vec(|this| this.read_ty_noxcx(tcx, cdata) )
+        unwrap_(self.read_to_vec(|this| wrap_(this.read_ty_noxcx(tcx, cdata)) ))
             .move_iter()
             .collect()
     }
@@ -1182,7 +1242,7 @@ fn read_ty(&mut self, xcx: &ExtendedDecodeContext) -> ty::t {
         // context.  However, we do not bother, because region types
         // are not used during trans.
 
-        return self.read_opaque(|this, doc| {
+        return unwrap_(self.read_opaque(|this, doc| {
             debug!("read_ty({})", type_string(doc));
 
             let ty = tydecode::parse_ty_data(
@@ -1192,8 +1252,8 @@ fn read_ty(&mut self, xcx: &ExtendedDecodeContext) -> ty::t {
                 xcx.dcx.tcx,
                 |s, a| this.convert_def_id(xcx, s, a));
 
-            ty
-        });
+            wrap_(ty)
+        }));
 
         fn type_string(doc: ebml::Doc) -> ~str {
             let mut str = ~"";
@@ -1205,94 +1265,95 @@ fn type_string(doc: ebml::Doc) -> ~str {
     }
 
     fn read_tys(&mut self, xcx: &ExtendedDecodeContext) -> Vec<ty::t> {
-        self.read_to_vec(|this| this.read_ty(xcx)).move_iter().collect()
+        unwrap_(self.read_to_vec(|this| wrap_(this.read_ty(xcx)))).move_iter().collect()
     }
 
     fn read_type_param_def(&mut self, xcx: &ExtendedDecodeContext)
                            -> ty::TypeParameterDef {
-        self.read_opaque(|this, doc| {
-            tydecode::parse_type_param_def_data(
+        unwrap_(self.read_opaque(|this, doc| {
+            wrap_(tydecode::parse_type_param_def_data(
                 doc.data,
                 doc.start,
                 xcx.dcx.cdata.cnum,
                 xcx.dcx.tcx,
-                |s, a| this.convert_def_id(xcx, s, a))
-        })
+                |s, a| this.convert_def_id(xcx, s, a)))
+        }))
     }
 
     fn read_ty_param_bounds_and_ty(&mut self, xcx: &ExtendedDecodeContext)
                                    -> ty::ty_param_bounds_and_ty {
-        self.read_struct("ty_param_bounds_and_ty", 2, |this| {
-            ty::ty_param_bounds_and_ty {
-                generics: this.read_struct_field("generics", 0, |this| {
+        unwrap_(self.read_struct("ty_param_bounds_and_ty", 2, |this| {
+            wrap_(ty::ty_param_bounds_and_ty {
+                generics: unwrap_(this.read_struct_field("generics", 0, |this| {
                     this.read_struct("Generics", 2, |this| {
-                        ty::Generics {
+                        wrap_(ty::Generics {
                             type_param_defs:
-                                this.read_struct_field("type_param_defs",
+                                unwrap_(this.read_struct_field("type_param_defs",
                                                        0,
                                                        |this| {
-                                    Rc::new(this.read_to_vec(|this|
-                                                             this.read_type_param_def(xcx))
+                                    wrap_(Rc::new(unwrap_(this.read_to_vec(|this|
+                                                             wrap_(this.read_type_param_def(xcx))))
                                                 .move_iter()
-                                                .collect())
-                            }),
+                                                .collect()))
+                            })),
                             region_param_defs:
-                                this.read_struct_field("region_param_defs",
+                                unwrap_(this.read_struct_field("region_param_defs",
                                                        1,
                                                        |this| {
                                     Decodable::decode(this)
-                                })
-                        }
+                                }))
+                        })
                     })
-                }),
-                ty: this.read_struct_field("ty", 1, |this| {
-                    this.read_ty(xcx)
-                })
-            }
-        })
+                })),
+                ty: unwrap_(this.read_struct_field("ty", 1, |this| {
+                    wrap_(this.read_ty(xcx))
+                }))
+            })
+        }))
     }
 
     fn read_substs(&mut self, xcx: &ExtendedDecodeContext) -> ty::substs {
-        self.read_opaque(|this, doc| {
-            tydecode::parse_substs_data(doc.data,
+        unwrap_(self.read_opaque(|this, doc| {
+            wrap_(tydecode::parse_substs_data(doc.data,
                                         xcx.dcx.cdata.cnum,
                                         doc.start,
                                         xcx.dcx.tcx,
-                                        |s, a| this.convert_def_id(xcx, s, a))
-        })
+                                        |s, a| this.convert_def_id(xcx, s, a)))
+        }))
     }
 
     fn read_auto_adjustment(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoAdjustment {
-        self.read_enum("AutoAdjustment", |this| {
+        unwrap_(self.read_enum("AutoAdjustment", |this| {
             let variants = ["AutoAddEnv", "AutoDerefRef", "AutoObject"];
             this.read_enum_variant(variants, |this, i| {
-                match i {
+                wrap_(match i {
                     0 => {
                         let region: ty::Region =
-                            this.read_enum_variant_arg(0, |this| Decodable::decode(this));
+                            unwrap_(this.read_enum_variant_arg(0, |this| Decodable::decode(this)));
                         let sigil: ast::Sigil =
-                            this.read_enum_variant_arg(1, |this| Decodable::decode(this));
+                            unwrap_(this.read_enum_variant_arg(1, |this| Decodable::decode(this)));
 
                         ty:: AutoAddEnv(region.tr(xcx), sigil)
                     }
                     1 => {
                         let auto_deref_ref: ty::AutoDerefRef =
-                            this.read_enum_variant_arg(0, |this| Decodable::decode(this));
+                            unwrap_(this.read_enum_variant_arg(0, |this| Decodable::decode(this)));
 
                         ty::AutoDerefRef(auto_deref_ref.tr(xcx))
                     }
                     2 => {
                         let sigil: ast::Sigil =
-                            this.read_enum_variant_arg(0, |this| Decodable::decode(this));
+                            unwrap_(this.read_enum_variant_arg(0, |this| Decodable::decode(this)));
                         let region: Option<ty::Region> =
-                            this.read_enum_variant_arg(1, |this| Decodable::decode(this));
+                            unwrap_(this.read_enum_variant_arg(1, |this| Decodable::decode(this)));
                         let m: ast::Mutability =
-                            this.read_enum_variant_arg(2, |this| Decodable::decode(this));
+                            unwrap_(this.read_enum_variant_arg(2, |this| Decodable::decode(this)));
                         let b: ty::BuiltinBounds =
-                            this.read_enum_variant_arg(3, |this| Decodable::decode(this));
+                            unwrap_(this.read_enum_variant_arg(3, |this| Decodable::decode(this)));
                         let def_id: ast::DefId =
-                            this.read_enum_variant_arg(4, |this| Decodable::decode(this));
-                        let substs = this.read_enum_variant_arg(5, |this| this.read_substs(xcx));
+                            unwrap_(this.read_enum_variant_arg(4, |this| Decodable::decode(this)));
+                        let substs = unwrap_(
+                            this.read_enum_variant_arg(5, |this| wrap_(this.read_substs(xcx))));
 
                         let region = match region {
                             Some(r) => Some(r.tr(xcx)),
@@ -1302,9 +1363,9 @@ fn read_auto_adjustment(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoAdjus
                         ty::AutoObject(sigil, region, m, b, def_id.tr(xcx), substs)
                     }
                     _ => fail!("bad enum variant for ty::AutoAdjustment")
-                }
+                })
             })
-        })
+        }))
     }
 
     fn convert_def_id(&mut self,
@@ -1387,9 +1448,9 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                         dcx.tcx.node_type_substs.borrow_mut().insert(id, tys);
                     }
                     c::tag_table_freevars => {
-                        let fv_info = @val_dsr.read_to_vec(|val_dsr| {
-                            @val_dsr.read_freevar_entry(xcx)
-                        }).move_iter().collect();
+                        let fv_info = @unwrap_(val_dsr.read_to_vec(|val_dsr| {
+                            wrap_(@val_dsr.read_freevar_entry(xcx))
+                        })).move_iter().collect();
                         dcx.tcx.freevars.borrow_mut().insert(id, fv_info);
                     }
                     c::tag_table_tcache => {
@@ -1425,7 +1486,8 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                     }
                     c::tag_table_capture_map => {
                         let cvars =
-                                val_dsr.read_to_vec(|val_dsr| val_dsr.read_capture_var(xcx))
+                                unwrap_(val_dsr.read_to_vec(
+                                            |val_dsr| wrap_(val_dsr.read_capture_var(xcx))))
                                        .move_iter()
                                        .collect();
                         dcx.maps.capture_map.borrow_mut().insert(id, Rc::new(cvars));
@@ -1447,7 +1509,7 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
 // Testing of astencode_gen
 
 #[cfg(test)]
-fn encode_item_ast(ebml_w: &mut writer::Encoder, item: @ast::Item) {
+fn encode_item_ast(ebml_w: &mut Encoder, item: @ast::Item) {
     ebml_w.start_tag(c::tag_tree as uint);
     (*item).encode(ebml_w);
     ebml_w.end_tag();
@@ -1457,7 +1519,7 @@ fn encode_item_ast(ebml_w: &mut writer::Encoder, item: @ast::Item) {
 fn decode_item_ast(par_doc: ebml::Doc) -> @ast::Item {
     let chi_doc = par_doc.get(c::tag_tree as uint);
     let mut d = reader::Decoder(chi_doc);
-    @Decodable::decode(&mut d)
+    @unwrap_(Decodable::decode(&mut d))
 }
 
 #[cfg(test)]
index 6fcd1f83cf41cccdb28974e6eafded61361d1702..38b3901a0eea353f8c7ce6391d2d74c1c7ead3ac 100644 (file)
@@ -327,6 +327,17 @@ fn rust_input(cratefile: &str, matches: &getopts::Matches) -> Output {
     return pm.run_plugins(krate);
 }
 
+// FIXME: remove unwrap_ after snapshot
+#[cfg(stage0)]
+fn unwrap_<T>(t: T) -> T {
+    t
+}
+
+#[cfg(not(stage0))]
+fn unwrap_<T, E>(r: Result<T, E>) -> T {
+    r.unwrap()
+}
+
 /// This input format purely deserializes the json output file. No passes are
 /// run over the deserialized output.
 fn json_input(input: &str) -> Result<Output, ~str> {
@@ -352,7 +363,7 @@ fn json_input(input: &str) -> Result<Output, ~str> {
             let krate = match obj.pop(&~"crate") {
                 Some(json) => {
                     let mut d = json::Decoder::new(json);
-                    Decodable::decode(&mut d)
+                    unwrap_(Decodable::decode(&mut d))
                 }
                 None => return Err(~"malformed json"),
             };
@@ -384,7 +395,7 @@ fn json_output(krate: clean::Crate, res: Vec<plugins::PluginJson> ,
         let mut w = MemWriter::new();
         {
             let mut encoder = json::Encoder::new(&mut w as &mut io::Writer);
-            krate.encode(&mut encoder);
+            unwrap_(krate.encode(&mut encoder));
         }
         str::from_utf8_owned(w.unwrap()).unwrap()
     };
index bb823c2d8cae79c05b9b146bb7d6c16ca63776f0..8631fef5168abe5ab95323a6c3ddeb9f20d2611b 100644 (file)
 use collections::enum_set::{EnumSet, CLike};
 
 impl<
-    S: Encoder,
-    T: Encodable<S>
-> Encodable<S> for DList<T> {
-    fn encode(&self, s: &mut S) {
+    E,
+    S: Encoder<E>,
+    T: Encodable<S, E>
+> Encodable<S, E> for DList<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
-                s.emit_seq_elt(i, |s| e.encode(s));
+                try!(s.emit_seq_elt(i, |s| e.encode(s)));
             }
+            Ok(())
         })
     }
 }
 
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for DList<T> {
-    fn decode(d: &mut D) -> DList<T> {
-        let mut list = DList::new();
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for DList<T> {
+    fn decode(d: &mut D) -> Result<DList<T>, E> {
         d.read_seq(|d, len| {
+            let mut list = DList::new();
             for i in range(0u, len) {
-                list.push_back(d.read_seq_elt(i, |d| Decodable::decode(d)));
+                list.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
             }
-        });
-        list
+            Ok(list)
+        })
     }
 }
 
 impl<
-    S: Encoder,
-    T: Encodable<S>
-> Encodable<S> for RingBuf<T> {
-    fn encode(&self, s: &mut S) {
+    E,
+    S: Encoder<E>,
+    T: Encodable<S, E>
+> Encodable<S, E> for RingBuf<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
-                s.emit_seq_elt(i, |s| e.encode(s));
+                try!(s.emit_seq_elt(i, |s| e.encode(s)));
             }
+            Ok(())
         })
     }
 }
 
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for RingBuf<T> {
-    fn decode(d: &mut D) -> RingBuf<T> {
-        let mut deque = RingBuf::new();
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for RingBuf<T> {
+    fn decode(d: &mut D) -> Result<RingBuf<T>, E> {
         d.read_seq(|d, len| {
+            let mut deque: RingBuf<T> = RingBuf::new();
             for i in range(0u, len) {
-                deque.push_back(d.read_seq_elt(i, |d| Decodable::decode(d)));
+                deque.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
             }
-        });
-        deque
+            Ok(deque)
+        })
     }
 }
 
 impl<
-    E: Encoder,
-    K: Encodable<E> + Eq + TotalOrd,
-    V: Encodable<E> + Eq
-> Encodable<E> for TreeMap<K, V> {
-    fn encode(&self, e: &mut E) {
+    E,
+    S: Encoder<E>,
+    K: Encodable<S, E> + Eq + TotalOrd,
+    V: Encodable<S, E> + Eq
+> Encodable<S, E> for TreeMap<K, V> {
+    fn encode(&self, e: &mut S) -> Result<(), E> {
         e.emit_map(self.len(), |e| {
             let mut i = 0;
             for (key, val) in self.iter() {
-                e.emit_map_elt_key(i, |e| key.encode(e));
-                e.emit_map_elt_val(i, |e| val.encode(e));
+                try!(e.emit_map_elt_key(i, |e| key.encode(e)));
+                try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                 i += 1;
             }
+            Ok(())
         })
     }
 }
 
 impl<
-    D: Decoder,
-    K: Decodable<D> + Eq + TotalOrd,
-    V: Decodable<D> + Eq
-> Decodable<D> for TreeMap<K, V> {
-    fn decode(d: &mut D) -> TreeMap<K, V> {
+    E,
+    D: Decoder<E>,
+    K: Decodable<D, E> + Eq + TotalOrd,
+    V: Decodable<D, E> + Eq
+> Decodable<D, E> for TreeMap<K, V> {
+    fn decode(d: &mut D) -> Result<TreeMap<K, V>, E> {
         d.read_map(|d, len| {
             let mut map = TreeMap::new();
             for i in range(0u, len) {
-                let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
-                let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
+                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
+                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                 map.insert(key, val);
             }
-            map
+            Ok(map)
         })
     }
 }
 
 impl<
-    S: Encoder,
-    T: Encodable<S> + Eq + TotalOrd
-> Encodable<S> for TreeSet<T> {
-    fn encode(&self, s: &mut S) {
+    E,
+    S: Encoder<E>,
+    T: Encodable<S, E> + Eq + TotalOrd
+> Encodable<S, E> for TreeSet<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_seq(self.len(), |s| {
             let mut i = 0;
             for e in self.iter() {
-                s.emit_seq_elt(i, |s| e.encode(s));
+                try!(s.emit_seq_elt(i, |s| e.encode(s)));
                 i += 1;
             }
+            Ok(())
         })
     }
 }
 
 impl<
-    D: Decoder,
-    T: Decodable<D> + Eq + TotalOrd
-> Decodable<D> for TreeSet<T> {
-    fn decode(d: &mut D) -> TreeSet<T> {
+    E,
+    D: Decoder<E>,
+    T: Decodable<D, E> + Eq + TotalOrd
+> Decodable<D, E> for TreeSet<T> {
+    fn decode(d: &mut D) -> Result<TreeSet<T>, E> {
         d.read_seq(|d, len| {
             let mut set = TreeSet::new();
             for i in range(0u, len) {
-                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
+                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
             }
-            set
+            Ok(set)
         })
     }
 }
 
 impl<
-    S: Encoder,
-    T: Encodable<S> + CLike
-> Encodable<S> for EnumSet<T> {
-    fn encode(&self, s: &mut S) {
+    E,
+    S: Encoder<E>,
+    T: Encodable<S, E> + CLike
+> Encodable<S, E> for EnumSet<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         let mut bits = 0;
         for item in self.iter() {
             bits |= item.to_uint();
         }
-        s.emit_uint(bits);
+        s.emit_uint(bits)
     }
 }
 
 impl<
-    D: Decoder,
-    T: Decodable<D> + CLike
-> Decodable<D> for EnumSet<T> {
-    fn decode(d: &mut D) -> EnumSet<T> {
-        let bits = d.read_uint();
+    E,
+    D: Decoder<E>,
+    T: Decodable<D, E> + CLike
+> Decodable<D, E> for EnumSet<T> {
+    fn decode(d: &mut D) -> Result<EnumSet<T>, E> {
+        let bits = try!(d.read_uint());
         let mut set = EnumSet::empty();
         for bit in range(0, uint::BITS) {
             if bits & (1 << bit) != 0 {
                 set.add(CLike::from_uint(1 << bit));
             }
         }
-        set
+        Ok(set)
     }
 }
 
 impl<
-    E: Encoder,
-    K: Encodable<E> + Hash<S> + TotalEq,
-    V: Encodable<E>,
-    S,
-    H: Hasher<S>
-> Encodable<E> for HashMap<K, V, H> {
-    fn encode(&self, e: &mut E) {
+    E,
+    S: Encoder<E>,
+    K: Encodable<S, E> + Hash<X> + TotalEq,
+    V: Encodable<S, E>,
+    X,
+    H: Hasher<X>
+> Encodable<S, E> for HashMap<K, V, H> {
+    fn encode(&self, e: &mut S) -> Result<(), E> {
         e.emit_map(self.len(), |e| {
             let mut i = 0;
             for (key, val) in self.iter() {
-                e.emit_map_elt_key(i, |e| key.encode(e));
-                e.emit_map_elt_val(i, |e| val.encode(e));
+                try!(e.emit_map_elt_key(i, |e| key.encode(e)));
+                try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                 i += 1;
             }
+            Ok(())
         })
     }
 }
 
 impl<
-    D: Decoder,
-    K: Decodable<D> + Hash<S> + TotalEq,
-    V: Decodable<D>,
+    E,
+    D: Decoder<E>,
+    K: Decodable<D, E> + Hash<S> + TotalEq,
+    V: Decodable<D, E>,
     S,
     H: Hasher<S> + Default
-> Decodable<D> for HashMap<K, V, H> {
-    fn decode(d: &mut D) -> HashMap<K, V, H> {
+> Decodable<D, E> for HashMap<K, V, H> {
+    fn decode(d: &mut D) -> Result<HashMap<K, V, H>, E> {
         d.read_map(|d, len| {
             let hasher = Default::default();
             let mut map = HashMap::with_capacity_and_hasher(len, hasher);
             for i in range(0u, len) {
-                let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
-                let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
+                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
+                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                 map.insert(key, val);
             }
-            map
+            Ok(map)
         })
     }
 }
 
 impl<
-    E: Encoder,
-    T: Encodable<E> + Hash<S> + TotalEq,
-    S,
-    H: Hasher<S>
-> Encodable<E> for HashSet<T, H> {
-    fn encode(&self, s: &mut E) {
+    E,
+    S: Encoder<E>,
+    T: Encodable<S, E> + Hash<X> + TotalEq,
+    X,
+    H: Hasher<X>
+> Encodable<S, E> for HashSet<T, H> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_seq(self.len(), |s| {
             let mut i = 0;
             for e in self.iter() {
-                s.emit_seq_elt(i, |s| e.encode(s));
+                try!(s.emit_seq_elt(i, |s| e.encode(s)));
                 i += 1;
             }
+            Ok(())
         })
     }
 }
 
 impl<
-    D: Decoder,
-    T: Decodable<D> + Hash<S> + TotalEq,
+    E,
+    D: Decoder<E>,
+    T: Decodable<D, E> + Hash<S> + TotalEq,
     S,
     H: Hasher<S> + Default
-> Decodable<D> for HashSet<T, H> {
-    fn decode(d: &mut D) -> HashSet<T, H> {
+> Decodable<D, E> for HashSet<T, H> {
+    fn decode(d: &mut D) -> Result<HashSet<T, H>, E> {
         d.read_seq(|d, len| {
             let mut set = HashSet::with_capacity_and_hasher(len, Default::default());
             for i in range(0u, len) {
-                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
+                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
             }
-            set
+            Ok(set)
         })
     }
 }
 
 impl<
-    E: Encoder,
-    V: Encodable<E>
-> Encodable<E> for TrieMap<V> {
-    fn encode(&self, e: &mut E) {
+    E,
+    S: Encoder<E>,
+    V: Encodable<S, E>
+> Encodable<S, E> for TrieMap<V> {
+    fn encode(&self, e: &mut S) -> Result<(), E> {
         e.emit_map(self.len(), |e| {
                 for (i, (key, val)) in self.iter().enumerate() {
-                    e.emit_map_elt_key(i, |e| key.encode(e));
-                    e.emit_map_elt_val(i, |e| val.encode(e));
+                    try!(e.emit_map_elt_key(i, |e| key.encode(e)));
+                    try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                 }
-            });
+                Ok(())
+            })
     }
 }
 
 impl<
-    D: Decoder,
-    V: Decodable<D>
-> Decodable<D> for TrieMap<V> {
-    fn decode(d: &mut D) -> TrieMap<V> {
+    E,
+    D: Decoder<E>,
+    V: Decodable<D, E>
+> Decodable<D, E> for TrieMap<V> {
+    fn decode(d: &mut D) -> Result<TrieMap<V>, E> {
         d.read_map(|d, len| {
             let mut map = TrieMap::new();
             for i in range(0u, len) {
-                let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
-                let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
+                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
+                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                 map.insert(key, val);
             }
-            map
+            Ok(map)
         })
     }
 }
 
-impl<S: Encoder> Encodable<S> for TrieSet {
-    fn encode(&self, s: &mut S) {
+impl<E, S: Encoder<E>> Encodable<S, E> for TrieSet {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_seq(self.len(), |s| {
                 for (i, e) in self.iter().enumerate() {
-                    s.emit_seq_elt(i, |s| e.encode(s));
+                    try!(s.emit_seq_elt(i, |s| e.encode(s)));
                 }
+                Ok(())
             })
     }
 }
 
-impl<D: Decoder> Decodable<D> for TrieSet {
-    fn decode(d: &mut D) -> TrieSet {
+impl<E, D: Decoder<E>> Decodable<D, E> for TrieSet {
+    fn decode(d: &mut D) -> Result<TrieSet, E> {
         d.read_seq(|d, len| {
             let mut set = TrieSet::new();
             for i in range(0u, len) {
-                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
+                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
             }
-            set
+            Ok(set)
         })
     }
 }
diff --git a/src/libserialize/collection_impls_old.rs b/src/libserialize/collection_impls_old.rs
new file mode 100644 (file)
index 0000000..5994fbc
--- /dev/null
@@ -0,0 +1,292 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Implementations of serialization for structures found in libcollections
+
+use std::uint;
+use std::default::Default;
+use std::hash::{Hash, Hasher};
+
+use {Decodable, Encodable, Decoder, Encoder};
+use collections::{DList, RingBuf, TreeMap, TreeSet, Deque, HashMap, HashSet,
+                  TrieMap, TrieSet};
+use collections::enum_set::{EnumSet, CLike};
+
+impl<
+    S: Encoder,
+    T: Encodable<S>
+> Encodable<S> for DList<T> {
+    fn encode(&self, s: &mut S) {
+        s.emit_seq(self.len(), |s| {
+            for (i, e) in self.iter().enumerate() {
+                s.emit_seq_elt(i, |s| e.encode(s));
+            }
+        })
+    }
+}
+
+impl<D:Decoder,T:Decodable<D>> Decodable<D> for DList<T> {
+    fn decode(d: &mut D) -> DList<T> {
+        let mut list = DList::new();
+        d.read_seq(|d, len| {
+            for i in range(0u, len) {
+                list.push_back(d.read_seq_elt(i, |d| Decodable::decode(d)));
+            }
+        });
+        list
+    }
+}
+
+impl<
+    S: Encoder,
+    T: Encodable<S>
+> Encodable<S> for RingBuf<T> {
+    fn encode(&self, s: &mut S) {
+        s.emit_seq(self.len(), |s| {
+            for (i, e) in self.iter().enumerate() {
+                s.emit_seq_elt(i, |s| e.encode(s));
+            }
+        })
+    }
+}
+
+impl<D:Decoder,T:Decodable<D>> Decodable<D> for RingBuf<T> {
+    fn decode(d: &mut D) -> RingBuf<T> {
+        let mut deque = RingBuf::new();
+        d.read_seq(|d, len| {
+            for i in range(0u, len) {
+                deque.push_back(d.read_seq_elt(i, |d| Decodable::decode(d)));
+            }
+        });
+        deque
+    }
+}
+
+impl<
+    E: Encoder,
+    K: Encodable<E> + Eq + TotalOrd,
+    V: Encodable<E> + Eq
+> Encodable<E> for TreeMap<K, V> {
+    fn encode(&self, e: &mut E) {
+        e.emit_map(self.len(), |e| {
+            let mut i = 0;
+            for (key, val) in self.iter() {
+                e.emit_map_elt_key(i, |e| key.encode(e));
+                e.emit_map_elt_val(i, |e| val.encode(e));
+                i += 1;
+            }
+        })
+    }
+}
+
+impl<
+    D: Decoder,
+    K: Decodable<D> + Eq + TotalOrd,
+    V: Decodable<D> + Eq
+> Decodable<D> for TreeMap<K, V> {
+    fn decode(d: &mut D) -> TreeMap<K, V> {
+        d.read_map(|d, len| {
+            let mut map = TreeMap::new();
+            for i in range(0u, len) {
+                let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
+                let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
+                map.insert(key, val);
+            }
+            map
+        })
+    }
+}
+
+impl<
+    S: Encoder,
+    T: Encodable<S> + Eq + TotalOrd
+> Encodable<S> for TreeSet<T> {
+    fn encode(&self, s: &mut S) {
+        s.emit_seq(self.len(), |s| {
+            let mut i = 0;
+            for e in self.iter() {
+                s.emit_seq_elt(i, |s| e.encode(s));
+                i += 1;
+            }
+        })
+    }
+}
+
+impl<
+    D: Decoder,
+    T: Decodable<D> + Eq + TotalOrd
+> Decodable<D> for TreeSet<T> {
+    fn decode(d: &mut D) -> TreeSet<T> {
+        d.read_seq(|d, len| {
+            let mut set = TreeSet::new();
+            for i in range(0u, len) {
+                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
+            }
+            set
+        })
+    }
+}
+
+impl<
+    S: Encoder,
+    T: Encodable<S> + CLike
+> Encodable<S> for EnumSet<T> {
+    fn encode(&self, s: &mut S) {
+        let mut bits = 0;
+        for item in self.iter() {
+            bits |= item.to_uint();
+        }
+        s.emit_uint(bits);
+    }
+}
+
+impl<
+    D: Decoder,
+    T: Decodable<D> + CLike
+> Decodable<D> for EnumSet<T> {
+    fn decode(d: &mut D) -> EnumSet<T> {
+        let bits = d.read_uint();
+        let mut set = EnumSet::empty();
+        for bit in range(0, uint::BITS) {
+            if bits & (1 << bit) != 0 {
+                set.add(CLike::from_uint(1 << bit));
+            }
+        }
+        set
+    }
+}
+
+impl<
+    E: Encoder,
+    K: Encodable<E> + Hash<S> + TotalEq,
+    V: Encodable<E>,
+    S,
+    H: Hasher<S>
+> Encodable<E> for HashMap<K, V, H> {
+    fn encode(&self, e: &mut E) {
+        e.emit_map(self.len(), |e| {
+            let mut i = 0;
+            for (key, val) in self.iter() {
+                e.emit_map_elt_key(i, |e| key.encode(e));
+                e.emit_map_elt_val(i, |e| val.encode(e));
+                i += 1;
+            }
+        })
+    }
+}
+
+impl<
+    D: Decoder,
+    K: Decodable<D> + Hash<S> + TotalEq,
+    V: Decodable<D>,
+    S,
+    H: Hasher<S> + Default
+> Decodable<D> for HashMap<K, V, H> {
+    fn decode(d: &mut D) -> HashMap<K, V, H> {
+        d.read_map(|d, len| {
+            let hasher = Default::default();
+            let mut map = HashMap::with_capacity_and_hasher(len, hasher);
+            for i in range(0u, len) {
+                let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
+                let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
+                map.insert(key, val);
+            }
+            map
+        })
+    }
+}
+
+impl<
+    E: Encoder,
+    T: Encodable<E> + Hash<S> + TotalEq,
+    S,
+    H: Hasher<S>
+> Encodable<E> for HashSet<T, H> {
+    fn encode(&self, s: &mut E) {
+        s.emit_seq(self.len(), |s| {
+            let mut i = 0;
+            for e in self.iter() {
+                s.emit_seq_elt(i, |s| e.encode(s));
+                i += 1;
+            }
+        })
+    }
+}
+
+impl<
+    D: Decoder,
+    T: Decodable<D> + Hash<S> + TotalEq,
+    S,
+    H: Hasher<S> + Default
+> Decodable<D> for HashSet<T, H> {
+    fn decode(d: &mut D) -> HashSet<T, H> {
+        d.read_seq(|d, len| {
+            let mut set = HashSet::with_capacity_and_hasher(len, Default::default());
+            for i in range(0u, len) {
+                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
+            }
+            set
+        })
+    }
+}
+
+impl<
+    E: Encoder,
+    V: Encodable<E>
+> Encodable<E> for TrieMap<V> {
+    fn encode(&self, e: &mut E) {
+        e.emit_map(self.len(), |e| {
+                for (i, (key, val)) in self.iter().enumerate() {
+                    e.emit_map_elt_key(i, |e| key.encode(e));
+                    e.emit_map_elt_val(i, |e| val.encode(e));
+                }
+            });
+    }
+}
+
+impl<
+    D: Decoder,
+    V: Decodable<D>
+> Decodable<D> for TrieMap<V> {
+    fn decode(d: &mut D) -> TrieMap<V> {
+        d.read_map(|d, len| {
+            let mut map = TrieMap::new();
+            for i in range(0u, len) {
+                let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
+                let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
+                map.insert(key, val);
+            }
+            map
+        })
+    }
+}
+
+impl<S: Encoder> Encodable<S> for TrieSet {
+    fn encode(&self, s: &mut S) {
+        s.emit_seq(self.len(), |s| {
+                for (i, e) in self.iter().enumerate() {
+                    s.emit_seq_elt(i, |s| e.encode(s));
+                }
+            })
+    }
+}
+
+impl<D: Decoder> Decodable<D> for TrieSet {
+    fn decode(d: &mut D) -> TrieSet {
+        d.read_seq(|d, len| {
+            let mut set = TrieSet::new();
+            for i in range(0u, len) {
+                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
+            }
+            set
+        })
+    }
+}
+
index 2b416f263c26a8b706976fd62cd8ffe9094ffeb7..cc2385665a21a207a19a3e80be812037f0a350d2 100644 (file)
 
 #[allow(missing_doc)];
 
+use std::io;
 use std::str;
 
-macro_rules! try( ($e:expr) => (
-    match $e { Ok(e) => e, Err(e) => { self.last_error = Err(e); return } }
-) )
-
 // Simple Extensible Binary Markup Language (ebml) reader and writer on a
 // cursor model. See the specification here:
 //     http://www.matroska.org/technical/specs/rfc/index.html
@@ -79,6 +76,13 @@ pub enum EbmlEncoderTag {
 
     EsLabel, // Used only when debugging
 }
+
+#[deriving(Show)]
+pub enum Error {
+    IntTooBig(uint),
+    Expected(~str),
+    IoError(io::IoError)
+}
 // --------------------------------------
 
 pub mod reader {
@@ -94,43 +98,57 @@ pub mod reader {
     use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey,
         EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8,
         EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint,
-        EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc };
+        EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc, Error, IntTooBig,
+        Expected };
 
+    pub type DecodeResult<T> = Result<T, Error>;
     // ebml reading
 
+    macro_rules! try_or(
+        ($e:expr, $r:expr) => (
+            match $e {
+                Ok(e) => e,
+                Err(e) => {
+                    debug!("ignored error: {}", e);
+                    return $r
+                }
+            }
+        )
+    )
+
     pub struct Res {
         val: uint,
         next: uint
     }
 
     #[inline(never)]
-    fn vuint_at_slow(data: &[u8], start: uint) -> Res {
+    fn vuint_at_slow(data: &[u8], start: uint) -> DecodeResult<Res> {
         let a = data[start];
         if a & 0x80u8 != 0u8 {
-            return Res {val: (a & 0x7fu8) as uint, next: start + 1u};
+            return Ok(Res {val: (a & 0x7fu8) as uint, next: start + 1u});
         }
         if a & 0x40u8 != 0u8 {
-            return Res {val: ((a & 0x3fu8) as uint) << 8u |
+            return Ok(Res {val: ((a & 0x3fu8) as uint) << 8u |
                         (data[start + 1u] as uint),
-                    next: start + 2u};
+                    next: start + 2u});
         }
         if a & 0x20u8 != 0u8 {
-            return Res {val: ((a & 0x1fu8) as uint) << 16u |
+            return Ok(Res {val: ((a & 0x1fu8) as uint) << 16u |
                         (data[start + 1u] as uint) << 8u |
                         (data[start + 2u] as uint),
-                    next: start + 3u};
+                    next: start + 3u});
         }
         if a & 0x10u8 != 0u8 {
-            return Res {val: ((a & 0x0fu8) as uint) << 24u |
+            return Ok(Res {val: ((a & 0x0fu8) as uint) << 24u |
                         (data[start + 1u] as uint) << 16u |
                         (data[start + 2u] as uint) << 8u |
                         (data[start + 3u] as uint),
-                    next: start + 4u};
+                    next: start + 4u});
         }
-        fail!("vint too big");
+        Err(IntTooBig(a as uint))
     }
 
-    pub fn vuint_at(data: &[u8], start: uint) -> Res {
+    pub fn vuint_at(data: &[u8], start: uint) -> DecodeResult<Res> {
         use std::mem::from_be32;
 
         if data.len() - start < 4 {
@@ -166,10 +184,10 @@ pub fn vuint_at(data: &[u8], start: uint) -> Res {
 
             let i = (val >> 28u) as uint;
             let (shift, mask) = SHIFT_MASK_TABLE[i];
-            Res {
+            Ok(Res {
                 val: ((val >> shift) & mask) as uint,
                 next: start + (((32 - shift) >> 3) as uint)
-            }
+            })
         }
     }
 
@@ -177,21 +195,21 @@ pub fn Doc<'a>(data: &'a [u8]) -> Doc<'a> {
         Doc { data: data, start: 0u, end: data.len() }
     }
 
-    pub fn doc_at<'a>(data: &'a [u8], start: uint) -> TaggedDoc<'a> {
-        let elt_tag = vuint_at(data, start);
-        let elt_size = vuint_at(data, elt_tag.next);
+    pub fn doc_at<'a>(data: &'a [u8], start: uint) -> DecodeResult<TaggedDoc<'a>> {
+        let elt_tag = try!(vuint_at(data, start));
+        let elt_size = try!(vuint_at(data, elt_tag.next));
         let end = elt_size.next + elt_size.val;
-        TaggedDoc {
+        Ok(TaggedDoc {
             tag: elt_tag.val,
             doc: Doc { data: data, start: elt_size.next, end: end }
-        }
+        })
     }
 
     pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: uint) -> Option<Doc<'a>> {
         let mut pos = d.start;
         while pos < d.end {
-            let elt_tag = vuint_at(d.data, pos);
-            let elt_size = vuint_at(d.data, elt_tag.next);
+            let elt_tag = try_or!(vuint_at(d.data, pos), None);
+            let elt_size = try_or!(vuint_at(d.data, elt_tag.next), None);
             pos = elt_size.next + elt_size.val;
             if elt_tag.val == tg {
                 return Some(Doc { data: d.data, start: elt_size.next,
@@ -214,8 +232,8 @@ pub fn get_doc<'a>(d: Doc<'a>, tg: uint) -> Doc<'a> {
     pub fn docs<'a>(d: Doc<'a>, it: |uint, Doc<'a>| -> bool) -> bool {
         let mut pos = d.start;
         while pos < d.end {
-            let elt_tag = vuint_at(d.data, pos);
-            let elt_size = vuint_at(d.data, elt_tag.next);
+            let elt_tag = try_or!(vuint_at(d.data, pos), false);
+            let elt_size = try_or!(vuint_at(d.data, elt_tag.next), false);
             pos = elt_size.next + elt_size.val;
             let doc = Doc { data: d.data, start: elt_size.next, end: pos };
             if !it(elt_tag.val, doc) {
@@ -228,8 +246,8 @@ pub fn docs<'a>(d: Doc<'a>, it: |uint, Doc<'a>| -> bool) -> bool {
     pub fn tagged_docs<'a>(d: Doc<'a>, tg: uint, it: |Doc<'a>| -> bool) -> bool {
         let mut pos = d.start;
         while pos < d.end {
-            let elt_tag = vuint_at(d.data, pos);
-            let elt_size = vuint_at(d.data, elt_tag.next);
+            let elt_tag = try_or!(vuint_at(d.data, pos), false);
+            let elt_size = try_or!(vuint_at(d.data, elt_tag.next), false);
             pos = elt_size.next + elt_size.val;
             if elt_tag.val == tg {
                 let doc = Doc { data: d.data, start: elt_size.next,
@@ -285,28 +303,29 @@ pub fn Decoder<'a>(d: Doc<'a>) -> Decoder<'a> {
     }
 
     impl<'doc> Decoder<'doc> {
-        fn _check_label(&mut self, lbl: &str) {
+        fn _check_label(&mut self, lbl: &str) -> DecodeResult<()> {
             if self.pos < self.parent.end {
                 let TaggedDoc { tag: r_tag, doc: r_doc } =
-                    doc_at(self.parent.data, self.pos);
+                    try!(doc_at(self.parent.data, self.pos));
 
                 if r_tag == (EsLabel as uint) {
                     self.pos = r_doc.end;
                     let str = r_doc.as_str_slice();
                     if lbl != str {
-                        fail!("Expected label {} but found {}", lbl, str);
+                        return Err(Expected(format!("Expected label {} but found {}", lbl, str)));
                     }
                 }
             }
+            Ok(())
         }
 
-        fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> Doc<'doc> {
+        fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<Doc<'doc>> {
             debug!(". next_doc(exp_tag={:?})", exp_tag);
             if self.pos >= self.parent.end {
-                fail!("no more documents in current node!");
+                return Err(Expected(format!("no more documents in current node!")));
             }
             let TaggedDoc { tag: r_tag, doc: r_doc } =
-                doc_at(self.parent.data, self.pos);
+                try!(doc_at(self.parent.data, self.pos));
             debug!("self.parent={}-{} self.pos={} r_tag={} r_doc={}-{}",
                    self.parent.start,
                    self.parent.end,
@@ -315,178 +334,183 @@ fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> Doc<'doc> {
                    r_doc.start,
                    r_doc.end);
             if r_tag != (exp_tag as uint) {
-                fail!("expected EBML doc with tag {:?} but found tag {:?}",
-                       exp_tag, r_tag);
+                return Err(Expected(format!("expected EBML doc with tag {:?} but found tag {:?}",
+                       exp_tag, r_tag)));
             }
             if r_doc.end > self.parent.end {
-                fail!("invalid EBML, child extends to {:#x}, parent to {:#x}",
-                      r_doc.end, self.parent.end);
+                return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to {:#x}",
+                      r_doc.end, self.parent.end)));
             }
             self.pos = r_doc.end;
-            r_doc
+            Ok(r_doc)
         }
 
         fn push_doc<T>(&mut self, exp_tag: EbmlEncoderTag,
-                       f: |&mut Decoder<'doc>| -> T) -> T {
-            let d = self.next_doc(exp_tag);
+                       f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
+            let d = try!(self.next_doc(exp_tag));
             let old_parent = self.parent;
             let old_pos = self.pos;
             self.parent = d;
             self.pos = d.start;
-            let r = f(self);
+            let r = try!(f(self));
             self.parent = old_parent;
             self.pos = old_pos;
-            r
+            Ok(r)
         }
 
-        fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> uint {
-            let r = doc_as_u32(self.next_doc(exp_tag));
+        fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<uint> {
+            let r = doc_as_u32(try!(self.next_doc(exp_tag)));
             debug!("_next_uint exp_tag={:?} result={}", exp_tag, r);
-            r as uint
+            Ok(r as uint)
         }
 
-        pub fn read_opaque<R>(&mut self, op: |&mut Decoder<'doc>, Doc| -> R) -> R {
-            let doc = self.next_doc(EsOpaque);
+        pub fn read_opaque<R>(&mut self,
+                              op: |&mut Decoder<'doc>, Doc| -> DecodeResult<R>) -> DecodeResult<R> {
+            let doc = try!(self.next_doc(EsOpaque));
 
             let (old_parent, old_pos) = (self.parent, self.pos);
             self.parent = doc;
             self.pos = doc.start;
 
-            let result = op(self, doc);
+            let result = try!(op(self, doc));
 
             self.parent = old_parent;
             self.pos = old_pos;
-            result
+            Ok(result)
         }
     }
 
-    impl<'doc> serialize::Decoder for Decoder<'doc> {
-        fn read_nil(&mut self) -> () { () }
+    impl<'doc> serialize::Decoder<Error> for Decoder<'doc> {
+        fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) }
 
-        fn read_u64(&mut self) -> u64 { doc_as_u64(self.next_doc(EsU64)) }
-        fn read_u32(&mut self) -> u32 { doc_as_u32(self.next_doc(EsU32)) }
-        fn read_u16(&mut self) -> u16 { doc_as_u16(self.next_doc(EsU16)) }
-        fn read_u8 (&mut self) -> u8  { doc_as_u8 (self.next_doc(EsU8 )) }
-        fn read_uint(&mut self) -> uint {
-            let v = doc_as_u64(self.next_doc(EsUint));
+        fn read_u64(&mut self) -> DecodeResult<u64> { Ok(doc_as_u64(try!(self.next_doc(EsU64)))) }
+        fn read_u32(&mut self) -> DecodeResult<u32> { Ok(doc_as_u32(try!(self.next_doc(EsU32)))) }
+        fn read_u16(&mut self) -> DecodeResult<u16> { Ok(doc_as_u16(try!(self.next_doc(EsU16)))) }
+        fn read_u8 (&mut self) -> DecodeResult<u8 > { Ok(doc_as_u8 (try!(self.next_doc(EsU8 )))) }
+        fn read_uint(&mut self) -> DecodeResult<uint> {
+            let v = doc_as_u64(try!(self.next_doc(EsUint)));
             if v > (::std::uint::MAX as u64) {
-                fail!("uint {} too large for this architecture", v);
+                Err(IntTooBig(v as uint))
+            } else {
+                Ok(v as uint)
             }
-            v as uint
         }
 
-        fn read_i64(&mut self) -> i64 {
-            doc_as_u64(self.next_doc(EsI64)) as i64
+        fn read_i64(&mut self) -> DecodeResult<i64> {
+            Ok(doc_as_u64(try!(self.next_doc(EsI64))) as i64)
         }
-        fn read_i32(&mut self) -> i32 {
-            doc_as_u32(self.next_doc(EsI32)) as i32
+        fn read_i32(&mut self) -> DecodeResult<i32> {
+            Ok(doc_as_u32(try!(self.next_doc(EsI32))) as i32)
         }
-        fn read_i16(&mut self) -> i16 {
-            doc_as_u16(self.next_doc(EsI16)) as i16
+        fn read_i16(&mut self) -> DecodeResult<i16> {
+            Ok(doc_as_u16(try!(self.next_doc(EsI16))) as i16)
         }
-        fn read_i8 (&mut self) -> i8 {
-            doc_as_u8(self.next_doc(EsI8 )) as i8
+        fn read_i8 (&mut self) -> DecodeResult<i8> {
+            Ok(doc_as_u8(try!(self.next_doc(EsI8 ))) as i8)
         }
-        fn read_int(&mut self) -> int {
-            let v = doc_as_u64(self.next_doc(EsInt)) as i64;
+        fn read_int(&mut self) -> DecodeResult<int> {
+            let v = doc_as_u64(try!(self.next_doc(EsInt))) as i64;
             if v > (int::MAX as i64) || v < (int::MIN as i64) {
                 debug!("FIXME \\#6122: Removing this makes this function miscompile");
-                fail!("int {} out of range for this architecture", v);
+                Err(IntTooBig(v as uint))
+            } else {
+                Ok(v as int)
             }
-            v as int
         }
 
-        fn read_bool(&mut self) -> bool {
-            doc_as_u8(self.next_doc(EsBool)) != 0
+        fn read_bool(&mut self) -> DecodeResult<bool> {
+            Ok(doc_as_u8(try!(self.next_doc(EsBool))) != 0)
         }
 
-        fn read_f64(&mut self) -> f64 {
-            let bits = doc_as_u64(self.next_doc(EsF64));
-            unsafe { transmute(bits) }
+        fn read_f64(&mut self) -> DecodeResult<f64> {
+            let bits = doc_as_u64(try!(self.next_doc(EsF64)));
+            Ok(unsafe { transmute(bits) })
         }
-        fn read_f32(&mut self) -> f32 {
-            let bits = doc_as_u32(self.next_doc(EsF32));
-            unsafe { transmute(bits) }
+        fn read_f32(&mut self) -> DecodeResult<f32> {
+            let bits = doc_as_u32(try!(self.next_doc(EsF32)));
+            Ok(unsafe { transmute(bits) })
         }
-        fn read_char(&mut self) -> char {
-            char::from_u32(doc_as_u32(self.next_doc(EsChar))).unwrap()
+        fn read_char(&mut self) -> DecodeResult<char> {
+            Ok(char::from_u32(doc_as_u32(try!(self.next_doc(EsChar)))).unwrap())
         }
-        fn read_str(&mut self) -> ~str {
-            self.next_doc(EsStr).as_str()
+        fn read_str(&mut self) -> DecodeResult<~str> {
+            Ok(try!(self.next_doc(EsStr)).as_str())
         }
 
         // Compound types:
-        fn read_enum<T>(&mut self, name: &str, f: |&mut Decoder<'doc>| -> T) -> T {
+        fn read_enum<T>(&mut self,
+                        name: &str,
+                        f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
             debug!("read_enum({})", name);
-            self._check_label(name);
+            try!(self._check_label(name));
 
-            let doc = self.next_doc(EsEnum);
+            let doc = try!(self.next_doc(EsEnum));
 
             let (old_parent, old_pos) = (self.parent, self.pos);
             self.parent = doc;
             self.pos = self.parent.start;
 
-            let result = f(self);
+            let result = try!(f(self));
 
             self.parent = old_parent;
             self.pos = old_pos;
-            result
+            Ok(result)
         }
 
         fn read_enum_variant<T>(&mut self,
                                 _: &[&str],
-                                f: |&mut Decoder<'doc>, uint| -> T)
-                                -> T {
+                                f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
+                                -> DecodeResult<T> {
             debug!("read_enum_variant()");
-            let idx = self._next_uint(EsEnumVid);
+            let idx = try!(self._next_uint(EsEnumVid));
             debug!("  idx={}", idx);
 
-            let doc = self.next_doc(EsEnumBody);
+            let doc = try!(self.next_doc(EsEnumBody));
 
             let (old_parent, old_pos) = (self.parent, self.pos);
             self.parent = doc;
             self.pos = self.parent.start;
 
-            let result = f(self, idx);
+            let result = try!(f(self, idx));
 
             self.parent = old_parent;
             self.pos = old_pos;
-            result
+            Ok(result)
         }
 
         fn read_enum_variant_arg<T>(&mut self,
                                     idx: uint,
-                                    f: |&mut Decoder<'doc>| -> T) -> T {
+                                    f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
             debug!("read_enum_variant_arg(idx={})", idx);
             f(self)
         }
 
         fn read_enum_struct_variant<T>(&mut self,
                                        _: &[&str],
-                                       f: |&mut Decoder<'doc>, uint| -> T)
-                                       -> T {
+                                       f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
+                                       -> DecodeResult<T> {
             debug!("read_enum_struct_variant()");
-            let idx = self._next_uint(EsEnumVid);
+            let idx = try!(self._next_uint(EsEnumVid));
             debug!("  idx={}", idx);
 
-            let doc = self.next_doc(EsEnumBody);
+            let doc = try!(self.next_doc(EsEnumBody));
 
             let (old_parent, old_pos) = (self.parent, self.pos);
             self.parent = doc;
             self.pos = self.parent.start;
 
-            let result = f(self, idx);
+            let result = try!(f(self, idx));
 
             self.parent = old_parent;
             self.pos = old_pos;
-            result
+            Ok(result)
         }
 
         fn read_enum_struct_variant_field<T>(&mut self,
                                              name: &str,
                                              idx: uint,
-                                             f: |&mut Decoder<'doc>| -> T)
-                                             -> T {
+                                             f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+                                             -> DecodeResult<T> {
             debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
             f(self)
         }
@@ -494,8 +518,8 @@ fn read_enum_struct_variant_field<T>(&mut self,
         fn read_struct<T>(&mut self,
                           name: &str,
                           _: uint,
-                          f: |&mut Decoder<'doc>| -> T)
-                          -> T {
+                          f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+                          -> DecodeResult<T> {
             debug!("read_struct(name={})", name);
             f(self)
         }
@@ -503,85 +527,89 @@ fn read_struct<T>(&mut self,
         fn read_struct_field<T>(&mut self,
                                 name: &str,
                                 idx: uint,
-                                f: |&mut Decoder<'doc>| -> T)
-                                -> T {
+                                f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+                                -> DecodeResult<T> {
             debug!("read_struct_field(name={}, idx={})", name, idx);
-            self._check_label(name);
+            try!(self._check_label(name));
             f(self)
         }
 
-        fn read_tuple<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T {
+        fn read_tuple<T>(&mut self,
+                         f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
             debug!("read_tuple()");
             self.read_seq(f)
         }
 
-        fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
-                             -> T {
+        fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+                             -> DecodeResult<T> {
             debug!("read_tuple_arg(idx={})", idx);
             self.read_seq_elt(idx, f)
         }
 
         fn read_tuple_struct<T>(&mut self,
                                 name: &str,
-                                f: |&mut Decoder<'doc>, uint| -> T)
-                                -> T {
+                                f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
+                                -> DecodeResult<T> {
             debug!("read_tuple_struct(name={})", name);
             self.read_tuple(f)
         }
 
         fn read_tuple_struct_arg<T>(&mut self,
                                     idx: uint,
-                                    f: |&mut Decoder<'doc>| -> T)
-                                    -> T {
+                                    f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+                                    -> DecodeResult<T> {
             debug!("read_tuple_struct_arg(idx={})", idx);
             self.read_tuple_arg(idx, f)
         }
 
-        fn read_option<T>(&mut self, f: |&mut Decoder<'doc>, bool| -> T) -> T {
+        fn read_option<T>(&mut self,
+                          f: |&mut Decoder<'doc>, bool| -> DecodeResult<T>) -> DecodeResult<T> {
             debug!("read_option()");
             self.read_enum("Option", |this| {
                 this.read_enum_variant(["None", "Some"], |this, idx| {
                     match idx {
                         0 => f(this, false),
                         1 => f(this, true),
-                        _ => fail!(),
+                        _ => Err(Expected(format!("Expected None or Some"))),
                     }
                 })
             })
         }
 
-        fn read_seq<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T {
+        fn read_seq<T>(&mut self,
+                       f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
             debug!("read_seq()");
             self.push_doc(EsVec, |d| {
-                let len = d._next_uint(EsVecLen);
+                let len = try!(d._next_uint(EsVecLen));
                 debug!("  len={}", len);
                 f(d, len)
             })
         }
 
-        fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
-                           -> T {
+        fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+                           -> DecodeResult<T> {
             debug!("read_seq_elt(idx={})", idx);
             self.push_doc(EsVecElt, f)
         }
 
-        fn read_map<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T {
+        fn read_map<T>(&mut self,
+                       f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
             debug!("read_map()");
             self.push_doc(EsMap, |d| {
-                let len = d._next_uint(EsMapLen);
+                let len = try!(d._next_uint(EsMapLen));
                 debug!("  len={}", len);
                 f(d, len)
             })
         }
 
-        fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
-                               -> T {
+        fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+                               -> DecodeResult<T> {
             debug!("read_map_elt_key(idx={})", idx);
             self.push_doc(EsMapKey, f)
         }
 
-        fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
-                               -> T {
+        fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+                               -> DecodeResult<T> {
             debug!("read_map_elt_val(idx={})", idx);
             self.push_doc(EsMapVal, f)
         }
@@ -593,7 +621,6 @@ pub mod writer {
     use std::clone::Clone;
     use std::io;
     use std::io::{Writer, Seek};
-    use std::io::MemWriter;
     use std::io::extensions::u64_to_be_bytes;
 
     use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey,
@@ -603,20 +630,16 @@ pub mod writer {
 
     use serialize;
 
+
+    pub type EncodeResult = io::IoResult<()>;
+
     // ebml writing
-    pub struct Encoder<'a> {
-        // FIXME(#5665): this should take a trait object. Note that if you
-        //               delete this comment you should consider removing the
-        //               unwrap()'s below of the results of the calls to
-        //               write(). We're guaranteed that writing into a MemWriter
-        //               won't fail, but this is not true for all I/O streams in
-        //               general.
-        writer: &'a mut MemWriter,
+    pub struct Encoder<'a, W> {
+        writer: &'a mut W,
         priv size_positions: ~[uint],
-        last_error: io::IoResult<()>,
     }
 
-    fn write_sized_vuint(w: &mut MemWriter, n: uint, size: uint) {
+    fn write_sized_vuint<W: Writer>(w: &mut W, n: uint, size: uint) -> EncodeResult {
         match size {
             1u => w.write(&[0x80u8 | (n as u8)]),
             2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]),
@@ -624,129 +647,136 @@ fn write_sized_vuint(w: &mut MemWriter, n: uint, size: uint) {
                             n as u8]),
             4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8,
                             (n >> 8_u) as u8, n as u8]),
-            _ => fail!("vint to write too big: {}", n)
-        }.unwrap()
+            _ => Err(io::IoError {
+                kind: io::OtherIoError,
+                desc: "int too big",
+                detail: Some(format!("{}", n))
+            })
+        }
     }
 
-    fn write_vuint(w: &mut MemWriter, n: uint) {
-        if n < 0x7f_u { write_sized_vuint(w, n, 1u); return; }
-        if n < 0x4000_u { write_sized_vuint(w, n, 2u); return; }
-        if n < 0x200000_u { write_sized_vuint(w, n, 3u); return; }
-        if n < 0x10000000_u { write_sized_vuint(w, n, 4u); return; }
-        fail!("vint to write too big: {}", n);
+    fn write_vuint<W: Writer>(w: &mut W, n: uint) -> EncodeResult {
+        if n < 0x7f_u { return write_sized_vuint(w, n, 1u); }
+        if n < 0x4000_u { return write_sized_vuint(w, n, 2u); }
+        if n < 0x200000_u { return write_sized_vuint(w, n, 3u); }
+        if n < 0x10000000_u { return write_sized_vuint(w, n, 4u); }
+        Err(io::IoError {
+            kind: io::OtherIoError,
+            desc: "int too big",
+            detail: Some(format!("{}", n))
+        })
     }
 
-    pub fn Encoder<'a>(w: &'a mut MemWriter) -> Encoder<'a> {
+    pub fn Encoder<'a, W: Writer + Seek>(w: &'a mut W) -> Encoder<'a, W> {
         let size_positions: ~[uint] = ~[];
         Encoder {
             writer: w,
             size_positions: size_positions,
-            last_error: Ok(()),
         }
     }
 
     // FIXME (#2741): Provide a function to write the standard ebml header.
-    impl<'a> Encoder<'a> {
+    impl<'a, W: Writer + Seek> Encoder<'a, W> {
         /// FIXME(pcwalton): Workaround for badness in trans. DO NOT USE ME.
-        pub unsafe fn unsafe_clone(&self) -> Encoder<'a> {
+        pub unsafe fn unsafe_clone(&self) -> Encoder<'a, W> {
             Encoder {
                 writer: cast::transmute_copy(&self.writer),
                 size_positions: self.size_positions.clone(),
-                last_error: Ok(()),
             }
         }
 
-        pub fn start_tag(&mut self, tag_id: uint) {
+        pub fn start_tag(&mut self, tag_id: uint) -> EncodeResult {
             debug!("Start tag {}", tag_id);
 
             // Write the enum ID:
-            write_vuint(self.writer, tag_id);
+            try!(write_vuint(self.writer, tag_id));
 
             // Write a placeholder four-byte size.
             self.size_positions.push(try!(self.writer.tell()) as uint);
             let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8];
-            try!(self.writer.write(zeroes));
+            self.writer.write(zeroes)
         }
 
-        pub fn end_tag(&mut self) {
+        pub fn end_tag(&mut self) -> EncodeResult {
             let last_size_pos = self.size_positions.pop().unwrap();
             let cur_pos = try!(self.writer.tell());
             try!(self.writer.seek(last_size_pos as i64, io::SeekSet));
             let size = cur_pos as uint - last_size_pos - 4;
-            write_sized_vuint(self.writer, size, 4u);
-            try!(self.writer.seek(cur_pos as i64, io::SeekSet));
+            try!(write_sized_vuint(self.writer, size, 4u));
+            let r = try!(self.writer.seek(cur_pos as i64, io::SeekSet));
 
             debug!("End tag (size = {})", size);
+            Ok(r)
         }
 
-        pub fn wr_tag(&mut self, tag_id: uint, blk: ||) {
-            self.start_tag(tag_id);
-            blk();
-            self.end_tag();
+        pub fn wr_tag(&mut self, tag_id: uint, blk: || -> EncodeResult) -> EncodeResult {
+            try!(self.start_tag(tag_id));
+            try!(blk());
+            self.end_tag()
         }
 
-        pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) {
-            write_vuint(self.writer, tag_id);
-            write_vuint(self.writer, b.len());
-            self.writer.write(b).unwrap();
+        pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) -> EncodeResult {
+            try!(write_vuint(self.writer, tag_id));
+            try!(write_vuint(self.writer, b.len()));
+            self.writer.write(b)
         }
 
-        pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) {
+        pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) -> EncodeResult {
             u64_to_be_bytes(v, 8u, |v| {
-                self.wr_tagged_bytes(tag_id, v);
+                self.wr_tagged_bytes(tag_id, v)
             })
         }
 
-        pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) {
+        pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32)  -> EncodeResult{
             u64_to_be_bytes(v as u64, 4u, |v| {
-                self.wr_tagged_bytes(tag_id, v);
+                self.wr_tagged_bytes(tag_id, v)
             })
         }
 
-        pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) {
+        pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) -> EncodeResult {
             u64_to_be_bytes(v as u64, 2u, |v| {
-                self.wr_tagged_bytes(tag_id, v);
+                self.wr_tagged_bytes(tag_id, v)
             })
         }
 
-        pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) {
-            self.wr_tagged_bytes(tag_id, &[v]);
+        pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) -> EncodeResult {
+            self.wr_tagged_bytes(tag_id, &[v])
         }
 
-        pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) {
+        pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) -> EncodeResult {
             u64_to_be_bytes(v as u64, 8u, |v| {
-                self.wr_tagged_bytes(tag_id, v);
+                self.wr_tagged_bytes(tag_id, v)
             })
         }
 
-        pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) {
+        pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) -> EncodeResult {
             u64_to_be_bytes(v as u64, 4u, |v| {
-                self.wr_tagged_bytes(tag_id, v);
+                self.wr_tagged_bytes(tag_id, v)
             })
         }
 
-        pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) {
+        pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) -> EncodeResult {
             u64_to_be_bytes(v as u64, 2u, |v| {
-                self.wr_tagged_bytes(tag_id, v);
+                self.wr_tagged_bytes(tag_id, v)
             })
         }
 
-        pub fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) {
-            self.wr_tagged_bytes(tag_id, &[v as u8]);
+        pub fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) -> EncodeResult {
+            self.wr_tagged_bytes(tag_id, &[v as u8])
         }
 
-        pub fn wr_tagged_str(&mut self, tag_id: uint, v: &str) {
-            self.wr_tagged_bytes(tag_id, v.as_bytes());
+        pub fn wr_tagged_str(&mut self, tag_id: uint, v: &str) -> EncodeResult {
+            self.wr_tagged_bytes(tag_id, v.as_bytes())
         }
 
-        pub fn wr_bytes(&mut self, b: &[u8]) {
+        pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult {
             debug!("Write {} bytes", b.len());
-            self.writer.write(b).unwrap();
+            self.writer.write(b)
         }
 
-        pub fn wr_str(&mut self, s: &str) {
+        pub fn wr_str(&mut self, s: &str) -> EncodeResult {
             debug!("Write str: {}", s);
-            self.writer.write(s.as_bytes()).unwrap();
+            self.writer.write(s.as_bytes())
         }
     }
 
@@ -757,14 +787,14 @@ pub fn wr_str(&mut self, s: &str) {
     // Totally lame approach.
     static DEBUG: bool = true;
 
-    impl<'a> Encoder<'a> {
+    impl<'a, W: Writer + Seek> Encoder<'a, W> {
         // used internally to emit things like the vector length and so on
-        fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) {
+        fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) -> EncodeResult {
             assert!(v <= 0xFFFF_FFFF_u);
-            self.wr_tagged_u32(t as uint, v as u32);
+            self.wr_tagged_u32(t as uint, v as u32)
         }
 
-        fn _emit_label(&mut self, label: &str) {
+        fn _emit_label(&mut self, label: &str) -> EncodeResult {
             // There are various strings that we have access to, such as
             // the name of a record field, which do not actually appear in
             // the encoded EBML (normally).  This is just for
@@ -772,89 +802,96 @@ fn _emit_label(&mut self, label: &str) {
             // labels and then they will be checked by decoder to
             // try and check failures more quickly.
             if DEBUG { self.wr_tagged_str(EsLabel as uint, label) }
+            else { Ok(()) }
         }
 
-        pub fn emit_opaque(&mut self, f: |&mut Encoder|) {
-            self.start_tag(EsOpaque as uint);
-            f(self);
-            self.end_tag();
+        pub fn emit_opaque(&mut self, f: |&mut Encoder<W>| -> EncodeResult) -> EncodeResult {
+            try!(self.start_tag(EsOpaque as uint));
+            try!(f(self));
+            self.end_tag()
         }
     }
 
-    impl<'a> serialize::Encoder for Encoder<'a> {
-        fn emit_nil(&mut self) {}
+    impl<'a, W: Writer + Seek> serialize::Encoder<io::IoError> for Encoder<'a, W> {
+        fn emit_nil(&mut self) -> EncodeResult {
+            Ok(())
+        }
 
-        fn emit_uint(&mut self, v: uint) {
-            self.wr_tagged_u64(EsUint as uint, v as u64);
+        fn emit_uint(&mut self, v: uint) -> EncodeResult {
+            self.wr_tagged_u64(EsUint as uint, v as u64)
         }
-        fn emit_u64(&mut self, v: u64) {
-            self.wr_tagged_u64(EsU64 as uint, v);
+        fn emit_u64(&mut self, v: u64) -> EncodeResult {
+            self.wr_tagged_u64(EsU64 as uint, v)
         }
-        fn emit_u32(&mut self, v: u32) {
-            self.wr_tagged_u32(EsU32 as uint, v);
+        fn emit_u32(&mut self, v: u32) -> EncodeResult {
+            self.wr_tagged_u32(EsU32 as uint, v)
         }
-        fn emit_u16(&mut self, v: u16) {
-            self.wr_tagged_u16(EsU16 as uint, v);
+        fn emit_u16(&mut self, v: u16) -> EncodeResult {
+            self.wr_tagged_u16(EsU16 as uint, v)
         }
-        fn emit_u8(&mut self, v: u8) {
-            self.wr_tagged_u8(EsU8 as uint, v);
+        fn emit_u8(&mut self, v: u8) -> EncodeResult {
+            self.wr_tagged_u8(EsU8 as uint, v)
         }
 
-        fn emit_int(&mut self, v: int) {
-            self.wr_tagged_i64(EsInt as uint, v as i64);
+        fn emit_int(&mut self, v: int) -> EncodeResult {
+            self.wr_tagged_i64(EsInt as uint, v as i64)
         }
-        fn emit_i64(&mut self, v: i64) {
-            self.wr_tagged_i64(EsI64 as uint, v);
+        fn emit_i64(&mut self, v: i64) -> EncodeResult {
+            self.wr_tagged_i64(EsI64 as uint, v)
         }
-        fn emit_i32(&mut self, v: i32) {
-            self.wr_tagged_i32(EsI32 as uint, v);
+        fn emit_i32(&mut self, v: i32) -> EncodeResult {
+            self.wr_tagged_i32(EsI32 as uint, v)
         }
-        fn emit_i16(&mut self, v: i16) {
-            self.wr_tagged_i16(EsI16 as uint, v);
+        fn emit_i16(&mut self, v: i16) -> EncodeResult {
+            self.wr_tagged_i16(EsI16 as uint, v)
         }
-        fn emit_i8(&mut self, v: i8) {
-            self.wr_tagged_i8(EsI8 as uint, v);
+        fn emit_i8(&mut self, v: i8) -> EncodeResult {
+            self.wr_tagged_i8(EsI8 as uint, v)
         }
 
-        fn emit_bool(&mut self, v: bool) {
+        fn emit_bool(&mut self, v: bool) -> EncodeResult {
             self.wr_tagged_u8(EsBool as uint, v as u8)
         }
 
-        fn emit_f64(&mut self, v: f64) {
+        fn emit_f64(&mut self, v: f64) -> EncodeResult {
             let bits = unsafe { cast::transmute(v) };
-            self.wr_tagged_u64(EsF64 as uint, bits);
+            self.wr_tagged_u64(EsF64 as uint, bits)
         }
-        fn emit_f32(&mut self, v: f32) {
+        fn emit_f32(&mut self, v: f32) -> EncodeResult {
             let bits = unsafe { cast::transmute(v) };
-            self.wr_tagged_u32(EsF32 as uint, bits);
+            self.wr_tagged_u32(EsF32 as uint, bits)
         }
-        fn emit_char(&mut self, v: char) {
-            self.wr_tagged_u32(EsChar as uint, v as u32);
+        fn emit_char(&mut self, v: char) -> EncodeResult {
+            self.wr_tagged_u32(EsChar as uint, v as u32)
         }
 
-        fn emit_str(&mut self, v: &str) {
+        fn emit_str(&mut self, v: &str) -> EncodeResult {
             self.wr_tagged_str(EsStr as uint, v)
         }
 
-        fn emit_enum(&mut self, name: &str, f: |&mut Encoder<'a>|) {
-            self._emit_label(name);
-            self.start_tag(EsEnum as uint);
-            f(self);
-            self.end_tag();
+        fn emit_enum(&mut self,
+                     name: &str,
+                     f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
+            try!(self._emit_label(name));
+            try!(self.start_tag(EsEnum as uint));
+            try!(f(self));
+            self.end_tag()
         }
 
         fn emit_enum_variant(&mut self,
                              _: &str,
                              v_id: uint,
                              _: uint,
-                             f: |&mut Encoder<'a>|) {
-            self._emit_tagged_uint(EsEnumVid, v_id);
-            self.start_tag(EsEnumBody as uint);
-            f(self);
-            self.end_tag();
+                             f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
+            try!(self._emit_tagged_uint(EsEnumVid, v_id));
+            try!(self.start_tag(EsEnumBody as uint));
+            try!(f(self));
+            self.end_tag()
         }
 
-        fn emit_enum_variant_arg(&mut self, _: uint, f: |&mut Encoder<'a>|) {
+        fn emit_enum_variant_arg(&mut self,
+                                 _: uint,
+                                 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
             f(self)
         }
 
@@ -862,91 +899,113 @@ fn emit_enum_struct_variant(&mut self,
                                     v_name: &str,
                                     v_id: uint,
                                     cnt: uint,
-                                    f: |&mut Encoder<'a>|) {
+                                    f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
             self.emit_enum_variant(v_name, v_id, cnt, f)
         }
 
         fn emit_enum_struct_variant_field(&mut self,
                                           _: &str,
                                           idx: uint,
-                                          f: |&mut Encoder<'a>|) {
+                                          f: |&mut Encoder<'a, W>| -> EncodeResult)
+            -> EncodeResult {
             self.emit_enum_variant_arg(idx, f)
         }
 
         fn emit_struct(&mut self,
                        _: &str,
                        _len: uint,
-                       f: |&mut Encoder<'a>|) {
+                       f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
             f(self)
         }
 
         fn emit_struct_field(&mut self,
                              name: &str,
                              _: uint,
-                             f: |&mut Encoder<'a>|) {
-            self._emit_label(name);
+                             f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
+            try!(self._emit_label(name));
             f(self)
         }
 
-        fn emit_tuple(&mut self, len: uint, f: |&mut Encoder<'a>|) {
+        fn emit_tuple(&mut self,
+                      len: uint,
+                      f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
             self.emit_seq(len, f)
         }
-        fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+        fn emit_tuple_arg(&mut self,
+                          idx: uint,
+                          f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
             self.emit_seq_elt(idx, f)
         }
 
         fn emit_tuple_struct(&mut self,
                              _: &str,
                              len: uint,
-                             f: |&mut Encoder<'a>|) {
+                             f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
             self.emit_seq(len, f)
         }
         fn emit_tuple_struct_arg(&mut self,
                                  idx: uint,
-                                 f: |&mut Encoder<'a>|) {
+                                 f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
             self.emit_seq_elt(idx, f)
         }
 
-        fn emit_option(&mut self, f: |&mut Encoder<'a>|) {
-            self.emit_enum("Option", f);
+        fn emit_option(&mut self,
+                       f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
+            self.emit_enum("Option", f)
         }
-        fn emit_option_none(&mut self) {
-            self.emit_enum_variant("None", 0, 0, |_| ())
+        fn emit_option_none(&mut self) -> EncodeResult {
+            self.emit_enum_variant("None", 0, 0, |_| Ok(()))
         }
-        fn emit_option_some(&mut self, f: |&mut Encoder<'a>|) {
+        fn emit_option_some(&mut self,
+                            f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
+
             self.emit_enum_variant("Some", 1, 1, f)
         }
 
-        fn emit_seq(&mut self, len: uint, f: |&mut Encoder<'a>|) {
-            self.start_tag(EsVec as uint);
-            self._emit_tagged_uint(EsVecLen, len);
-            f(self);
-            self.end_tag();
+        fn emit_seq(&mut self,
+                    len: uint,
+                    f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
+
+            try!(self.start_tag(EsVec as uint));
+            try!(self._emit_tagged_uint(EsVecLen, len));
+            try!(f(self));
+            self.end_tag()
         }
 
-        fn emit_seq_elt(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
-            self.start_tag(EsVecElt as uint);
-            f(self);
-            self.end_tag();
+        fn emit_seq_elt(&mut self,
+                        _idx: uint,
+                        f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
+
+            try!(self.start_tag(EsVecElt as uint));
+            try!(f(self));
+            self.end_tag()
         }
 
-        fn emit_map(&mut self, len: uint, f: |&mut Encoder<'a>|) {
-            self.start_tag(EsMap as uint);
-            self._emit_tagged_uint(EsMapLen, len);
-            f(self);
-            self.end_tag();
+        fn emit_map(&mut self,
+                    len: uint,
+                    f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
+
+            try!(self.start_tag(EsMap as uint));
+            try!(self._emit_tagged_uint(EsMapLen, len));
+            try!(f(self));
+            self.end_tag()
         }
 
-        fn emit_map_elt_key(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
-            self.start_tag(EsMapKey as uint);
-            f(self);
-            self.end_tag();
+        fn emit_map_elt_key(&mut self,
+                            _idx: uint,
+                            f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
+
+            try!(self.start_tag(EsMapKey as uint));
+            try!(f(self));
+            self.end_tag()
         }
 
-        fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
-            self.start_tag(EsMapVal as uint);
-            f(self);
-            self.end_tag();
+        fn emit_map_elt_val(&mut self,
+                            _idx: uint,
+                            f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
+            try!(self.start_tag(EsMapVal as uint));
+            try!(f(self));
+            self.end_tag()
         }
     }
 }
@@ -979,34 +1038,34 @@ fn test_vuint_at() {
         let mut res: reader::Res;
 
         // Class A
-        res = reader::vuint_at(data, 0);
+        res = reader::vuint_at(data, 0).unwrap();
         assert_eq!(res.val, 0);
         assert_eq!(res.next, 1);
-        res = reader::vuint_at(data, res.next);
+        res = reader::vuint_at(data, res.next).unwrap();
         assert_eq!(res.val, (1 << 7) - 1);
         assert_eq!(res.next, 2);
 
         // Class B
-        res = reader::vuint_at(data, res.next);
+        res = reader::vuint_at(data, res.next).unwrap();
         assert_eq!(res.val, 0);
         assert_eq!(res.next, 4);
-        res = reader::vuint_at(data, res.next);
+        res = reader::vuint_at(data, res.next).unwrap();
         assert_eq!(res.val, (1 << 14) - 1);
         assert_eq!(res.next, 6);
 
         // Class C
-        res = reader::vuint_at(data, res.next);
+        res = reader::vuint_at(data, res.next).unwrap();
         assert_eq!(res.val, 0);
         assert_eq!(res.next, 9);
-        res = reader::vuint_at(data, res.next);
+        res = reader::vuint_at(data, res.next).unwrap();
         assert_eq!(res.val, (1 << 21) - 1);
         assert_eq!(res.next, 12);
 
         // Class D
-        res = reader::vuint_at(data, res.next);
+        res = reader::vuint_at(data, res.next).unwrap();
         assert_eq!(res.val, 0);
         assert_eq!(res.next, 16);
-        res = reader::vuint_at(data, res.next);
+        res = reader::vuint_at(data, res.next).unwrap();
         assert_eq!(res.val, (1 << 28) - 1);
         assert_eq!(res.next, 20);
     }
@@ -1018,11 +1077,11 @@ fn test_v(v: Option<int>) {
             let mut wr = MemWriter::new();
             {
                 let mut ebml_w = writer::Encoder(&mut wr);
-                v.encode(&mut ebml_w);
+                let _ = v.encode(&mut ebml_w);
             }
             let ebml_doc = reader::Doc(wr.get_ref());
             let mut deser = reader::Decoder(ebml_doc);
-            let v1 = Decodable::decode(&mut deser);
+            let v1 = Decodable::decode(&mut deser).unwrap();
             debug!("v1 == {:?}", v1);
             assert_eq!(v, v1);
         }
@@ -1052,7 +1111,7 @@ pub fn vuint_at_A_aligned(bh: &mut BenchHarness) {
         bh.iter(|| {
             let mut i = 0;
             while i < data.len() {
-                sum += reader::vuint_at(data, i).val;
+                sum += reader::vuint_at(data, i).unwrap().val;
                 i += 4;
             }
         });
@@ -1071,7 +1130,7 @@ pub fn vuint_at_A_unaligned(bh: &mut BenchHarness) {
         bh.iter(|| {
             let mut i = 1;
             while i < data.len() {
-                sum += reader::vuint_at(data, i).val;
+                sum += reader::vuint_at(data, i).unwrap().val;
                 i += 4;
             }
         });
@@ -1091,7 +1150,7 @@ pub fn vuint_at_D_aligned(bh: &mut BenchHarness) {
         bh.iter(|| {
             let mut i = 0;
             while i < data.len() {
-                sum += reader::vuint_at(data, i).val;
+                sum += reader::vuint_at(data, i).unwrap().val;
                 i += 4;
             }
         });
@@ -1111,7 +1170,7 @@ pub fn vuint_at_D_unaligned(bh: &mut BenchHarness) {
         bh.iter(|| {
             let mut i = 1;
             while i < data.len() {
-                sum += reader::vuint_at(data, i).val;
+                sum += reader::vuint_at(data, i).unwrap().val;
                 i += 4;
             }
         });
diff --git a/src/libserialize/ebml_old.rs b/src/libserialize/ebml_old.rs
new file mode 100644 (file)
index 0000000..1c66960
--- /dev/null
@@ -0,0 +1,1120 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[allow(missing_doc)];
+
+use std::str;
+
+macro_rules! try( ($e:expr) => (
+    match $e { Ok(e) => e, Err(e) => { self.last_error = Err(e); return } }
+) )
+
+// Simple Extensible Binary Markup Language (ebml) reader and writer on a
+// cursor model. See the specification here:
+//     http://www.matroska.org/technical/specs/rfc/index.html
+
+// Common data structures
+#[deriving(Clone)]
+pub struct Doc<'a> {
+    data: &'a [u8],
+    start: uint,
+    end: uint,
+}
+
+impl<'doc> Doc<'doc> {
+    pub fn get<'a>(&'a self, tag: uint) -> Doc<'a> {
+        reader::get_doc(*self, tag)
+    }
+
+    pub fn as_str_slice<'a>(&'a self) -> &'a str {
+        str::from_utf8(self.data.slice(self.start, self.end)).unwrap()
+    }
+
+    pub fn as_str(&self) -> ~str {
+        self.as_str_slice().to_owned()
+    }
+}
+
+pub struct TaggedDoc<'a> {
+    priv tag: uint,
+    doc: Doc<'a>,
+}
+
+pub enum EbmlEncoderTag {
+    EsUint,     // 0
+    EsU64,      // 1
+    EsU32,      // 2
+    EsU16,      // 3
+    EsU8,       // 4
+    EsInt,      // 5
+    EsI64,      // 6
+    EsI32,      // 7
+    EsI16,      // 8
+    EsI8,       // 9
+    EsBool,     // 10
+    EsChar,     // 11
+    EsStr,      // 12
+    EsF64,      // 13
+    EsF32,      // 14
+    EsFloat,    // 15
+    EsEnum,     // 16
+    EsEnumVid,  // 17
+    EsEnumBody, // 18
+    EsVec,      // 19
+    EsVecLen,   // 20
+    EsVecElt,   // 21
+    EsMap,      // 22
+    EsMapLen,   // 23
+    EsMapKey,   // 24
+    EsMapVal,   // 25
+
+    EsOpaque,
+
+    EsLabel, // Used only when debugging
+}
+// --------------------------------------
+
+pub mod reader {
+    use std::char;
+
+    use std::cast::transmute;
+    use std::int;
+    use std::option::{None, Option, Some};
+    use std::io::extensions::u64_from_be_bytes;
+
+    use serialize;
+
+    use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey,
+        EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8,
+        EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint,
+        EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc };
+
+    // ebml reading
+
+    pub struct Res {
+        val: uint,
+        next: uint
+    }
+
+    #[inline(never)]
+    fn vuint_at_slow(data: &[u8], start: uint) -> Res {
+        let a = data[start];
+        if a & 0x80u8 != 0u8 {
+            return Res {val: (a & 0x7fu8) as uint, next: start + 1u};
+        }
+        if a & 0x40u8 != 0u8 {
+            return Res {val: ((a & 0x3fu8) as uint) << 8u |
+                        (data[start + 1u] as uint),
+                    next: start + 2u};
+        }
+        if a & 0x20u8 != 0u8 {
+            return Res {val: ((a & 0x1fu8) as uint) << 16u |
+                        (data[start + 1u] as uint) << 8u |
+                        (data[start + 2u] as uint),
+                    next: start + 3u};
+        }
+        if a & 0x10u8 != 0u8 {
+            return Res {val: ((a & 0x0fu8) as uint) << 24u |
+                        (data[start + 1u] as uint) << 16u |
+                        (data[start + 2u] as uint) << 8u |
+                        (data[start + 3u] as uint),
+                    next: start + 4u};
+        }
+        fail!("vint too big");
+    }
+
+    pub fn vuint_at(data: &[u8], start: uint) -> Res {
+        use std::mem::from_be32;
+
+        if data.len() - start < 4 {
+            return vuint_at_slow(data, start);
+        }
+
+        // Lookup table for parsing EBML Element IDs as per http://ebml.sourceforge.net/specs/
+        // The Element IDs are parsed by reading a big endian u32 positioned at data[start].
+        // Using the four most significant bits of the u32 we lookup in the table below how the
+        // element ID should be derived from it.
+        //
+        // The table stores tuples (shift, mask) where shift is the number the u32 should be right
+        // shifted with and mask is the value the right shifted value should be masked with.
+        // If for example the most significant bit is set this means it's a class A ID and the u32
+        // should be right shifted with 24 and masked with 0x7f. Therefore we store (24, 0x7f) at
+        // index 0x8 - 0xF (four bit numbers where the most significant bit is set).
+        //
+        // By storing the number of shifts and masks in a table instead of checking in order if
+        // the most significant bit is set, the second most significant bit is set etc. we can
+        // replace up to three "and+branch" with a single table lookup which gives us a measured
+        // speedup of around 2x on x86_64.
+        static SHIFT_MASK_TABLE: [(u32, u32), ..16] = [
+            (0, 0x0), (0, 0x0fffffff),
+            (8, 0x1fffff), (8, 0x1fffff),
+            (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff),
+            (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f),
+            (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f)
+        ];
+
+        unsafe {
+            let ptr = data.as_ptr().offset(start as int) as *i32;
+            let val = from_be32(*ptr) as u32;
+
+            let i = (val >> 28u) as uint;
+            let (shift, mask) = SHIFT_MASK_TABLE[i];
+            Res {
+                val: ((val >> shift) & mask) as uint,
+                next: start + (((32 - shift) >> 3) as uint)
+            }
+        }
+    }
+
+    pub fn Doc<'a>(data: &'a [u8]) -> Doc<'a> {
+        Doc { data: data, start: 0u, end: data.len() }
+    }
+
+    pub fn doc_at<'a>(data: &'a [u8], start: uint) -> TaggedDoc<'a> {
+        let elt_tag = vuint_at(data, start);
+        let elt_size = vuint_at(data, elt_tag.next);
+        let end = elt_size.next + elt_size.val;
+        TaggedDoc {
+            tag: elt_tag.val,
+            doc: Doc { data: data, start: elt_size.next, end: end }
+        }
+    }
+
+    pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: uint) -> Option<Doc<'a>> {
+        let mut pos = d.start;
+        while pos < d.end {
+            let elt_tag = vuint_at(d.data, pos);
+            let elt_size = vuint_at(d.data, elt_tag.next);
+            pos = elt_size.next + elt_size.val;
+            if elt_tag.val == tg {
+                return Some(Doc { data: d.data, start: elt_size.next,
+                                  end: pos });
+            }
+        }
+        None
+    }
+
+    pub fn get_doc<'a>(d: Doc<'a>, tg: uint) -> Doc<'a> {
+        match maybe_get_doc(d, tg) {
+            Some(d) => d,
+            None => {
+                error!("failed to find block with tag {}", tg);
+                fail!();
+            }
+        }
+    }
+
+    pub fn docs<'a>(d: Doc<'a>, it: |uint, Doc<'a>| -> bool) -> bool {
+        let mut pos = d.start;
+        while pos < d.end {
+            let elt_tag = vuint_at(d.data, pos);
+            let elt_size = vuint_at(d.data, elt_tag.next);
+            pos = elt_size.next + elt_size.val;
+            let doc = Doc { data: d.data, start: elt_size.next, end: pos };
+            if !it(elt_tag.val, doc) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    pub fn tagged_docs<'a>(d: Doc<'a>, tg: uint, it: |Doc<'a>| -> bool) -> bool {
+        let mut pos = d.start;
+        while pos < d.end {
+            let elt_tag = vuint_at(d.data, pos);
+            let elt_size = vuint_at(d.data, elt_tag.next);
+            pos = elt_size.next + elt_size.val;
+            if elt_tag.val == tg {
+                let doc = Doc { data: d.data, start: elt_size.next,
+                                end: pos };
+                if !it(doc) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    pub fn with_doc_data<'a, T>(d: Doc<'a>, f: |x: &'a [u8]| -> T) -> T {
+        f(d.data.slice(d.start, d.end))
+    }
+
+
+    pub fn doc_as_u8(d: Doc) -> u8 {
+        assert_eq!(d.end, d.start + 1u);
+        d.data[d.start]
+    }
+
+    pub fn doc_as_u16(d: Doc) -> u16 {
+        assert_eq!(d.end, d.start + 2u);
+        u64_from_be_bytes(d.data, d.start, 2u) as u16
+    }
+
+    pub fn doc_as_u32(d: Doc) -> u32 {
+        assert_eq!(d.end, d.start + 4u);
+        u64_from_be_bytes(d.data, d.start, 4u) as u32
+    }
+
+    pub fn doc_as_u64(d: Doc) -> u64 {
+        assert_eq!(d.end, d.start + 8u);
+        u64_from_be_bytes(d.data, d.start, 8u)
+    }
+
+    pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
+    pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 }
+    pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 }
+    pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 }
+
+    pub struct Decoder<'a> {
+        priv parent: Doc<'a>,
+        priv pos: uint,
+    }
+
+    pub fn Decoder<'a>(d: Doc<'a>) -> Decoder<'a> {
+        Decoder {
+            parent: d,
+            pos: d.start
+        }
+    }
+
+    impl<'doc> Decoder<'doc> {
+        fn _check_label(&mut self, lbl: &str) {
+            if self.pos < self.parent.end {
+                let TaggedDoc { tag: r_tag, doc: r_doc } =
+                    doc_at(self.parent.data, self.pos);
+
+                if r_tag == (EsLabel as uint) {
+                    self.pos = r_doc.end;
+                    let str = r_doc.as_str_slice();
+                    if lbl != str {
+                        fail!("Expected label {} but found {}", lbl, str);
+                    }
+                }
+            }
+        }
+
+        fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> Doc<'doc> {
+            debug!(". next_doc(exp_tag={:?})", exp_tag);
+            if self.pos >= self.parent.end {
+                fail!("no more documents in current node!");
+            }
+            let TaggedDoc { tag: r_tag, doc: r_doc } =
+                doc_at(self.parent.data, self.pos);
+            debug!("self.parent={}-{} self.pos={} r_tag={} r_doc={}-{}",
+                   self.parent.start,
+                   self.parent.end,
+                   self.pos,
+                   r_tag,
+                   r_doc.start,
+                   r_doc.end);
+            if r_tag != (exp_tag as uint) {
+                fail!("expected EBML doc with tag {:?} but found tag {:?}",
+                       exp_tag, r_tag);
+            }
+            if r_doc.end > self.parent.end {
+                fail!("invalid EBML, child extends to {:#x}, parent to {:#x}",
+                      r_doc.end, self.parent.end);
+            }
+            self.pos = r_doc.end;
+            r_doc
+        }
+
+        fn push_doc<T>(&mut self, exp_tag: EbmlEncoderTag,
+                       f: |&mut Decoder<'doc>| -> T) -> T {
+            let d = self.next_doc(exp_tag);
+            let old_parent = self.parent;
+            let old_pos = self.pos;
+            self.parent = d;
+            self.pos = d.start;
+            let r = f(self);
+            self.parent = old_parent;
+            self.pos = old_pos;
+            r
+        }
+
+        fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> uint {
+            let r = doc_as_u32(self.next_doc(exp_tag));
+            debug!("_next_uint exp_tag={:?} result={}", exp_tag, r);
+            r as uint
+        }
+
+        pub fn read_opaque<R>(&mut self, op: |&mut Decoder<'doc>, Doc| -> R) -> R {
+            let doc = self.next_doc(EsOpaque);
+
+            let (old_parent, old_pos) = (self.parent, self.pos);
+            self.parent = doc;
+            self.pos = doc.start;
+
+            let result = op(self, doc);
+
+            self.parent = old_parent;
+            self.pos = old_pos;
+            result
+        }
+    }
+
+    impl<'doc> serialize::Decoder for Decoder<'doc> {
+        fn read_nil(&mut self) -> () { () }
+
+        fn read_u64(&mut self) -> u64 { doc_as_u64(self.next_doc(EsU64)) }
+        fn read_u32(&mut self) -> u32 { doc_as_u32(self.next_doc(EsU32)) }
+        fn read_u16(&mut self) -> u16 { doc_as_u16(self.next_doc(EsU16)) }
+        fn read_u8 (&mut self) -> u8  { doc_as_u8 (self.next_doc(EsU8 )) }
+        fn read_uint(&mut self) -> uint {
+            let v = doc_as_u64(self.next_doc(EsUint));
+            if v > (::std::uint::MAX as u64) {
+                fail!("uint {} too large for this architecture", v);
+            }
+            v as uint
+        }
+
+        fn read_i64(&mut self) -> i64 {
+            doc_as_u64(self.next_doc(EsI64)) as i64
+        }
+        fn read_i32(&mut self) -> i32 {
+            doc_as_u32(self.next_doc(EsI32)) as i32
+        }
+        fn read_i16(&mut self) -> i16 {
+            doc_as_u16(self.next_doc(EsI16)) as i16
+        }
+        fn read_i8 (&mut self) -> i8 {
+            doc_as_u8(self.next_doc(EsI8 )) as i8
+        }
+        fn read_int(&mut self) -> int {
+            let v = doc_as_u64(self.next_doc(EsInt)) as i64;
+            if v > (int::MAX as i64) || v < (int::MIN as i64) {
+                debug!("FIXME \\#6122: Removing this makes this function miscompile");
+                fail!("int {} out of range for this architecture", v);
+            }
+            v as int
+        }
+
+        fn read_bool(&mut self) -> bool {
+            doc_as_u8(self.next_doc(EsBool)) != 0
+        }
+
+        fn read_f64(&mut self) -> f64 {
+            let bits = doc_as_u64(self.next_doc(EsF64));
+            unsafe { transmute(bits) }
+        }
+        fn read_f32(&mut self) -> f32 {
+            let bits = doc_as_u32(self.next_doc(EsF32));
+            unsafe { transmute(bits) }
+        }
+        fn read_char(&mut self) -> char {
+            char::from_u32(doc_as_u32(self.next_doc(EsChar))).unwrap()
+        }
+        fn read_str(&mut self) -> ~str {
+            self.next_doc(EsStr).as_str()
+        }
+
+        // Compound types:
+        fn read_enum<T>(&mut self, name: &str, f: |&mut Decoder<'doc>| -> T) -> T {
+            debug!("read_enum({})", name);
+            self._check_label(name);
+
+            let doc = self.next_doc(EsEnum);
+
+            let (old_parent, old_pos) = (self.parent, self.pos);
+            self.parent = doc;
+            self.pos = self.parent.start;
+
+            let result = f(self);
+
+            self.parent = old_parent;
+            self.pos = old_pos;
+            result
+        }
+
+        fn read_enum_variant<T>(&mut self,
+                                _: &[&str],
+                                f: |&mut Decoder<'doc>, uint| -> T)
+                                -> T {
+            debug!("read_enum_variant()");
+            let idx = self._next_uint(EsEnumVid);
+            debug!("  idx={}", idx);
+
+            let doc = self.next_doc(EsEnumBody);
+
+            let (old_parent, old_pos) = (self.parent, self.pos);
+            self.parent = doc;
+            self.pos = self.parent.start;
+
+            let result = f(self, idx);
+
+            self.parent = old_parent;
+            self.pos = old_pos;
+            result
+        }
+
+        fn read_enum_variant_arg<T>(&mut self,
+                                    idx: uint,
+                                    f: |&mut Decoder<'doc>| -> T) -> T {
+            debug!("read_enum_variant_arg(idx={})", idx);
+            f(self)
+        }
+
+        fn read_enum_struct_variant<T>(&mut self,
+                                       _: &[&str],
+                                       f: |&mut Decoder<'doc>, uint| -> T)
+                                       -> T {
+            debug!("read_enum_struct_variant()");
+            let idx = self._next_uint(EsEnumVid);
+            debug!("  idx={}", idx);
+
+            let doc = self.next_doc(EsEnumBody);
+
+            let (old_parent, old_pos) = (self.parent, self.pos);
+            self.parent = doc;
+            self.pos = self.parent.start;
+
+            let result = f(self, idx);
+
+            self.parent = old_parent;
+            self.pos = old_pos;
+            result
+        }
+
+        fn read_enum_struct_variant_field<T>(&mut self,
+                                             name: &str,
+                                             idx: uint,
+                                             f: |&mut Decoder<'doc>| -> T)
+                                             -> T {
+            debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
+            f(self)
+        }
+
+        fn read_struct<T>(&mut self,
+                          name: &str,
+                          _: uint,
+                          f: |&mut Decoder<'doc>| -> T)
+                          -> T {
+            debug!("read_struct(name={})", name);
+            f(self)
+        }
+
+        fn read_struct_field<T>(&mut self,
+                                name: &str,
+                                idx: uint,
+                                f: |&mut Decoder<'doc>| -> T)
+                                -> T {
+            debug!("read_struct_field(name={}, idx={})", name, idx);
+            self._check_label(name);
+            f(self)
+        }
+
+        fn read_tuple<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T {
+            debug!("read_tuple()");
+            self.read_seq(f)
+        }
+
+        fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
+                             -> T {
+            debug!("read_tuple_arg(idx={})", idx);
+            self.read_seq_elt(idx, f)
+        }
+
+        fn read_tuple_struct<T>(&mut self,
+                                name: &str,
+                                f: |&mut Decoder<'doc>, uint| -> T)
+                                -> T {
+            debug!("read_tuple_struct(name={})", name);
+            self.read_tuple(f)
+        }
+
+        fn read_tuple_struct_arg<T>(&mut self,
+                                    idx: uint,
+                                    f: |&mut Decoder<'doc>| -> T)
+                                    -> T {
+            debug!("read_tuple_struct_arg(idx={})", idx);
+            self.read_tuple_arg(idx, f)
+        }
+
+        fn read_option<T>(&mut self, f: |&mut Decoder<'doc>, bool| -> T) -> T {
+            debug!("read_option()");
+            self.read_enum("Option", |this| {
+                this.read_enum_variant(["None", "Some"], |this, idx| {
+                    match idx {
+                        0 => f(this, false),
+                        1 => f(this, true),
+                        _ => fail!(),
+                    }
+                })
+            })
+        }
+
+        fn read_seq<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T {
+            debug!("read_seq()");
+            self.push_doc(EsVec, |d| {
+                let len = d._next_uint(EsVecLen);
+                debug!("  len={}", len);
+                f(d, len)
+            })
+        }
+
+        fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
+                           -> T {
+            debug!("read_seq_elt(idx={})", idx);
+            self.push_doc(EsVecElt, f)
+        }
+
+        fn read_map<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T {
+            debug!("read_map()");
+            self.push_doc(EsMap, |d| {
+                let len = d._next_uint(EsMapLen);
+                debug!("  len={}", len);
+                f(d, len)
+            })
+        }
+
+        fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
+                               -> T {
+            debug!("read_map_elt_key(idx={})", idx);
+            self.push_doc(EsMapKey, f)
+        }
+
+        fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
+                               -> T {
+            debug!("read_map_elt_val(idx={})", idx);
+            self.push_doc(EsMapVal, f)
+        }
+    }
+}
+
+pub mod writer {
+    use std::cast;
+    use std::clone::Clone;
+    use std::io;
+    use std::io::{Writer, Seek};
+    use std::io::MemWriter;
+    use std::io::extensions::u64_to_be_bytes;
+
+    use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey,
+        EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8,
+        EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint,
+        EsOpaque, EsLabel, EbmlEncoderTag };
+
+    use serialize;
+
+    // ebml writing
+    pub struct Encoder<'a> {
+        // FIXME(#5665): this should take a trait object. Note that if you
+        //               delete this comment you should consider removing the
+        //               unwrap()'s below of the results of the calls to
+        //               write(). We're guaranteed that writing into a MemWriter
+        //               won't fail, but this is not true for all I/O streams in
+        //               general.
+        writer: &'a mut MemWriter,
+        priv size_positions: ~[uint],
+        last_error: io::IoResult<()>,
+    }
+
+    fn write_sized_vuint(w: &mut MemWriter, n: uint, size: uint) {
+        match size {
+            1u => w.write(&[0x80u8 | (n as u8)]),
+            2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]),
+            3u => w.write(&[0x20u8 | ((n >> 16_u) as u8), (n >> 8_u) as u8,
+                            n as u8]),
+            4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8,
+                            (n >> 8_u) as u8, n as u8]),
+            _ => fail!("vint to write too big: {}", n)
+        }.unwrap()
+    }
+
+    fn write_vuint(w: &mut MemWriter, n: uint) {
+        if n < 0x7f_u { write_sized_vuint(w, n, 1u); return; }
+        if n < 0x4000_u { write_sized_vuint(w, n, 2u); return; }
+        if n < 0x200000_u { write_sized_vuint(w, n, 3u); return; }
+        if n < 0x10000000_u { write_sized_vuint(w, n, 4u); return; }
+        fail!("vint to write too big: {}", n);
+    }
+
+    pub fn Encoder<'a>(w: &'a mut MemWriter) -> Encoder<'a> {
+        let size_positions: ~[uint] = ~[];
+        Encoder {
+            writer: w,
+            size_positions: size_positions,
+            last_error: Ok(()),
+        }
+    }
+
+    // FIXME (#2741): Provide a function to write the standard ebml header.
+    impl<'a> Encoder<'a> {
+        /// FIXME(pcwalton): Workaround for badness in trans. DO NOT USE ME.
+        pub unsafe fn unsafe_clone(&self) -> Encoder<'a> {
+            Encoder {
+                writer: cast::transmute_copy(&self.writer),
+                size_positions: self.size_positions.clone(),
+                last_error: Ok(()),
+            }
+        }
+
+        pub fn start_tag(&mut self, tag_id: uint) {
+            debug!("Start tag {}", tag_id);
+
+            // Write the enum ID:
+            write_vuint(self.writer, tag_id);
+
+            // Write a placeholder four-byte size.
+            self.size_positions.push(try!(self.writer.tell()) as uint);
+            let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8];
+            try!(self.writer.write(zeroes));
+        }
+
+        pub fn end_tag(&mut self) {
+            let last_size_pos = self.size_positions.pop().unwrap();
+            let cur_pos = try!(self.writer.tell());
+            try!(self.writer.seek(last_size_pos as i64, io::SeekSet));
+            let size = cur_pos as uint - last_size_pos - 4;
+            write_sized_vuint(self.writer, size, 4u);
+            try!(self.writer.seek(cur_pos as i64, io::SeekSet));
+
+            debug!("End tag (size = {})", size);
+        }
+
+        pub fn wr_tag(&mut self, tag_id: uint, blk: ||) {
+            self.start_tag(tag_id);
+            blk();
+            self.end_tag();
+        }
+
+        pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) {
+            write_vuint(self.writer, tag_id);
+            write_vuint(self.writer, b.len());
+            self.writer.write(b).unwrap();
+        }
+
+        pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) {
+            u64_to_be_bytes(v, 8u, |v| {
+                self.wr_tagged_bytes(tag_id, v);
+            })
+        }
+
+        pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) {
+            u64_to_be_bytes(v as u64, 4u, |v| {
+                self.wr_tagged_bytes(tag_id, v);
+            })
+        }
+
+        pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) {
+            u64_to_be_bytes(v as u64, 2u, |v| {
+                self.wr_tagged_bytes(tag_id, v);
+            })
+        }
+
+        pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) {
+            self.wr_tagged_bytes(tag_id, &[v]);
+        }
+
+        pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) {
+            u64_to_be_bytes(v as u64, 8u, |v| {
+                self.wr_tagged_bytes(tag_id, v);
+            })
+        }
+
+        pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) {
+            u64_to_be_bytes(v as u64, 4u, |v| {
+                self.wr_tagged_bytes(tag_id, v);
+            })
+        }
+
+        pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) {
+            u64_to_be_bytes(v as u64, 2u, |v| {
+                self.wr_tagged_bytes(tag_id, v);
+            })
+        }
+
+        pub fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) {
+            self.wr_tagged_bytes(tag_id, &[v as u8]);
+        }
+
+        pub fn wr_tagged_str(&mut self, tag_id: uint, v: &str) {
+            self.wr_tagged_bytes(tag_id, v.as_bytes());
+        }
+
+        pub fn wr_bytes(&mut self, b: &[u8]) {
+            debug!("Write {} bytes", b.len());
+            self.writer.write(b).unwrap();
+        }
+
+        pub fn wr_str(&mut self, s: &str) {
+            debug!("Write str: {}", s);
+            self.writer.write(s.as_bytes()).unwrap();
+        }
+    }
+
+    // FIXME (#2743): optionally perform "relaxations" on end_tag to more
+    // efficiently encode sizes; this is a fixed point iteration
+
+    // Set to true to generate more debugging in EBML code.
+    // Totally lame approach.
+    static DEBUG: bool = true;
+
+    impl<'a> Encoder<'a> {
+        // used internally to emit things like the vector length and so on
+        fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) {
+            assert!(v <= 0xFFFF_FFFF_u);
+            self.wr_tagged_u32(t as uint, v as u32);
+        }
+
+        fn _emit_label(&mut self, label: &str) {
+            // There are various strings that we have access to, such as
+            // the name of a record field, which do not actually appear in
+            // the encoded EBML (normally).  This is just for
+            // efficiency.  When debugging, though, we can emit such
+            // labels and then they will be checked by decoder to
+            // try and check failures more quickly.
+            if DEBUG { self.wr_tagged_str(EsLabel as uint, label) }
+        }
+
+        pub fn emit_opaque(&mut self, f: |&mut Encoder|) {
+            self.start_tag(EsOpaque as uint);
+            f(self);
+            self.end_tag();
+        }
+    }
+
+    impl<'a> serialize::Encoder for Encoder<'a> {
+        fn emit_nil(&mut self) {}
+
+        fn emit_uint(&mut self, v: uint) {
+            self.wr_tagged_u64(EsUint as uint, v as u64);
+        }
+        fn emit_u64(&mut self, v: u64) {
+            self.wr_tagged_u64(EsU64 as uint, v);
+        }
+        fn emit_u32(&mut self, v: u32) {
+            self.wr_tagged_u32(EsU32 as uint, v);
+        }
+        fn emit_u16(&mut self, v: u16) {
+            self.wr_tagged_u16(EsU16 as uint, v);
+        }
+        fn emit_u8(&mut self, v: u8) {
+            self.wr_tagged_u8(EsU8 as uint, v);
+        }
+
+        fn emit_int(&mut self, v: int) {
+            self.wr_tagged_i64(EsInt as uint, v as i64);
+        }
+        fn emit_i64(&mut self, v: i64) {
+            self.wr_tagged_i64(EsI64 as uint, v);
+        }
+        fn emit_i32(&mut self, v: i32) {
+            self.wr_tagged_i32(EsI32 as uint, v);
+        }
+        fn emit_i16(&mut self, v: i16) {
+            self.wr_tagged_i16(EsI16 as uint, v);
+        }
+        fn emit_i8(&mut self, v: i8) {
+            self.wr_tagged_i8(EsI8 as uint, v);
+        }
+
+        fn emit_bool(&mut self, v: bool) {
+            self.wr_tagged_u8(EsBool as uint, v as u8)
+        }
+
+        fn emit_f64(&mut self, v: f64) {
+            let bits = unsafe { cast::transmute(v) };
+            self.wr_tagged_u64(EsF64 as uint, bits);
+        }
+        fn emit_f32(&mut self, v: f32) {
+            let bits = unsafe { cast::transmute(v) };
+            self.wr_tagged_u32(EsF32 as uint, bits);
+        }
+        fn emit_char(&mut self, v: char) {
+            self.wr_tagged_u32(EsChar as uint, v as u32);
+        }
+
+        fn emit_str(&mut self, v: &str) {
+            self.wr_tagged_str(EsStr as uint, v)
+        }
+
+        fn emit_enum(&mut self, name: &str, f: |&mut Encoder<'a>|) {
+            self._emit_label(name);
+            self.start_tag(EsEnum as uint);
+            f(self);
+            self.end_tag();
+        }
+
+        fn emit_enum_variant(&mut self,
+                             _: &str,
+                             v_id: uint,
+                             _: uint,
+                             f: |&mut Encoder<'a>|) {
+            self._emit_tagged_uint(EsEnumVid, v_id);
+            self.start_tag(EsEnumBody as uint);
+            f(self);
+            self.end_tag();
+        }
+
+        fn emit_enum_variant_arg(&mut self, _: uint, f: |&mut Encoder<'a>|) {
+            f(self)
+        }
+
+        fn emit_enum_struct_variant(&mut self,
+                                    v_name: &str,
+                                    v_id: uint,
+                                    cnt: uint,
+                                    f: |&mut Encoder<'a>|) {
+            self.emit_enum_variant(v_name, v_id, cnt, f)
+        }
+
+        fn emit_enum_struct_variant_field(&mut self,
+                                          _: &str,
+                                          idx: uint,
+                                          f: |&mut Encoder<'a>|) {
+            self.emit_enum_variant_arg(idx, f)
+        }
+
+        fn emit_struct(&mut self,
+                       _: &str,
+                       _len: uint,
+                       f: |&mut Encoder<'a>|) {
+            f(self)
+        }
+
+        fn emit_struct_field(&mut self,
+                             name: &str,
+                             _: uint,
+                             f: |&mut Encoder<'a>|) {
+            self._emit_label(name);
+            f(self)
+        }
+
+        fn emit_tuple(&mut self, len: uint, f: |&mut Encoder<'a>|) {
+            self.emit_seq(len, f)
+        }
+        fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+            self.emit_seq_elt(idx, f)
+        }
+
+        fn emit_tuple_struct(&mut self,
+                             _: &str,
+                             len: uint,
+                             f: |&mut Encoder<'a>|) {
+            self.emit_seq(len, f)
+        }
+        fn emit_tuple_struct_arg(&mut self,
+                                 idx: uint,
+                                 f: |&mut Encoder<'a>|) {
+            self.emit_seq_elt(idx, f)
+        }
+
+        fn emit_option(&mut self, f: |&mut Encoder<'a>|) {
+            self.emit_enum("Option", f);
+        }
+        fn emit_option_none(&mut self) {
+            self.emit_enum_variant("None", 0, 0, |_| ())
+        }
+        fn emit_option_some(&mut self, f: |&mut Encoder<'a>|) {
+            self.emit_enum_variant("Some", 1, 1, f)
+        }
+
+        fn emit_seq(&mut self, len: uint, f: |&mut Encoder<'a>|) {
+            self.start_tag(EsVec as uint);
+            self._emit_tagged_uint(EsVecLen, len);
+            f(self);
+            self.end_tag();
+        }
+
+        fn emit_seq_elt(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
+            self.start_tag(EsVecElt as uint);
+            f(self);
+            self.end_tag();
+        }
+
+        fn emit_map(&mut self, len: uint, f: |&mut Encoder<'a>|) {
+            self.start_tag(EsMap as uint);
+            self._emit_tagged_uint(EsMapLen, len);
+            f(self);
+            self.end_tag();
+        }
+
+        fn emit_map_elt_key(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
+            self.start_tag(EsMapKey as uint);
+            f(self);
+            self.end_tag();
+        }
+
+        fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
+            self.start_tag(EsMapVal as uint);
+            f(self);
+            self.end_tag();
+        }
+    }
+}
+
+// ___________________________________________________________________________
+// Testing
+
+#[cfg(test)]
+mod tests {
+    use ebml::reader;
+    use ebml::writer;
+    use {Encodable, Decodable};
+
+    use std::io::MemWriter;
+    use std::option::{None, Option, Some};
+
+    #[test]
+    fn test_vuint_at() {
+        let data = [
+            0x80,
+            0xff,
+            0x40, 0x00,
+            0x7f, 0xff,
+            0x20, 0x00, 0x00,
+            0x3f, 0xff, 0xff,
+            0x10, 0x00, 0x00, 0x00,
+            0x1f, 0xff, 0xff, 0xff
+        ];
+
+        let mut res: reader::Res;
+
+        // Class A
+        res = reader::vuint_at(data, 0);
+        assert_eq!(res.val, 0);
+        assert_eq!(res.next, 1);
+        res = reader::vuint_at(data, res.next);
+        assert_eq!(res.val, (1 << 7) - 1);
+        assert_eq!(res.next, 2);
+
+        // Class B
+        res = reader::vuint_at(data, res.next);
+        assert_eq!(res.val, 0);
+        assert_eq!(res.next, 4);
+        res = reader::vuint_at(data, res.next);
+        assert_eq!(res.val, (1 << 14) - 1);
+        assert_eq!(res.next, 6);
+
+        // Class C
+        res = reader::vuint_at(data, res.next);
+        assert_eq!(res.val, 0);
+        assert_eq!(res.next, 9);
+        res = reader::vuint_at(data, res.next);
+        assert_eq!(res.val, (1 << 21) - 1);
+        assert_eq!(res.next, 12);
+
+        // Class D
+        res = reader::vuint_at(data, res.next);
+        assert_eq!(res.val, 0);
+        assert_eq!(res.next, 16);
+        res = reader::vuint_at(data, res.next);
+        assert_eq!(res.val, (1 << 28) - 1);
+        assert_eq!(res.next, 20);
+    }
+
+    #[test]
+    fn test_option_int() {
+        fn test_v(v: Option<int>) {
+            debug!("v == {:?}", v);
+            let mut wr = MemWriter::new();
+            {
+                let mut ebml_w = writer::Encoder(&mut wr);
+                v.encode(&mut ebml_w);
+            }
+            let ebml_doc = reader::Doc(wr.get_ref());
+            let mut deser = reader::Decoder(ebml_doc);
+            let v1 = Decodable::decode(&mut deser);
+            debug!("v1 == {:?}", v1);
+            assert_eq!(v, v1);
+        }
+
+        test_v(Some(22));
+        test_v(None);
+        test_v(Some(3));
+    }
+}
+
+#[cfg(test)]
+mod bench {
+    extern crate test;
+    use self::test::BenchHarness;
+    use ebml::reader;
+
+    #[bench]
+    pub fn vuint_at_A_aligned(bh: &mut BenchHarness) {
+        use std::slice;
+        let data = slice::from_fn(4*100, |i| {
+            match i % 2 {
+              0 => 0x80u8,
+              _ => i as u8,
+            }
+        });
+        let mut sum = 0u;
+        bh.iter(|| {
+            let mut i = 0;
+            while i < data.len() {
+                sum += reader::vuint_at(data, i).val;
+                i += 4;
+            }
+        });
+    }
+
+    #[bench]
+    pub fn vuint_at_A_unaligned(bh: &mut BenchHarness) {
+        use std::slice;
+        let data = slice::from_fn(4*100+1, |i| {
+            match i % 2 {
+              1 => 0x80u8,
+              _ => i as u8
+            }
+        });
+        let mut sum = 0u;
+        bh.iter(|| {
+            let mut i = 1;
+            while i < data.len() {
+                sum += reader::vuint_at(data, i).val;
+                i += 4;
+            }
+        });
+    }
+
+    #[bench]
+    pub fn vuint_at_D_aligned(bh: &mut BenchHarness) {
+        use std::slice;
+        let data = slice::from_fn(4*100, |i| {
+            match i % 4 {
+              0 => 0x10u8,
+              3 => i as u8,
+              _ => 0u8
+            }
+        });
+        let mut sum = 0u;
+        bh.iter(|| {
+            let mut i = 0;
+            while i < data.len() {
+                sum += reader::vuint_at(data, i).val;
+                i += 4;
+            }
+        });
+    }
+
+    #[bench]
+    pub fn vuint_at_D_unaligned(bh: &mut BenchHarness) {
+        use std::slice;
+        let data = slice::from_fn(4*100+1, |i| {
+            match i % 4 {
+              1 => 0x10u8,
+              0 => i as u8,
+              _ => 0u8
+            }
+        });
+        let mut sum = 0u;
+        bh.iter(|| {
+            let mut i = 1;
+            while i < data.len() {
+                sum += reader::vuint_at(data, i).val;
+                i += 4;
+            }
+        });
+    }
+}
+
index c52cfb1e35de036244b11a8c859d2c6438e96e73..f2bdef445bd7d121fd4f835a5aadb1ead4ea7a45 100644 (file)
@@ -72,7 +72,10 @@ fn main() {
     let mut m = io::MemWriter::new();
     {
         let mut encoder = json::Encoder::new(&mut m as &mut std::io::Writer);
-        to_encode_object.encode(&mut encoder);
+        match to_encode_object.encode(&mut encoder) {
+            Ok(()) => (),
+            Err(e) => fail!("json encoding error: {}", e)
+        };
     }
 }
 ```
@@ -141,7 +144,10 @@ fn main() {
             ~"{\"attr1\":1,\"attr2\":\"toto\"}";
     let json_object = json::from_str(json_str_to_decode);
     let mut decoder = json::Decoder::new(json_object.unwrap());
-    let decoded_object: MyStruct = Decodable::decode(&mut decoder); // create the final object
+    let decoded_object: MyStruct = match Decodable::decode(&mut decoder) {
+        Ok(v) => v,
+        Err(e) => fail!("Decoding error: {}", e)
+    }; // create the final object
 }
 ```
 
@@ -174,7 +180,7 @@ fn main() {
 
     let json_object = json::from_str(encoded_str);
     let mut decoder = json::Decoder::new(json_object.unwrap());
-    let decoded1: TestStruct1 = Decodable::decode(&mut decoder); // create the final object
+    let decoded1: TestStruct1 = Decodable::decode(&mut decoder).unwrap(); // create the final object
 }
 ```
 
@@ -219,7 +225,7 @@ fn main() {
 
     let mut decoder = json::Decoder::new(json::from_str(json_str).unwrap());
     // create the final object
-    let decoded2: TestStruct1 = Decodable::decode(&mut decoder);
+    let decoded2: TestStruct1 = Decodable::decode(&mut decoder).unwrap();
 }
 ```
 
@@ -237,10 +243,6 @@ fn main() {
 use Encodable;
 use collections::TreeMap;
 
-macro_rules! try( ($e:expr) => (
-    match $e { Ok(e) => e, Err(e) => { self.error = Err(e); return } }
-) )
-
 /// Represents a json value
 #[deriving(Clone, Eq)]
 pub enum Json {
@@ -255,25 +257,18 @@ pub enum Json {
 pub type List = ~[Json];
 pub type Object = TreeMap<~str, Json>;
 
-#[deriving(Eq)]
-/// If an error occurs while parsing some JSON, this is the structure which is
-/// returned
-pub struct Error {
-    /// The line number at which the error occurred
-    priv line: uint,
-    /// The column number at which the error occurred
-    priv col: uint,
-    /// A message describing the type of the error
-    priv msg: ~str,
+#[deriving(Eq, Show)]
+pub enum Error {
+    /// msg, line, col
+    ParseError(~str, uint, uint),
+    ExpectedError(~str, ~str),
+    MissingFieldError(~str),
+    UnknownVariantError(~str),
+    IoError(io::IoError)
 }
 
-fn io_error_to_error(io: io::IoError) -> Error {
-    Error {
-        line: 0,
-        col: 0,
-        msg: format!("io error: {}", io)
-    }
-}
+pub type EncodeResult = io::IoResult<()>;
+pub type DecodeResult<T> = Result<T, Error>;
 
 fn escape_str(s: &str) -> ~str {
     let mut escaped = ~"\"";
@@ -304,183 +299,203 @@ fn spaces(n: uint) -> ~str {
 /// A structure for implementing serialization to JSON.
 pub struct Encoder<'a> {
     priv wr: &'a mut io::Writer,
-    priv error: io::IoResult<()>,
 }
 
 impl<'a> Encoder<'a> {
     /// Creates a new JSON encoder whose output will be written to the writer
     /// specified.
     pub fn new<'a>(wr: &'a mut io::Writer) -> Encoder<'a> {
-        Encoder { wr: wr, error: Ok(()) }
+        Encoder { wr: wr }
     }
 
     /// Encode the specified struct into a json [u8]
-    pub fn buffer_encode<T:Encodable<Encoder<'a>>>(to_encode_object: &T) -> ~[u8]  {
+    pub fn buffer_encode<T:Encodable<Encoder<'a>, io::IoError>>(to_encode_object: &T) -> ~[u8]  {
        //Serialize the object in a string using a writer
         let mut m = MemWriter::new();
         {
             let mut encoder = Encoder::new(&mut m as &mut io::Writer);
-            to_encode_object.encode(&mut encoder);
+            // MemWriter never Errs
+            let _ = to_encode_object.encode(&mut encoder);
         }
         m.unwrap()
     }
 
     /// Encode the specified struct into a json str
-    pub fn str_encode<T:Encodable<Encoder<'a>>>(to_encode_object: &T) -> ~str  {
+    pub fn str_encode<T:Encodable<Encoder<'a>, io::IoError>>(to_encode_object: &T) -> ~str  {
         let buff:~[u8] = Encoder::buffer_encode(to_encode_object);
         str::from_utf8_owned(buff).unwrap()
     }
 }
 
-impl<'a> ::Encoder for Encoder<'a> {
-    fn emit_nil(&mut self) { try!(write!(self.wr, "null")) }
+impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
+    fn emit_nil(&mut self) -> EncodeResult { write!(self.wr, "null") }
 
-    fn emit_uint(&mut self, v: uint) { self.emit_f64(v as f64); }
-    fn emit_u64(&mut self, v: u64) { self.emit_f64(v as f64); }
-    fn emit_u32(&mut self, v: u32) { self.emit_f64(v as f64); }
-    fn emit_u16(&mut self, v: u16) { self.emit_f64(v as f64); }
-    fn emit_u8(&mut self, v: u8)   { self.emit_f64(v as f64); }
+    fn emit_uint(&mut self, v: uint) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_u64(&mut self, v: u64) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_u32(&mut self, v: u32) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_u16(&mut self, v: u16) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_u8(&mut self, v: u8) -> EncodeResult  { self.emit_f64(v as f64) }
 
-    fn emit_int(&mut self, v: int) { self.emit_f64(v as f64); }
-    fn emit_i64(&mut self, v: i64) { self.emit_f64(v as f64); }
-    fn emit_i32(&mut self, v: i32) { self.emit_f64(v as f64); }
-    fn emit_i16(&mut self, v: i16) { self.emit_f64(v as f64); }
-    fn emit_i8(&mut self, v: i8)   { self.emit_f64(v as f64); }
+    fn emit_int(&mut self, v: int) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_i64(&mut self, v: i64) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_i32(&mut self, v: i32) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_i16(&mut self, v: i16) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_i8(&mut self, v: i8) -> EncodeResult  { self.emit_f64(v as f64) }
 
-    fn emit_bool(&mut self, v: bool) {
+    fn emit_bool(&mut self, v: bool) -> EncodeResult {
         if v {
-            try!(write!(self.wr, "true"));
+            write!(self.wr, "true")
         } else {
-            try!(write!(self.wr, "false"));
+            write!(self.wr, "false")
         }
     }
 
-    fn emit_f64(&mut self, v: f64) {
-        try!(write!(self.wr, "{}", f64::to_str_digits(v, 6u)))
+    fn emit_f64(&mut self, v: f64) -> EncodeResult {
+        write!(self.wr, "{}", f64::to_str_digits(v, 6u))
     }
-    fn emit_f32(&mut self, v: f32) { self.emit_f64(v as f64); }
+    fn emit_f32(&mut self, v: f32) -> EncodeResult { self.emit_f64(v as f64) }
 
-    fn emit_char(&mut self, v: char) { self.emit_str(str::from_char(v)) }
-    fn emit_str(&mut self, v: &str) {
-        try!(write!(self.wr, "{}", escape_str(v)))
+    fn emit_char(&mut self, v: char) -> EncodeResult { self.emit_str(str::from_char(v)) }
+    fn emit_str(&mut self, v: &str) -> EncodeResult {
+        write!(self.wr, "{}", escape_str(v))
     }
 
-    fn emit_enum(&mut self, _name: &str, f: |&mut Encoder<'a>|) { f(self) }
+    fn emit_enum(&mut self,
+                 _name: &str,
+                 f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult { f(self) }
 
     fn emit_enum_variant(&mut self,
                          name: &str,
                          _id: uint,
                          cnt: uint,
-                         f: |&mut Encoder<'a>|) {
+                         f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
         // enums are encoded as strings or objects
         // Bunny => "Bunny"
         // Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]}
         if cnt == 0 {
-            try!(write!(self.wr, "{}", escape_str(name)));
+            write!(self.wr, "{}", escape_str(name))
         } else {
             try!(write!(self.wr, "\\{\"variant\":"));
             try!(write!(self.wr, "{}", escape_str(name)));
             try!(write!(self.wr, ",\"fields\":["));
-            f(self);
-            try!(write!(self.wr, "]\\}"));
+            try!(f(self));
+            write!(self.wr, "]\\}")
         }
     }
 
-    fn emit_enum_variant_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+    fn emit_enum_variant_arg(&mut self,
+                             idx: uint,
+                             f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
         if idx != 0 {
             try!(write!(self.wr, ","));
         }
-        f(self);
+        f(self)
     }
 
     fn emit_enum_struct_variant(&mut self,
                                 name: &str,
                                 id: uint,
                                 cnt: uint,
-                                f: |&mut Encoder<'a>|) {
+                                f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
         self.emit_enum_variant(name, id, cnt, f)
     }
 
     fn emit_enum_struct_variant_field(&mut self,
                                       _: &str,
                                       idx: uint,
-                                      f: |&mut Encoder<'a>|) {
+                                      f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
         self.emit_enum_variant_arg(idx, f)
     }
 
-    fn emit_struct(&mut self, _: &str, _: uint, f: |&mut Encoder<'a>|) {
+    fn emit_struct(&mut self,
+                   _: &str,
+                   _: uint,
+                   f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
         try!(write!(self.wr, r"\{"));
-        f(self);
-        try!(write!(self.wr, r"\}"));
+        try!(f(self));
+        write!(self.wr, r"\}")
     }
 
     fn emit_struct_field(&mut self,
                          name: &str,
                          idx: uint,
-                         f: |&mut Encoder<'a>|) {
-        if idx != 0 { try!(write!(self.wr, ",")) }
+                         f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
+        if idx != 0 { try!(write!(self.wr, ",")); }
         try!(write!(self.wr, "{}:", escape_str(name)));
-        f(self);
+        f(self)
     }
 
-    fn emit_tuple(&mut self, len: uint, f: |&mut Encoder<'a>|) {
+    fn emit_tuple(&mut self, len: uint, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
         self.emit_seq(len, f)
     }
-    fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+    fn emit_tuple_arg(&mut self,
+                      idx: uint,
+                      f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
         self.emit_seq_elt(idx, f)
     }
 
     fn emit_tuple_struct(&mut self,
                          _name: &str,
                          len: uint,
-                         f: |&mut Encoder<'a>|) {
+                         f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
         self.emit_seq(len, f)
     }
-    fn emit_tuple_struct_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+    fn emit_tuple_struct_arg(&mut self,
+                             idx: uint,
+                             f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
         self.emit_seq_elt(idx, f)
     }
 
-    fn emit_option(&mut self, f: |&mut Encoder<'a>|) { f(self); }
-    fn emit_option_none(&mut self) { self.emit_nil(); }
-    fn emit_option_some(&mut self, f: |&mut Encoder<'a>|) { f(self); }
+    fn emit_option(&mut self, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
+        f(self)
+    }
+    fn emit_option_none(&mut self) -> EncodeResult { self.emit_nil() }
+    fn emit_option_some(&mut self, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
+        f(self)
+    }
 
-    fn emit_seq(&mut self, _len: uint, f: |&mut Encoder<'a>|) {
+    fn emit_seq(&mut self, _len: uint, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
         try!(write!(self.wr, "["));
-        f(self);
-        try!(write!(self.wr, "]"));
+        try!(f(self));
+        write!(self.wr, "]")
     }
 
-    fn emit_seq_elt(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+    fn emit_seq_elt(&mut self, idx: uint, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
         if idx != 0 {
             try!(write!(self.wr, ","));
         }
         f(self)
     }
 
-    fn emit_map(&mut self, _len: uint, f: |&mut Encoder<'a>|) {
+    fn emit_map(&mut self, _len: uint, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
         try!(write!(self.wr, r"\{"));
-        f(self);
-        try!(write!(self.wr, r"\}"));
+        try!(f(self));
+        write!(self.wr, r"\}")
     }
 
-    fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+    fn emit_map_elt_key(&mut self,
+                        idx: uint,
+                        f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
         use std::str::from_utf8;
         if idx != 0 { try!(write!(self.wr, ",")) }
         // 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();
         let mut check_encoder = Encoder::new(&mut buf);
-        f(&mut check_encoder);
+        try!(f(&mut check_encoder));
         let buf = buf.unwrap();
         let out = from_utf8(buf).unwrap();
         let needs_wrapping = out.char_at(0) != '"' &&
             out.char_at_reverse(out.len()) != '"';
         if needs_wrapping { try!(write!(self.wr, "\"")); }
-        f(self);
+        try!(f(self));
         if needs_wrapping { try!(write!(self.wr, "\"")); }
+        Ok(())
     }
 
-    fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
+    fn emit_map_elt_val(&mut self,
+                        _idx: uint,
+                        f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
         try!(write!(self.wr, ":"));
         f(self)
     }
@@ -491,7 +506,6 @@ fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
 pub struct PrettyEncoder<'a> {
     priv wr: &'a mut io::Writer,
     priv indent: uint,
-    priv error: io::IoResult<()>,
 }
 
 impl<'a> PrettyEncoder<'a> {
@@ -500,45 +514,46 @@ pub fn new<'a>(wr: &'a mut io::Writer) -> PrettyEncoder<'a> {
         PrettyEncoder {
             wr: wr,
             indent: 0,
-            error: Ok(())
         }
     }
 }
 
-impl<'a> ::Encoder for PrettyEncoder<'a> {
-    fn emit_nil(&mut self) { try!(write!(self.wr, "null")); }
+impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
+    fn emit_nil(&mut self) -> EncodeResult { write!(self.wr, "null") }
 
-    fn emit_uint(&mut self, v: uint) { self.emit_f64(v as f64); }
-    fn emit_u64(&mut self, v: u64) { self.emit_f64(v as f64); }
-    fn emit_u32(&mut self, v: u32) { self.emit_f64(v as f64); }
-    fn emit_u16(&mut self, v: u16) { self.emit_f64(v as f64); }
-    fn emit_u8(&mut self, v: u8)   { self.emit_f64(v as f64); }
+    fn emit_uint(&mut self, v: uint) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_u64(&mut self, v: u64) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_u32(&mut self, v: u32) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_u16(&mut self, v: u16) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_u8(&mut self, v: u8) -> EncodeResult { self.emit_f64(v as f64) }
 
-    fn emit_int(&mut self, v: int) { self.emit_f64(v as f64); }
-    fn emit_i64(&mut self, v: i64) { self.emit_f64(v as f64); }
-    fn emit_i32(&mut self, v: i32) { self.emit_f64(v as f64); }
-    fn emit_i16(&mut self, v: i16) { self.emit_f64(v as f64); }
-    fn emit_i8(&mut self, v: i8)   { self.emit_f64(v as f64); }
+    fn emit_int(&mut self, v: int) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_i64(&mut self, v: i64) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_i32(&mut self, v: i32) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_i16(&mut self, v: i16) -> EncodeResult { self.emit_f64(v as f64) }
+    fn emit_i8(&mut self, v: i8) -> EncodeResult { self.emit_f64(v as f64) }
 
-    fn emit_bool(&mut self, v: bool) {
+    fn emit_bool(&mut self, v: bool) -> EncodeResult {
         if v {
-            try!(write!(self.wr, "true"));
+            write!(self.wr, "true")
         } else {
-            try!(write!(self.wr, "false"));
+            write!(self.wr, "false")
         }
     }
 
-    fn emit_f64(&mut self, v: f64) {
-        try!(write!(self.wr, "{}", f64::to_str_digits(v, 6u)));
+    fn emit_f64(&mut self, v: f64) -> EncodeResult {
+        write!(self.wr, "{}", f64::to_str_digits(v, 6u))
     }
-    fn emit_f32(&mut self, v: f32) { self.emit_f64(v as f64); }
+    fn emit_f32(&mut self, v: f32) -> EncodeResult { self.emit_f64(v as f64) }
 
-    fn emit_char(&mut self, v: char) { self.emit_str(str::from_char(v)) }
-    fn emit_str(&mut self, v: &str) {
-        try!(write!(self.wr, "{}", escape_str(v)));
+    fn emit_char(&mut self, v: char) -> EncodeResult { self.emit_str(str::from_char(v)) }
+    fn emit_str(&mut self, v: &str) -> EncodeResult {
+        write!(self.wr, "{}", escape_str(v))
     }
 
-    fn emit_enum(&mut self, _name: &str, f: |&mut PrettyEncoder<'a>|) {
+    fn emit_enum(&mut self,
+                 _name: &str,
+                 f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         f(self)
     }
 
@@ -546,22 +561,22 @@ fn emit_enum_variant(&mut self,
                          name: &str,
                          _: uint,
                          cnt: uint,
-                         f: |&mut PrettyEncoder<'a>|) {
+                         f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         if cnt == 0 {
-            try!(write!(self.wr, "{}", escape_str(name)));
+            write!(self.wr, "{}", escape_str(name))
         } else {
             self.indent += 2;
             try!(write!(self.wr, "[\n{}{},\n", spaces(self.indent),
                           escape_str(name)));
-            f(self);
+            try!(f(self));
             self.indent -= 2;
-            try!(write!(self.wr, "\n{}]", spaces(self.indent)));
+            write!(self.wr, "\n{}]", spaces(self.indent))
         }
     }
 
     fn emit_enum_variant_arg(&mut self,
                              idx: uint,
-                             f: |&mut PrettyEncoder<'a>|) {
+                             f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         if idx != 0 {
             try!(write!(self.wr, ",\n"));
         }
@@ -573,14 +588,14 @@ fn emit_enum_struct_variant(&mut self,
                                 name: &str,
                                 id: uint,
                                 cnt: uint,
-                                f: |&mut PrettyEncoder<'a>|) {
+                                f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         self.emit_enum_variant(name, id, cnt, f)
     }
 
     fn emit_enum_struct_variant_field(&mut self,
                                       _: &str,
                                       idx: uint,
-                                      f: |&mut PrettyEncoder<'a>|) {
+                                      f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         self.emit_enum_variant_arg(idx, f)
     }
 
@@ -588,67 +603,79 @@ fn emit_enum_struct_variant_field(&mut self,
     fn emit_struct(&mut self,
                    _: &str,
                    len: uint,
-                   f: |&mut PrettyEncoder<'a>|) {
+                   f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         if len == 0 {
-            try!(write!(self.wr, "\\{\\}"));
+            write!(self.wr, "\\{\\}")
         } else {
             try!(write!(self.wr, "\\{"));
             self.indent += 2;
-            f(self);
+            try!(f(self));
             self.indent -= 2;
-            try!(write!(self.wr, "\n{}\\}", spaces(self.indent)));
+            write!(self.wr, "\n{}\\}", spaces(self.indent))
         }
     }
 
     fn emit_struct_field(&mut self,
                          name: &str,
                          idx: uint,
-                         f: |&mut PrettyEncoder<'a>|) {
+                         f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         if idx == 0 {
             try!(write!(self.wr, "\n"));
         } else {
             try!(write!(self.wr, ",\n"));
         }
         try!(write!(self.wr, "{}{}: ", spaces(self.indent), escape_str(name)));
-        f(self);
+        f(self)
     }
 
-    fn emit_tuple(&mut self, len: uint, f: |&mut PrettyEncoder<'a>|) {
+    fn emit_tuple(&mut self,
+                  len: uint,
+                  f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         self.emit_seq(len, f)
     }
-    fn emit_tuple_arg(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
+    fn emit_tuple_arg(&mut self,
+                      idx: uint,
+                      f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         self.emit_seq_elt(idx, f)
     }
 
     fn emit_tuple_struct(&mut self,
                          _: &str,
                          len: uint,
-                         f: |&mut PrettyEncoder<'a>|) {
+                         f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         self.emit_seq(len, f)
     }
     fn emit_tuple_struct_arg(&mut self,
                              idx: uint,
-                             f: |&mut PrettyEncoder<'a>|) {
+                             f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         self.emit_seq_elt(idx, f)
     }
 
-    fn emit_option(&mut self, f: |&mut PrettyEncoder<'a>|) { f(self); }
-    fn emit_option_none(&mut self) { self.emit_nil(); }
-    fn emit_option_some(&mut self, f: |&mut PrettyEncoder<'a>|) { f(self); }
+    fn emit_option(&mut self, f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
+        f(self)
+    }
+    fn emit_option_none(&mut self) -> EncodeResult { self.emit_nil() }
+    fn emit_option_some(&mut self, f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
+        f(self)
+    }
 
-    fn emit_seq(&mut self, len: uint, f: |&mut PrettyEncoder<'a>|) {
+    fn emit_seq(&mut self,
+                len: uint,
+                f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         if len == 0 {
-            try!(write!(self.wr, "[]"));
+            write!(self.wr, "[]")
         } else {
             try!(write!(self.wr, "["));
             self.indent += 2;
-            f(self);
+            try!(f(self));
             self.indent -= 2;
-            try!(write!(self.wr, "\n{}]", spaces(self.indent)));
+            write!(self.wr, "\n{}]", spaces(self.indent))
         }
     }
 
-    fn emit_seq_elt(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
+    fn emit_seq_elt(&mut self,
+                    idx: uint,
+                    f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         if idx == 0 {
             try!(write!(self.wr, "\n"));
         } else {
@@ -658,19 +685,23 @@ fn emit_seq_elt(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
         f(self)
     }
 
-    fn emit_map(&mut self, len: uint, f: |&mut PrettyEncoder<'a>|) {
+    fn emit_map(&mut self,
+                len: uint,
+                f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         if len == 0 {
-            try!(write!(self.wr, "\\{\\}"));
+            write!(self.wr, "\\{\\}")
         } else {
             try!(write!(self.wr, "\\{"));
             self.indent += 2;
-            f(self);
+            try!(f(self));
             self.indent -= 2;
-            try!(write!(self.wr, "\n{}\\}", spaces(self.indent)));
+            write!(self.wr, "\n{}\\}", spaces(self.indent))
         }
     }
 
-    fn emit_map_elt_key(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
+    fn emit_map_elt_key(&mut self,
+                        idx: uint,
+                        f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         use std::str::from_utf8;
         if idx == 0 {
             try!(write!(self.wr, "\n"));
@@ -682,24 +713,27 @@ fn emit_map_elt_key(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
         // in the event that its of a type that omits them (eg numbers)
         let mut buf = MemWriter::new();
         let mut check_encoder = PrettyEncoder::new(&mut buf);
-        f(&mut check_encoder);
+        try!(f(&mut check_encoder));
         let buf = buf.unwrap();
         let out = from_utf8(buf).unwrap();
         let needs_wrapping = out.char_at(0) != '"' &&
             out.char_at_reverse(out.len()) != '"';
         if needs_wrapping { try!(write!(self.wr, "\"")); }
-        f(self);
+        try!(f(self));
         if needs_wrapping { try!(write!(self.wr, "\"")); }
+        Ok(())
     }
 
-    fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut PrettyEncoder<'a>|) {
+    fn emit_map_elt_val(&mut self,
+                        _idx: uint,
+                        f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
         try!(write!(self.wr, ": "));
-        f(self);
+        f(self)
     }
 }
 
-impl<E: ::Encoder> Encodable<E> for Json {
-    fn encode(&self, e: &mut E) {
+impl<E: ::Encoder<io::IoError>> Encodable<E, io::IoError> for Json {
+    fn encode(&self, e: &mut E) -> EncodeResult {
         match *self {
             Number(v) => v.encode(e),
             String(ref v) => v.encode(e),
@@ -713,18 +747,16 @@ fn encode(&self, e: &mut E) {
 
 impl Json {
     /// Encodes a json value into a io::writer.  Uses a single line.
-    pub fn to_writer(&self, wr: &mut io::Writer) -> io::IoResult<()> {
+    pub fn to_writer(&self, wr: &mut io::Writer) -> EncodeResult {
         let mut encoder = Encoder::new(wr);
-        self.encode(&mut encoder);
-        encoder.error
+        self.encode(&mut encoder)
     }
 
     /// Encodes a json value into a io::writer.
     /// Pretty-prints in a more readable format.
-    pub fn to_pretty_writer(&self, wr: &mut io::Writer) -> io::IoResult<()> {
+    pub fn to_pretty_writer(&self, wr: &mut io::Writer) -> EncodeResult {
         let mut encoder = PrettyEncoder::new(wr);
-        self.encode(&mut encoder);
-        encoder.error
+        self.encode(&mut encoder)
     }
 
     /// Encodes a json value into a string
@@ -888,7 +920,7 @@ pub fn new(rdr: T) -> Parser<T> {
 }
 
 impl<T: Iterator<char>> Parser<T> {
-    pub fn parse(&mut self) -> Result<Json, Error> {
+    pub fn parse(&mut self) -> DecodeResult<Json> {
         match self.parse_value() {
           Ok(value) => {
             // Skip trailing whitespaces.
@@ -927,11 +959,11 @@ fn ch_is(&self, c: char) -> bool {
         self.ch == Some(c)
     }
 
-    fn error<T>(&self, msg: ~str) -> Result<T, Error> {
-        Err(Error { line: self.line, col: self.col, msg: msg })
+    fn error<T>(&self, msg: ~str) -> DecodeResult<T> {
+        Err(ParseError(msg, self.line, self.col))
     }
 
-    fn parse_value(&mut self) -> Result<Json, Error> {
+    fn parse_value(&mut self) -> DecodeResult<Json> {
         self.parse_whitespace();
 
         if self.eof() { return self.error(~"EOF while parsing value"); }
@@ -960,7 +992,7 @@ fn parse_whitespace(&mut self) {
               self.ch_is('\r') { self.bump(); }
     }
 
-    fn parse_ident(&mut self, ident: &str, value: Json) -> Result<Json, Error> {
+    fn parse_ident(&mut self, ident: &str, value: Json) -> DecodeResult<Json> {
         if ident.chars().all(|c| Some(c) == self.next_char()) {
             self.bump();
             Ok(value)
@@ -969,7 +1001,7 @@ fn parse_ident(&mut self, ident: &str, value: Json) -> Result<Json, Error> {
         }
     }
 
-    fn parse_number(&mut self) -> Result<Json, Error> {
+    fn parse_number(&mut self) -> DecodeResult<Json> {
         let mut neg = 1.0;
 
         if self.ch_is('-') {
@@ -999,7 +1031,7 @@ fn parse_number(&mut self) -> Result<Json, Error> {
         Ok(Number(neg * res))
     }
 
-    fn parse_integer(&mut self) -> Result<f64, Error> {
+    fn parse_integer(&mut self) -> DecodeResult<f64> {
         let mut res = 0.0;
 
         match self.ch_or_null() {
@@ -1030,7 +1062,7 @@ fn parse_integer(&mut self) -> Result<f64, Error> {
         Ok(res)
     }
 
-    fn parse_decimal(&mut self, res: f64) -> Result<f64, Error> {
+    fn parse_decimal(&mut self, res: f64) -> DecodeResult<f64> {
         self.bump();
 
         // Make sure a digit follows the decimal place.
@@ -1056,7 +1088,7 @@ fn parse_decimal(&mut self, res: f64) -> Result<f64, Error> {
         Ok(res)
     }
 
-    fn parse_exponent(&mut self, mut res: f64) -> Result<f64, Error> {
+    fn parse_exponent(&mut self, mut res: f64) -> DecodeResult<f64> {
         self.bump();
 
         let mut exp = 0u;
@@ -1096,7 +1128,7 @@ fn parse_exponent(&mut self, mut res: f64) -> Result<f64, Error> {
         Ok(res)
     }
 
-    fn parse_str(&mut self) -> Result<~str, Error> {
+    fn parse_str(&mut self) -> DecodeResult<~str> {
         let mut escape = false;
         let mut res = ~"";
 
@@ -1160,7 +1192,7 @@ fn parse_str(&mut self) -> Result<~str, Error> {
         }
     }
 
-    fn parse_list(&mut self) -> Result<Json, Error> {
+    fn parse_list(&mut self) -> DecodeResult<Json> {
         self.bump();
         self.parse_whitespace();
 
@@ -1193,7 +1225,7 @@ fn parse_list(&mut self) -> Result<Json, Error> {
         };
     }
 
-    fn parse_object(&mut self) -> Result<Json, Error> {
+    fn parse_object(&mut self) -> DecodeResult<Json> {
         self.bump();
         self.parse_whitespace();
 
@@ -1245,21 +1277,21 @@ fn parse_object(&mut self) -> Result<Json, Error> {
 }
 
 /// Decodes a json value from an `&mut io::Reader`
-pub fn from_reader(rdr: &mut io::Reader) -> Result<Json, Error> {
+pub fn from_reader(rdr: &mut io::Reader) -> DecodeResult<Json> {
     let contents = match rdr.read_to_end() {
         Ok(c) => c,
-        Err(e) => return Err(io_error_to_error(e))
+        Err(e) => return Err(IoError(e))
     };
     let s = match str::from_utf8_owned(contents) {
         Some(s) => s,
-        None => return Err(Error { line: 0, col: 0, msg: ~"contents not utf-8" })
+        None => return Err(ParseError(~"contents not utf-8", 0, 0))
     };
     let mut parser = Parser::new(s.chars());
     parser.parse()
 }
 
 /// Decodes a json value from a string
-pub fn from_str(s: &str) -> Result<Json, Error> {
+pub fn from_str(s: &str) -> DecodeResult<Json> {
     let mut parser = Parser::new(s.chars());
     parser.parse()
 }
@@ -1279,110 +1311,103 @@ pub fn new(json: Json) -> Decoder {
 }
 
 impl Decoder {
-    fn err(&self, msg: &str) -> ! {
-        fail!("JSON decode error: {}", msg);
-    }
-    fn missing_field(&self, field: &str, object: ~Object) -> ! {
-        self.err(format!("missing required '{}' field in object: {}",
-                         field, Object(object).to_str()))
-    }
-    fn expected(&self, expected: &str, found: &Json) -> ! {
-        let found_s = match *found {
-            Null => "null",
-            List(..) => "list",
-            Object(..) => "object",
-            Number(..) => "number",
-            String(..) => "string",
-            Boolean(..) => "boolean"
-        };
-        self.err(format!("expected {expct} but found {fnd}: {val}",
-                         expct=expected, fnd=found_s, val=found.to_str()))
+    fn pop(&mut self) -> Json {
+        self.stack.pop().unwrap()
     }
 }
 
-impl ::Decoder for Decoder {
-    fn read_nil(&mut self) -> () {
-        debug!("read_nil");
-        match self.stack.pop().unwrap() {
-            Null => (),
-            value => self.expected("null", &value)
+macro_rules! expect(
+    ($e:expr, Null) => ({
+        match $e {
+            Null => Ok(()),
+            other => Err(ExpectedError(~"Null", format!("{}", other)))
+        }
+    });
+    ($e:expr, $t:ident) => ({
+        match $e {
+            $t(v) => Ok(v),
+            other => Err(ExpectedError(stringify!($t).to_owned(), format!("{}", other)))
         }
+    })
+)
+
+impl ::Decoder<Error> for Decoder {
+    fn read_nil(&mut self) -> DecodeResult<()> {
+        debug!("read_nil");
+        try!(expect!(self.pop(), Null));
+        Ok(())
     }
 
-    fn read_u64(&mut self)  -> u64  { self.read_f64() as u64 }
-    fn read_u32(&mut self)  -> u32  { self.read_f64() as u32 }
-    fn read_u16(&mut self)  -> u16  { self.read_f64() as u16 }
-    fn read_u8 (&mut self)  -> u8   { self.read_f64() as u8 }
-    fn read_uint(&mut self) -> uint { self.read_f64() as uint }
+    fn read_u64(&mut self)  -> DecodeResult<u64 > { Ok(try!(self.read_f64()) as u64) }
+    fn read_u32(&mut self)  -> DecodeResult<u32 > { Ok(try!(self.read_f64()) as u32) }
+    fn read_u16(&mut self)  -> DecodeResult<u16 > { Ok(try!(self.read_f64()) as u16) }
+    fn read_u8 (&mut self)  -> DecodeResult<u8  > { Ok(try!(self.read_f64()) as u8) }
+    fn read_uint(&mut self) -> DecodeResult<uint> { Ok(try!(self.read_f64()) as uint) }
 
-    fn read_i64(&mut self) -> i64 { self.read_f64() as i64 }
-    fn read_i32(&mut self) -> i32 { self.read_f64() as i32 }
-    fn read_i16(&mut self) -> i16 { self.read_f64() as i16 }
-    fn read_i8 (&mut self) -> i8  { self.read_f64() as i8 }
-    fn read_int(&mut self) -> int { self.read_f64() as int }
+    fn read_i64(&mut self) -> DecodeResult<i64> { Ok(try!(self.read_f64()) as i64) }
+    fn read_i32(&mut self) -> DecodeResult<i32> { Ok(try!(self.read_f64()) as i32) }
+    fn read_i16(&mut self) -> DecodeResult<i16> { Ok(try!(self.read_f64()) as i16) }
+    fn read_i8 (&mut self) -> DecodeResult<i8 > { Ok(try!(self.read_f64()) as i8) }
+    fn read_int(&mut self) -> DecodeResult<int> { Ok(try!(self.read_f64()) as int) }
 
-    fn read_bool(&mut self) -> bool {
+    fn read_bool(&mut self) -> DecodeResult<bool> {
         debug!("read_bool");
-        match self.stack.pop().unwrap() {
-            Boolean(b) => b,
-            value => self.expected("boolean", &value)
-        }
+        Ok(try!(expect!(self.pop(), Boolean)))
     }
 
-    fn read_f64(&mut self) -> f64 {
+    fn read_f64(&mut self) -> DecodeResult<f64> {
         use std::from_str::FromStr;
         debug!("read_f64");
-        match self.stack.pop().unwrap() {
-            Number(f) => f,
+        match self.pop() {
+            Number(f) => Ok(f),
             String(s) => {
                 // re: #12967.. a type w/ numeric keys (ie HashMap<uint, V> etc)
                 // is going to have a string here, as per JSON spec..
-                FromStr::from_str(s).unwrap()
+                Ok(FromStr::from_str(s).unwrap())
             },
-            value => self.expected("number", &value)
+            value => Err(ExpectedError(~"Number", format!("{}", value)))
         }
     }
 
-    fn read_f32(&mut self) -> f32 { self.read_f64() as f32 }
+    fn read_f32(&mut self) -> DecodeResult<f32> { Ok(try!(self.read_f64()) as f32) }
 
-    fn read_char(&mut self) -> char {
-        let s = self.read_str();
+    fn read_char(&mut self) -> DecodeResult<char> {
+        let s = try!(self.read_str());
         {
             let mut it = s.chars();
             match (it.next(), it.next()) {
                 // exactly one character
-                (Some(c), None) => return c,
+                (Some(c), None) => return Ok(c),
                 _ => ()
             }
         }
-        self.expected("single character string", &String(s))
+        Err(ExpectedError(~"single character string", format!("{}", s)))
     }
 
-    fn read_str(&mut self) -> ~str {
+    fn read_str(&mut self) -> DecodeResult<~str> {
         debug!("read_str");
-        match self.stack.pop().unwrap() {
-            String(s) => s,
-            value => self.expected("string", &value)
-        }
+        Ok(try!(expect!(self.pop(), String)))
     }
 
-    fn read_enum<T>(&mut self, name: &str, f: |&mut Decoder| -> T) -> T {
+    fn read_enum<T>(&mut self,
+                    name: &str,
+                    f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
         debug!("read_enum({})", name);
         f(self)
     }
 
     fn read_enum_variant<T>(&mut self,
                             names: &[&str],
-                            f: |&mut Decoder, uint| -> T)
-                            -> T {
+                            f: |&mut Decoder, uint| -> DecodeResult<T>)
+                            -> DecodeResult<T> {
         debug!("read_enum_variant(names={:?})", names);
-        let name = match self.stack.pop().unwrap() {
+        let name = match self.pop() {
             String(s) => s,
             Object(mut o) => {
                 let n = match o.pop(&~"variant") {
                     Some(String(s)) => s,
-                    Some(val) => self.expected("string", &val),
-                    None => self.missing_field("variant", o)
+                    Some(val) => return Err(ExpectedError(~"String", format!("{}", val))),
+                    None => return Err(MissingFieldError(~"variant"))
                 };
                 match o.pop(&~"fields") {
                     Some(List(l)) => {
@@ -1390,36 +1415,30 @@ fn read_enum_variant<T>(&mut self,
                             self.stack.push(field.clone());
                         }
                     },
-                    Some(val) => self.expected("list", &val),
-                    None => {
-                        // re-insert the variant field so we're
-                        // printing the "whole" struct in the error
-                        // message... ick.
-                        o.insert(~"variant", String(n));
-                        self.missing_field("fields", o);
-                    }
+                    Some(val) => return Err(ExpectedError(~"List", format!("{}", val))),
+                    None => return Err(MissingFieldError(~"fields"))
                 }
                 n
             }
-            json => self.expected("string or object", &json)
+            json => return Err(ExpectedError(~"String or Object", format!("{}", json)))
         };
         let idx = match names.iter().position(|n| str::eq_slice(*n, name)) {
             Some(idx) => idx,
-            None => self.err(format!("unknown variant name: {}", name))
+            None => return Err(UnknownVariantError(name))
         };
         f(self, idx)
     }
 
-    fn read_enum_variant_arg<T>(&mut self, idx: uint, f: |&mut Decoder| -> T)
-                                -> T {
+    fn read_enum_variant_arg<T>(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult<T>)
+                                -> DecodeResult<T> {
         debug!("read_enum_variant_arg(idx={})", idx);
         f(self)
     }
 
     fn read_enum_struct_variant<T>(&mut self,
                                    names: &[&str],
-                                   f: |&mut Decoder, uint| -> T)
-                                   -> T {
+                                   f: |&mut Decoder, uint| -> DecodeResult<T>)
+                                   -> DecodeResult<T> {
         debug!("read_enum_struct_variant(names={:?})", names);
         self.read_enum_variant(names, f)
     }
@@ -1428,8 +1447,8 @@ fn read_enum_struct_variant<T>(&mut self,
     fn read_enum_struct_variant_field<T>(&mut self,
                                          name: &str,
                                          idx: uint,
-                                         f: |&mut Decoder| -> T)
-                                         -> T {
+                                         f: |&mut Decoder| -> DecodeResult<T>)
+                                         -> DecodeResult<T> {
         debug!("read_enum_struct_variant_field(name={}, idx={})", name, idx);
         self.read_enum_variant_arg(idx, f)
     }
@@ -1437,113 +1456,104 @@ fn read_enum_struct_variant_field<T>(&mut self,
     fn read_struct<T>(&mut self,
                       name: &str,
                       len: uint,
-                      f: |&mut Decoder| -> T)
-                      -> T {
+                      f: |&mut Decoder| -> DecodeResult<T>)
+                      -> DecodeResult<T> {
         debug!("read_struct(name={}, len={})", name, len);
-        let value = f(self);
-        self.stack.pop().unwrap();
-        value
+        let value = try!(f(self));
+        self.pop();
+        Ok(value)
     }
 
     fn read_struct_field<T>(&mut self,
                             name: &str,
                             idx: uint,
-                            f: |&mut Decoder| -> T)
-                            -> T {
+                            f: |&mut Decoder| -> DecodeResult<T>)
+                            -> DecodeResult<T> {
         debug!("read_struct_field(name={}, idx={})", name, idx);
-        match self.stack.pop().unwrap() {
-            Object(mut obj) => {
-                let value = match obj.pop(&name.to_owned()) {
-                    None => self.missing_field(name, obj),
-                    Some(json) => {
-                        self.stack.push(json);
-                        f(self)
-                    }
-                };
-                self.stack.push(Object(obj));
-                value
+        let mut obj = try!(expect!(self.pop(), Object));
+
+        let value = match obj.pop(&name.to_owned()) {
+            None => return Err(MissingFieldError(name.to_owned())),
+            Some(json) => {
+                self.stack.push(json);
+                try!(f(self))
             }
-            value => self.expected("object", &value)
-        }
+        };
+        self.stack.push(Object(obj));
+        Ok(value)
     }
 
-    fn read_tuple<T>(&mut self, f: |&mut Decoder, uint| -> T) -> T {
+    fn read_tuple<T>(&mut self, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
         debug!("read_tuple()");
         self.read_seq(f)
     }
 
-    fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder| -> T) -> T {
+    fn read_tuple_arg<T>(&mut self,
+                         idx: uint,
+                         f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
         debug!("read_tuple_arg(idx={})", idx);
         self.read_seq_elt(idx, f)
     }
 
     fn read_tuple_struct<T>(&mut self,
                             name: &str,
-                            f: |&mut Decoder, uint| -> T)
-                            -> T {
+                            f: |&mut Decoder, uint| -> DecodeResult<T>)
+                            -> DecodeResult<T> {
         debug!("read_tuple_struct(name={})", name);
         self.read_tuple(f)
     }
 
     fn read_tuple_struct_arg<T>(&mut self,
                                 idx: uint,
-                                f: |&mut Decoder| -> T)
-                                -> T {
+                                f: |&mut Decoder| -> DecodeResult<T>)
+                                -> DecodeResult<T> {
         debug!("read_tuple_struct_arg(idx={})", idx);
         self.read_tuple_arg(idx, f)
     }
 
-    fn read_option<T>(&mut self, f: |&mut Decoder, bool| -> T) -> T {
-        match self.stack.pop().unwrap() {
+    fn read_option<T>(&mut self, f: |&mut Decoder, bool| -> DecodeResult<T>) -> DecodeResult<T> {
+        match self.pop() {
             Null => f(self, false),
             value => { self.stack.push(value); f(self, true) }
         }
     }
 
-    fn read_seq<T>(&mut self, f: |&mut Decoder, uint| -> T) -> T {
+    fn read_seq<T>(&mut self, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
         debug!("read_seq()");
-        let len = match self.stack.pop().unwrap() {
-            List(list) => {
-                let len = list.len();
-                for v in list.move_rev_iter() {
-                    self.stack.push(v);
-                }
-                len
-            }
-            value => self.expected("list", &value)
-        };
+        let list = try!(expect!(self.pop(), List));
+        let len = list.len();
+        for v in list.move_rev_iter() {
+            self.stack.push(v);
+        }
         f(self, len)
     }
 
-    fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder| -> T) -> T {
+    fn read_seq_elt<T>(&mut self,
+                       idx: uint,
+                       f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
         debug!("read_seq_elt(idx={})", idx);
         f(self)
     }
 
-    fn read_map<T>(&mut self, f: |&mut Decoder, uint| -> T) -> T {
+    fn read_map<T>(&mut self, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
         debug!("read_map()");
-        let len = match self.stack.pop().unwrap() {
-            Object(obj) => {
-                let len = obj.len();
-                for (key, value) in obj.move_iter() {
-                    self.stack.push(value);
-                    self.stack.push(String(key));
-                }
-                len
-            }
-            value => self.expected("object", &value)
-        };
+        let obj = try!(expect!(self.pop(), Object));
+        let len = obj.len();
+        for (key, value) in obj.move_iter() {
+            self.stack.push(value);
+            self.stack.push(String(key));
+        }
         f(self, len)
     }
 
-    fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder| -> T)
-                           -> T {
+    fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult<T>)
+                           -> DecodeResult<T> {
         debug!("read_map_elt_key(idx={})", idx);
         f(self)
     }
 
-    fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder| -> T)
-                           -> T {
+    fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult<T>)
+                           -> DecodeResult<T> {
         debug!("read_map_elt_val(idx={})", idx);
         f(self)
     }
@@ -1735,17 +1745,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-impl fmt::Show for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f.buf, "{}:{}: {}", self.line, self.col, self.msg)
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use {Encodable, Decodable};
     use super::{Encoder, Decoder, Error, Boolean, Number, List, String, Null,
-                PrettyEncoder, Object, Json, from_str};
+                PrettyEncoder, Object, Json, from_str, ParseError, ExpectedError,
+                MissingFieldError, UnknownVariantError, DecodeResult };
     use std::io;
     use collections::TreeMap;
 
@@ -1931,14 +1936,14 @@ fn test_write_enum() {
         assert_eq!(
             with_str_writer(|wr| {
                 let mut encoder = Encoder::new(wr);
-                animal.encode(&mut encoder);
+                animal.encode(&mut encoder).unwrap();
             }),
             ~"\"Dog\""
         );
         assert_eq!(
             with_str_writer(|wr| {
                 let mut encoder = PrettyEncoder::new(wr);
-                animal.encode(&mut encoder);
+                animal.encode(&mut encoder).unwrap();
             }),
             ~"\"Dog\""
         );
@@ -1947,14 +1952,14 @@ fn test_write_enum() {
         assert_eq!(
             with_str_writer(|wr| {
                 let mut encoder = Encoder::new(wr);
-                animal.encode(&mut encoder);
+                animal.encode(&mut encoder).unwrap();
             }),
             ~"{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}"
         );
         assert_eq!(
             with_str_writer(|wr| {
                 let mut encoder = PrettyEncoder::new(wr);
-                animal.encode(&mut encoder);
+                animal.encode(&mut encoder).unwrap();
             }),
             ~"\
             [\n  \
@@ -1970,14 +1975,14 @@ fn test_write_some() {
         let value = Some(~"jodhpurs");
         let s = with_str_writer(|wr| {
             let mut encoder = Encoder::new(wr);
-            value.encode(&mut encoder);
+            value.encode(&mut encoder).unwrap();
         });
         assert_eq!(s, ~"\"jodhpurs\"");
 
         let value = Some(~"jodhpurs");
         let s = with_str_writer(|wr| {
             let mut encoder = PrettyEncoder::new(wr);
-            value.encode(&mut encoder);
+            value.encode(&mut encoder).unwrap();
         });
         assert_eq!(s, ~"\"jodhpurs\"");
     }
@@ -1987,13 +1992,13 @@ fn test_write_none() {
         let value: Option<~str> = None;
         let s = with_str_writer(|wr| {
             let mut encoder = Encoder::new(wr);
-            value.encode(&mut encoder);
+            value.encode(&mut encoder).unwrap();
         });
         assert_eq!(s, ~"null");
 
         let s = with_str_writer(|wr| {
             let mut encoder = Encoder::new(wr);
-            value.encode(&mut encoder);
+            value.encode(&mut encoder).unwrap();
         });
         assert_eq!(s, ~"null");
     }
@@ -2001,35 +2006,35 @@ fn test_write_none() {
     #[test]
     fn test_trailing_characters() {
         assert_eq!(from_str("nulla"),
-            Err(Error {line: 1u, col: 5u, msg: ~"trailing characters"}));
+            Err(ParseError(~"trailing characters", 1u, 5u)));
         assert_eq!(from_str("truea"),
-            Err(Error {line: 1u, col: 5u, msg: ~"trailing characters"}));
+            Err(ParseError(~"trailing characters", 1u, 5u)));
         assert_eq!(from_str("falsea"),
-            Err(Error {line: 1u, col: 6u, msg: ~"trailing characters"}));
+            Err(ParseError(~"trailing characters", 1u, 6u)));
         assert_eq!(from_str("1a"),
-            Err(Error {line: 1u, col: 2u, msg: ~"trailing characters"}));
+            Err(ParseError(~"trailing characters", 1u, 2u)));
         assert_eq!(from_str("[]a"),
-            Err(Error {line: 1u, col: 3u, msg: ~"trailing characters"}));
+            Err(ParseError(~"trailing characters", 1u, 3u)));
         assert_eq!(from_str("{}a"),
-            Err(Error {line: 1u, col: 3u, msg: ~"trailing characters"}));
+            Err(ParseError(~"trailing characters", 1u, 3u)));
     }
 
     #[test]
     fn test_read_identifiers() {
         assert_eq!(from_str("n"),
-            Err(Error {line: 1u, col: 2u, msg: ~"invalid syntax"}));
+            Err(ParseError(~"invalid syntax", 1u, 2u)));
         assert_eq!(from_str("nul"),
-            Err(Error {line: 1u, col: 4u, msg: ~"invalid syntax"}));
+            Err(ParseError(~"invalid syntax", 1u, 4u)));
 
         assert_eq!(from_str("t"),
-            Err(Error {line: 1u, col: 2u, msg: ~"invalid syntax"}));
+            Err(ParseError(~"invalid syntax", 1u, 2u)));
         assert_eq!(from_str("truz"),
-            Err(Error {line: 1u, col: 4u, msg: ~"invalid syntax"}));
+            Err(ParseError(~"invalid syntax", 1u, 4u)));
 
         assert_eq!(from_str("f"),
-            Err(Error {line: 1u, col: 2u, msg: ~"invalid syntax"}));
+            Err(ParseError(~"invalid syntax", 1u, 2u)));
         assert_eq!(from_str("faz"),
-            Err(Error {line: 1u, col: 3u, msg: ~"invalid syntax"}));
+            Err(ParseError(~"invalid syntax", 1u, 3u)));
 
         assert_eq!(from_str("null"), Ok(Null));
         assert_eq!(from_str("true"), Ok(Boolean(true)));
@@ -2042,35 +2047,35 @@ fn test_read_identifiers() {
     #[test]
     fn test_decode_identifiers() {
         let mut decoder = Decoder::new(from_str("null").unwrap());
-        let v: () = Decodable::decode(&mut decoder);
+        let v: () = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ());
 
         let mut decoder = Decoder::new(from_str("true").unwrap());
-        let v: bool = Decodable::decode(&mut decoder);
+        let v: bool = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, true);
 
         let mut decoder = Decoder::new(from_str("false").unwrap());
-        let v: bool = Decodable::decode(&mut decoder);
+        let v: bool = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, false);
     }
 
     #[test]
     fn test_read_number() {
         assert_eq!(from_str("+"),
-            Err(Error {line: 1u, col: 1u, msg: ~"invalid syntax"}));
+            Err(ParseError(~"invalid syntax", 1u, 1u)));
         assert_eq!(from_str("."),
-            Err(Error {line: 1u, col: 1u, msg: ~"invalid syntax"}));
+            Err(ParseError(~"invalid syntax", 1u, 1u)));
 
         assert_eq!(from_str("-"),
-            Err(Error {line: 1u, col: 2u, msg: ~"invalid number"}));
+            Err(ParseError(~"invalid number", 1u, 2u)));
         assert_eq!(from_str("00"),
-            Err(Error {line: 1u, col: 2u, msg: ~"invalid number"}));
+            Err(ParseError(~"invalid number", 1u, 2u)));
         assert_eq!(from_str("1."),
-            Err(Error {line: 1u, col: 3u, msg: ~"invalid number"}));
+            Err(ParseError(~"invalid number", 1u, 3u)));
         assert_eq!(from_str("1e"),
-            Err(Error {line: 1u, col: 3u, msg: ~"invalid number"}));
+            Err(ParseError(~"invalid number", 1u, 3u)));
         assert_eq!(from_str("1e+"),
-            Err(Error {line: 1u, col: 4u, msg: ~"invalid number"}));
+            Err(ParseError(~"invalid number", 1u, 4u)));
 
         assert_eq!(from_str("3"), Ok(Number(3.0)));
         assert_eq!(from_str("3.1"), Ok(Number(3.1)));
@@ -2085,42 +2090,40 @@ fn test_read_number() {
     #[test]
     fn test_decode_numbers() {
         let mut decoder = Decoder::new(from_str("3").unwrap());
-        let v: f64 = Decodable::decode(&mut decoder);
+        let v: f64 = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, 3.0);
 
         let mut decoder = Decoder::new(from_str("3.1").unwrap());
-        let v: f64 = Decodable::decode(&mut decoder);
+        let v: f64 = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, 3.1);
 
         let mut decoder = Decoder::new(from_str("-1.2").unwrap());
-        let v: f64 = Decodable::decode(&mut decoder);
+        let v: f64 = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, -1.2);
 
         let mut decoder = Decoder::new(from_str("0.4").unwrap());
-        let v: f64 = Decodable::decode(&mut decoder);
+        let v: f64 = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, 0.4);
 
         let mut decoder = Decoder::new(from_str("0.4e5").unwrap());
-        let v: f64 = Decodable::decode(&mut decoder);
+        let v: f64 = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, 0.4e5);
 
         let mut decoder = Decoder::new(from_str("0.4e15").unwrap());
-        let v: f64 = Decodable::decode(&mut decoder);
+        let v: f64 = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, 0.4e15);
 
         let mut decoder = Decoder::new(from_str("0.4e-01").unwrap());
-        let v: f64 = Decodable::decode(&mut decoder);
+        let v: f64 = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, 0.4e-01);
     }
 
     #[test]
     fn test_read_str() {
         assert_eq!(from_str("\""),
-            Err(Error {line: 1u, col: 2u, msg: ~"EOF while parsing string"
-        }));
+            Err(ParseError(~"EOF while parsing string", 1u, 2u)));
         assert_eq!(from_str("\"lol"),
-            Err(Error {line: 1u, col: 5u, msg: ~"EOF while parsing string"
-        }));
+            Err(ParseError(~"EOF while parsing string", 1u, 5u)));
 
         assert_eq!(from_str("\"\""), Ok(String(~"")));
         assert_eq!(from_str("\"foo\""), Ok(String(~"foo")));
@@ -2137,54 +2140,54 @@ fn test_read_str() {
     #[test]
     fn test_decode_str() {
         let mut decoder = Decoder::new(from_str("\"\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
+        let v: ~str = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ~"");
 
         let mut decoder = Decoder::new(from_str("\"foo\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
+        let v: ~str = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ~"foo");
 
         let mut decoder = Decoder::new(from_str("\"\\\"\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
+        let v: ~str = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ~"\"");
 
         let mut decoder = Decoder::new(from_str("\"\\b\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
+        let v: ~str = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ~"\x08");
 
         let mut decoder = Decoder::new(from_str("\"\\n\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
+        let v: ~str = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ~"\n");
 
         let mut decoder = Decoder::new(from_str("\"\\r\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
+        let v: ~str = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ~"\r");
 
         let mut decoder = Decoder::new(from_str("\"\\t\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
+        let v: ~str = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ~"\t");
 
         let mut decoder = Decoder::new(from_str("\"\\u12ab\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
+        let v: ~str = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ~"\u12ab");
 
         let mut decoder = Decoder::new(from_str("\"\\uAB12\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
+        let v: ~str = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ~"\uAB12");
     }
 
     #[test]
     fn test_read_list() {
         assert_eq!(from_str("["),
-            Err(Error {line: 1u, col: 2u, msg: ~"EOF while parsing value"}));
+            Err(ParseError(~"EOF while parsing value", 1u, 2u)));
         assert_eq!(from_str("[1"),
-            Err(Error {line: 1u, col: 3u, msg: ~"EOF while parsing list"}));
+            Err(ParseError(~"EOF while parsing list", 1u, 3u)));
         assert_eq!(from_str("[1,"),
-            Err(Error {line: 1u, col: 4u, msg: ~"EOF while parsing value"}));
+            Err(ParseError(~"EOF while parsing value", 1u, 4u)));
         assert_eq!(from_str("[1,]"),
-            Err(Error {line: 1u, col: 4u, msg: ~"invalid syntax"}));
+            Err(ParseError(~"invalid syntax", 1u, 4u)));
         assert_eq!(from_str("[6 7]"),
-            Err(Error {line: 1u, col: 4u, msg: ~"expected `,` or `]`"}));
+            Err(ParseError(~"expected `,` or `]`", 1u, 4u)));
 
         assert_eq!(from_str("[]"), Ok(List(~[])));
         assert_eq!(from_str("[ ]"), Ok(List(~[])));
@@ -2202,79 +2205,55 @@ fn test_read_list() {
     #[test]
     fn test_decode_list() {
         let mut decoder = Decoder::new(from_str("[]").unwrap());
-        let v: ~[()] = Decodable::decode(&mut decoder);
+        let v: ~[()] = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ~[]);
 
         let mut decoder = Decoder::new(from_str("[null]").unwrap());
-        let v: ~[()] = Decodable::decode(&mut decoder);
+        let v: ~[()] = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ~[()]);
 
         let mut decoder = Decoder::new(from_str("[true]").unwrap());
-        let v: ~[bool] = Decodable::decode(&mut decoder);
+        let v: ~[bool] = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ~[true]);
 
         let mut decoder = Decoder::new(from_str("[true]").unwrap());
-        let v: ~[bool] = Decodable::decode(&mut decoder);
+        let v: ~[bool] = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ~[true]);
 
         let mut decoder = Decoder::new(from_str("[3, 1]").unwrap());
-        let v: ~[int] = Decodable::decode(&mut decoder);
+        let v: ~[int] = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ~[3, 1]);
 
         let mut decoder = Decoder::new(from_str("[[3], [1, 2]]").unwrap());
-        let v: ~[~[uint]] = Decodable::decode(&mut decoder);
+        let v: ~[~[uint]] = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(v, ~[~[3], ~[1, 2]]);
     }
 
     #[test]
     fn test_read_object() {
         assert_eq!(from_str("{"),
-            Err(Error {
-                line: 1u,
-                col: 2u,
-                msg: ~"EOF while parsing object"}));
+            Err(ParseError(~"EOF while parsing object", 1u, 2u)));
         assert_eq!(from_str("{ "),
-            Err(Error {
-                line: 1u,
-                col: 3u,
-                msg: ~"EOF while parsing object"}));
+            Err(ParseError(~"EOF while parsing object", 1u, 3u)));
         assert_eq!(from_str("{1"),
-            Err(Error {
-                line: 1u,
-                col: 2u,
-                msg: ~"key must be a string"}));
+            Err(ParseError(~"key must be a string", 1u, 2u)));
         assert_eq!(from_str("{ \"a\""),
-            Err(Error {
-                line: 1u,
-                col: 6u,
-                msg: ~"EOF while parsing object"}));
+            Err(ParseError(~"EOF while parsing object", 1u, 6u)));
         assert_eq!(from_str("{\"a\""),
-            Err(Error {
-                line: 1u,
-                col: 5u,
-                msg: ~"EOF while parsing object"}));
+            Err(ParseError(~"EOF while parsing object", 1u, 5u)));
         assert_eq!(from_str("{\"a\" "),
-            Err(Error {
-                line: 1u,
-                col: 6u,
-                msg: ~"EOF while parsing object"}));
+            Err(ParseError(~"EOF while parsing object", 1u, 6u)));
 
         assert_eq!(from_str("{\"a\" 1"),
-            Err(Error {line: 1u, col: 6u, msg: ~"expected `:`"}));
+            Err(ParseError(~"expected `:`", 1u, 6u)));
         assert_eq!(from_str("{\"a\":"),
-            Err(Error {line: 1u, col: 6u, msg: ~"EOF while parsing value"}));
+            Err(ParseError(~"EOF while parsing value", 1u, 6u)));
         assert_eq!(from_str("{\"a\":1"),
-            Err(Error {
-                line: 1u,
-                col: 7u,
-                msg: ~"EOF while parsing object"}));
+            Err(ParseError(~"EOF while parsing object", 1u, 7u)));
         assert_eq!(from_str("{\"a\":1 1"),
-            Err(Error {line: 1u, col: 8u, msg: ~"expected `,` or `}`"}));
+            Err(ParseError(~"expected `,` or `}`", 1u, 8u)));
         assert_eq!(from_str("{\"a\":1,"),
-            Err(Error {
-                line: 1u,
-                col: 8u,
-                msg: ~"EOF while parsing object"}));
+            Err(ParseError(~"EOF while parsing object", 1u, 8u)));
 
         assert_eq!(from_str("{}").unwrap(), mk_object([]));
         assert_eq!(from_str("{\"a\": 3}").unwrap(),
@@ -2324,7 +2303,7 @@ fn test_decode_struct() {
             ]
         }";
         let mut decoder = Decoder::new(from_str(s).unwrap());
-        let v: Outer = Decodable::decode(&mut decoder);
+        let v: Outer = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(
             v,
             Outer {
@@ -2338,23 +2317,23 @@ fn test_decode_struct() {
     #[test]
     fn test_decode_option() {
         let mut decoder = Decoder::new(from_str("null").unwrap());
-        let value: Option<~str> = Decodable::decode(&mut decoder);
+        let value: Option<~str> = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(value, None);
 
         let mut decoder = Decoder::new(from_str("\"jodhpurs\"").unwrap());
-        let value: Option<~str> = Decodable::decode(&mut decoder);
+        let value: Option<~str> = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(value, Some(~"jodhpurs"));
     }
 
     #[test]
     fn test_decode_enum() {
         let mut decoder = Decoder::new(from_str("\"Dog\"").unwrap());
-        let value: Animal = Decodable::decode(&mut decoder);
+        let value: Animal = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(value, Dog);
 
         let s = "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}";
         let mut decoder = Decoder::new(from_str(s).unwrap());
-        let value: Animal = Decodable::decode(&mut decoder);
+        let value: Animal = Decodable::decode(&mut decoder).unwrap();
         assert_eq!(value, Frog(~"Henry", 349));
     }
 
@@ -2362,7 +2341,7 @@ fn test_decode_enum() {
     fn test_decode_map() {
         let s = ~"{\"a\": \"Dog\", \"b\": {\"variant\":\"Frog\",\"fields\":[\"Henry\", 349]}}";
         let mut decoder = Decoder::new(from_str(s).unwrap());
-        let mut map: TreeMap<~str, Animal> = Decodable::decode(&mut decoder);
+        let mut map: TreeMap<~str, Animal> = Decodable::decode(&mut decoder).unwrap();
 
         assert_eq!(map.pop(&~"a"), Some(Dog));
         assert_eq!(map.pop(&~"b"), Some(Frog(~"Henry", 349)));
@@ -2371,10 +2350,7 @@ fn test_decode_map() {
     #[test]
     fn test_multiline_errors() {
         assert_eq!(from_str("{\n  \"foo\":\n \"bar\""),
-            Err(Error {
-                line: 3u,
-                col: 8u,
-                msg: ~"EOF while parsing object"}));
+            Err(ParseError(~"EOF while parsing object", 3u, 8u)));
     }
 
     #[deriving(Decodable)]
@@ -2389,60 +2365,48 @@ enum DecodeEnum {
         A(f64),
         B(~str)
     }
-    fn check_err<T: Decodable<Decoder>>(to_parse: &'static str, expected_error: &str) {
-        use std::any::AnyRefExt;
-        use std::task;
-        let res = task::try(proc() {
-            // either fails in `decode` (which is what we want), or
-            // returns Some(error_message)/None if the string was
-            // invalid or valid JSON.
-            match from_str(to_parse) {
-                Err(e) => Some(e.to_str()),
-                Ok(json) => {
-                    let _: T = Decodable::decode(&mut Decoder::new(json));
-                    None
-                }
-            }
-        });
+    fn check_err<T: Decodable<Decoder, Error>>(to_parse: &'static str, expected: Error) {
+        let res: DecodeResult<T> = match from_str(to_parse) {
+            Err(e) => Err(e),
+            Ok(json) => Decodable::decode(&mut Decoder::new(json))
+        };
         match res {
-            Ok(Some(parse_error)) => fail!("`{}` is not valid json: {}",
-                                           to_parse, parse_error),
-            Ok(None) => fail!("`{}` parsed & decoded ok, expecting error `{}`",
-                              to_parse, expected_error),
+            Ok(_) => fail!("`{}` parsed & decoded ok, expecting error `{}`",
+                              to_parse, expected),
+            Err(ParseError(e, _, _)) => fail!("`{}` is not valid json: {}",
+                                           to_parse, e),
             Err(e) => {
-                let err = e.as_ref::<~str>().unwrap();
-                assert!(err.contains(expected_error),
-                        "`{}` errored incorrectly, found `{}` expecting `{}`",
-                        to_parse, *err, expected_error);
+                assert_eq!(e, expected);
             }
+
         }
     }
     #[test]
     fn test_decode_errors_struct() {
-        check_err::<DecodeStruct>("[]", "object but found list");
+        check_err::<DecodeStruct>("[]", ExpectedError(~"Object", ~"[]"));
         check_err::<DecodeStruct>("{\"x\": true, \"y\": true, \"z\": \"\", \"w\": []}",
-                                  "number but found boolean");
+                                  ExpectedError(~"Number", ~"true"));
         check_err::<DecodeStruct>("{\"x\": 1, \"y\": [], \"z\": \"\", \"w\": []}",
-                                  "boolean but found list");
+                                  ExpectedError(~"Boolean", ~"[]"));
         check_err::<DecodeStruct>("{\"x\": 1, \"y\": true, \"z\": {}, \"w\": []}",
-                                  "string but found object");
+                                  ExpectedError(~"String", ~"{}"));
         check_err::<DecodeStruct>("{\"x\": 1, \"y\": true, \"z\": \"\", \"w\": null}",
-                                  "list but found null");
+                                  ExpectedError(~"List", ~"null"));
         check_err::<DecodeStruct>("{\"x\": 1, \"y\": true, \"z\": \"\"}",
-                                  "'w' field in object");
+                                  MissingFieldError(~"w"));
     }
     #[test]
     fn test_decode_errors_enum() {
         check_err::<DecodeEnum>("{}",
-                                "'variant' field in object");
+                                MissingFieldError(~"variant"));
         check_err::<DecodeEnum>("{\"variant\": 1}",
-                                "string but found number");
+                                ExpectedError(~"String", ~"1"));
         check_err::<DecodeEnum>("{\"variant\": \"A\"}",
-                                "'fields' field in object");
+                                MissingFieldError(~"fields"));
         check_err::<DecodeEnum>("{\"variant\": \"A\", \"fields\": null}",
-                                "list but found null");
+                                ExpectedError(~"List", ~"null"));
         check_err::<DecodeEnum>("{\"variant\": \"C\", \"fields\": []}",
-                                "unknown variant name");
+                                UnknownVariantError(~"C"));
     }
 
     #[test]
@@ -2561,7 +2525,7 @@ fn test_encode_hashmap_with_numeric_key() {
         let mut mem_buf = MemWriter::new();
         {
             let mut encoder = Encoder::new(&mut mem_buf as &mut io::Writer);
-            hm.encode(&mut encoder)
+            hm.encode(&mut encoder).unwrap();
         }
         let bytes = mem_buf.unwrap();
         let json_str = from_utf8(bytes).unwrap();
@@ -2581,7 +2545,7 @@ fn test_prettyencode_hashmap_with_numeric_key() {
         let mut mem_buf = MemWriter::new();
         {
             let mut encoder = PrettyEncoder::new(&mut mem_buf as &mut io::Writer);
-            hm.encode(&mut encoder)
+            hm.encode(&mut encoder).unwrap();
         }
         let bytes = mem_buf.unwrap();
         let json_str = from_utf8(bytes).unwrap();
@@ -2600,6 +2564,6 @@ fn test_hashmap_with_numeric_key_can_handle_double_quote_delimited_key() {
             Ok(o) => o
         };
         let mut decoder = Decoder::new(json_obj);
-        let _hm: HashMap<uint, bool> = Decodable::decode(&mut decoder);
+        let _hm: HashMap<uint, bool> = Decodable::decode(&mut decoder).unwrap();
     }
 }
diff --git a/src/libserialize/json_old.rs b/src/libserialize/json_old.rs
new file mode 100644 (file)
index 0000000..cc4c865
--- /dev/null
@@ -0,0 +1,2606 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Rust JSON serialization library
+// Copyright (c) 2011 Google Inc.
+
+#[forbid(non_camel_case_types)];
+#[allow(missing_doc)];
+
+/*!
+JSON parsing and serialization
+
+# What is JSON?
+
+JSON (JavaScript Object Notation) is a way to write data in Javascript.
+Like XML it allows one to encode structured data in a text format that can be read by humans easily.
+Its native compatibility with JavaScript and its simple syntax make it used widely.
+
+Json data are encoded in a form of "key":"value".
+Data types that can be encoded are JavaScript types :
+boolean (`true` or `false`), number (`f64`), string, array, object, null.
+An object is a series of string keys mapping to values, in `"key": value` format.
+Arrays are enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }).
+A simple JSON document encoding a person, his/her age, address and phone numbers could look like:
+
+```ignore
+{
+    "FirstName": "John",
+    "LastName": "Doe",
+    "Age": 43,
+    "Address": {
+        "Street": "Downing Street 10",
+        "City": "London",
+        "Country": "Great Britain"
+    },
+    "PhoneNumbers": [
+        "+44 1234567",
+        "+44 2345678"
+    ]
+}
+```
+
+# Rust Type-based Encoding and Decoding
+
+Rust provides a mechanism for low boilerplate encoding & decoding
+of values to and from JSON via the serialization API.
+To be able to encode a piece of data, it must implement the `serialize::Encodable` trait.
+To be able to decode a piece of data, it must implement the `serialize::Decodable` trait.
+The Rust compiler provides an annotation to automatically generate
+the code for these traits: `#[deriving(Decodable, Encodable)]`
+
+To encode using Encodable :
+
+```rust
+use std::io;
+use serialize::{json, Encodable};
+
+ #[deriving(Encodable)]
+ pub struct TestStruct   {
+    data_str: ~str,
+ }
+
+fn main() {
+    let to_encode_object = TestStruct{data_str:~"example of string to encode"};
+    let mut m = io::MemWriter::new();
+    {
+        let mut encoder = json::Encoder::new(&mut m as &mut std::io::Writer);
+        to_encode_object.encode(&mut encoder);
+    }
+}
+```
+
+Two wrapper functions are provided to encode a Encodable object
+into a string (~str) or buffer (~[u8]): `str_encode(&m)` and `buffer_encode(&m)`.
+
+```rust
+use serialize::json;
+let to_encode_object = ~"example of string to encode";
+let encoded_str: ~str = json::Encoder::str_encode(&to_encode_object);
+```
+
+JSON API provide an enum `json::Json` and a trait `ToJson` to encode object.
+The trait `ToJson` encode object into a container `json::Json` and the API provide writer
+to encode them into a stream or a string ...
+
+When using `ToJson` the `Encodable` trait implementation is not mandatory.
+
+A basic `ToJson` example using a TreeMap of attribute name / attribute value:
+
+
+```rust
+extern crate collections;
+extern crate serialize;
+
+use serialize::json;
+use serialize::json::ToJson;
+use collections::TreeMap;
+
+pub struct MyStruct  {
+    attr1: u8,
+    attr2: ~str,
+}
+
+impl ToJson for MyStruct {
+    fn to_json( &self ) -> json::Json {
+        let mut d = ~TreeMap::new();
+        d.insert(~"attr1", self.attr1.to_json());
+        d.insert(~"attr2", self.attr2.to_json());
+        json::Object(d)
+    }
+}
+
+fn main() {
+    let test2: MyStruct = MyStruct {attr1: 1, attr2:~"test"};
+    let tjson: json::Json = test2.to_json();
+    let json_str: ~str = tjson.to_str();
+}
+```
+
+To decode a JSON string using `Decodable` trait :
+
+```rust
+extern crate serialize;
+use serialize::{json, Decodable};
+
+#[deriving(Decodable)]
+pub struct MyStruct  {
+     attr1: u8,
+     attr2: ~str,
+}
+
+fn main() {
+    let json_str_to_decode: ~str =
+            ~"{\"attr1\":1,\"attr2\":\"toto\"}";
+    let json_object = json::from_str(json_str_to_decode);
+    let mut decoder = json::Decoder::new(json_object.unwrap());
+    let decoded_object: MyStruct = Decodable::decode(&mut decoder); // create the final object
+}
+```
+
+# Examples of use
+
+## Using Autoserialization
+
+Create a struct called TestStruct1 and serialize and deserialize it to and from JSON
+using the serialization API, using the derived serialization code.
+
+```rust
+extern crate serialize;
+use serialize::{json, Encodable, Decodable};
+
+ #[deriving(Decodable, Encodable)] //generate Decodable, Encodable impl.
+ pub struct TestStruct1  {
+    data_int: u8,
+    data_str: ~str,
+    data_vector: ~[u8],
+ }
+
+// To serialize use the `json::str_encode` to encode an object in a string.
+// It calls the generated `Encodable` impl.
+fn main() {
+    let to_encode_object = TestStruct1
+         {data_int: 1, data_str:~"toto", data_vector:~[2,3,4,5]};
+    let encoded_str: ~str = json::Encoder::str_encode(&to_encode_object);
+
+    // To deserialize use the `json::from_str` and `json::Decoder`
+
+    let json_object = json::from_str(encoded_str);
+    let mut decoder = json::Decoder::new(json_object.unwrap());
+    let decoded1: TestStruct1 = Decodable::decode(&mut decoder); // create the final object
+}
+```
+
+## Using `ToJson`
+
+This example use the ToJson impl to deserialize the JSON string.
+Example of `ToJson` trait implementation for TestStruct1.
+
+```rust
+extern crate serialize;
+extern crate collections;
+
+use serialize::json::ToJson;
+use serialize::{json, Encodable, Decodable};
+use collections::TreeMap;
+
+#[deriving(Decodable, Encodable)] // generate Decodable, Encodable impl.
+pub struct TestStruct1  {
+    data_int: u8,
+    data_str: ~str,
+    data_vector: ~[u8],
+}
+
+impl ToJson for TestStruct1 {
+    fn to_json( &self ) -> json::Json {
+        let mut d = ~TreeMap::new();
+        d.insert(~"data_int", self.data_int.to_json());
+        d.insert(~"data_str", self.data_str.to_json());
+        d.insert(~"data_vector", self.data_vector.to_json());
+        json::Object(d)
+    }
+}
+
+fn main() {
+    // Serialization using our impl of to_json
+
+    let test2: TestStruct1 = TestStruct1 {data_int: 1, data_str:~"toto", data_vector:~[2,3,4,5]};
+    let tjson: json::Json = test2.to_json();
+    let json_str: ~str = tjson.to_str();
+
+    // Deserialize like before.
+
+    let mut decoder = json::Decoder::new(json::from_str(json_str).unwrap());
+    // create the final object
+    let decoded2: TestStruct1 = Decodable::decode(&mut decoder);
+}
+```
+
+*/
+
+use std::char;
+use std::f64;
+use collections::HashMap;
+use std::io;
+use std::io::MemWriter;
+use std::num;
+use std::str;
+use std::fmt;
+
+use Encodable;
+use collections::TreeMap;
+
+macro_rules! try( ($e:expr) => (
+    match $e { Ok(e) => e, Err(e) => { self.error = Err(e); return } }
+) )
+
+/// Represents a json value
+#[deriving(Clone, Eq)]
+pub enum Json {
+    Number(f64),
+    String(~str),
+    Boolean(bool),
+    List(List),
+    Object(~Object),
+    Null,
+}
+
+pub type List = ~[Json];
+pub type Object = TreeMap<~str, Json>;
+
+#[deriving(Eq)]
+/// If an error occurs while parsing some JSON, this is the structure which is
+/// returned
+pub struct Error {
+    /// The line number at which the error occurred
+    priv line: uint,
+    /// The column number at which the error occurred
+    priv col: uint,
+    /// A message describing the type of the error
+    priv msg: ~str,
+}
+
+fn io_error_to_error(io: io::IoError) -> Error {
+    Error {
+        line: 0,
+        col: 0,
+        msg: format!("io error: {}", io)
+    }
+}
+
+fn escape_str(s: &str) -> ~str {
+    let mut escaped = ~"\"";
+    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 spaces(n: uint) -> ~str {
+    let mut ss = ~"";
+    for _ in range(0, n) { ss.push_str(" "); }
+    return ss;
+}
+
+/// A structure for implementing serialization to JSON.
+pub struct Encoder<'a> {
+    priv wr: &'a mut io::Writer,
+    priv error: io::IoResult<()>,
+}
+
+impl<'a> Encoder<'a> {
+    /// Creates a new JSON encoder whose output will be written to the writer
+    /// specified.
+    pub fn new<'a>(wr: &'a mut io::Writer) -> Encoder<'a> {
+        Encoder { wr: wr, error: Ok(()) }
+    }
+
+    /// Encode the specified struct into a json [u8]
+    pub fn buffer_encode<T:Encodable<Encoder<'a>>>(to_encode_object: &T) -> ~[u8]  {
+       //Serialize the object in a string using a writer
+        let mut m = MemWriter::new();
+        {
+            let mut encoder = Encoder::new(&mut m as &mut io::Writer);
+            to_encode_object.encode(&mut encoder);
+        }
+        m.unwrap()
+    }
+
+    /// Encode the specified struct into a json str
+    pub fn str_encode<T:Encodable<Encoder<'a>>>(to_encode_object: &T) -> ~str  {
+        let buff:~[u8] = Encoder::buffer_encode(to_encode_object);
+        str::from_utf8_owned(buff).unwrap()
+    }
+}
+
+impl<'a> ::Encoder for Encoder<'a> {
+    fn emit_nil(&mut self) { try!(write!(self.wr, "null")) }
+
+    fn emit_uint(&mut self, v: uint) { self.emit_f64(v as f64); }
+    fn emit_u64(&mut self, v: u64) { self.emit_f64(v as f64); }
+    fn emit_u32(&mut self, v: u32) { self.emit_f64(v as f64); }
+    fn emit_u16(&mut self, v: u16) { self.emit_f64(v as f64); }
+    fn emit_u8(&mut self, v: u8)   { self.emit_f64(v as f64); }
+
+    fn emit_int(&mut self, v: int) { self.emit_f64(v as f64); }
+    fn emit_i64(&mut self, v: i64) { self.emit_f64(v as f64); }
+    fn emit_i32(&mut self, v: i32) { self.emit_f64(v as f64); }
+    fn emit_i16(&mut self, v: i16) { self.emit_f64(v as f64); }
+    fn emit_i8(&mut self, v: i8)   { self.emit_f64(v as f64); }
+
+    fn emit_bool(&mut self, v: bool) {
+        if v {
+            try!(write!(self.wr, "true"));
+        } else {
+            try!(write!(self.wr, "false"));
+        }
+    }
+
+    fn emit_f64(&mut self, v: f64) {
+        try!(write!(self.wr, "{}", f64::to_str_digits(v, 6u)))
+    }
+    fn emit_f32(&mut self, v: f32) { self.emit_f64(v as f64); }
+
+    fn emit_char(&mut self, v: char) { self.emit_str(str::from_char(v)) }
+    fn emit_str(&mut self, v: &str) {
+        try!(write!(self.wr, "{}", escape_str(v)))
+    }
+
+    fn emit_enum(&mut self, _name: &str, f: |&mut Encoder<'a>|) { f(self) }
+
+    fn emit_enum_variant(&mut self,
+                         name: &str,
+                         _id: uint,
+                         cnt: uint,
+                         f: |&mut Encoder<'a>|) {
+        // enums are encoded as strings or objects
+        // Bunny => "Bunny"
+        // Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]}
+        if cnt == 0 {
+            try!(write!(self.wr, "{}", escape_str(name)));
+        } else {
+            try!(write!(self.wr, "\\{\"variant\":"));
+            try!(write!(self.wr, "{}", escape_str(name)));
+            try!(write!(self.wr, ",\"fields\":["));
+            f(self);
+            try!(write!(self.wr, "]\\}"));
+        }
+    }
+
+    fn emit_enum_variant_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+        if idx != 0 {
+            try!(write!(self.wr, ","));
+        }
+        f(self);
+    }
+
+    fn emit_enum_struct_variant(&mut self,
+                                name: &str,
+                                id: uint,
+                                cnt: uint,
+                                f: |&mut Encoder<'a>|) {
+        self.emit_enum_variant(name, id, cnt, f)
+    }
+
+    fn emit_enum_struct_variant_field(&mut self,
+                                      _: &str,
+                                      idx: uint,
+                                      f: |&mut Encoder<'a>|) {
+        self.emit_enum_variant_arg(idx, f)
+    }
+
+    fn emit_struct(&mut self, _: &str, _: uint, f: |&mut Encoder<'a>|) {
+        try!(write!(self.wr, r"\{"));
+        f(self);
+        try!(write!(self.wr, r"\}"));
+    }
+
+    fn emit_struct_field(&mut self,
+                         name: &str,
+                         idx: uint,
+                         f: |&mut Encoder<'a>|) {
+        if idx != 0 { try!(write!(self.wr, ",")) }
+        try!(write!(self.wr, "{}:", escape_str(name)));
+        f(self);
+    }
+
+    fn emit_tuple(&mut self, len: uint, f: |&mut Encoder<'a>|) {
+        self.emit_seq(len, f)
+    }
+    fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+        self.emit_seq_elt(idx, f)
+    }
+
+    fn emit_tuple_struct(&mut self,
+                         _name: &str,
+                         len: uint,
+                         f: |&mut Encoder<'a>|) {
+        self.emit_seq(len, f)
+    }
+    fn emit_tuple_struct_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+        self.emit_seq_elt(idx, f)
+    }
+
+    fn emit_option(&mut self, f: |&mut Encoder<'a>|) { f(self); }
+    fn emit_option_none(&mut self) { self.emit_nil(); }
+    fn emit_option_some(&mut self, f: |&mut Encoder<'a>|) { f(self); }
+
+    fn emit_seq(&mut self, _len: uint, f: |&mut Encoder<'a>|) {
+        try!(write!(self.wr, "["));
+        f(self);
+        try!(write!(self.wr, "]"));
+    }
+
+    fn emit_seq_elt(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+        if idx != 0 {
+            try!(write!(self.wr, ","));
+        }
+        f(self)
+    }
+
+    fn emit_map(&mut self, _len: uint, f: |&mut Encoder<'a>|) {
+        try!(write!(self.wr, r"\{"));
+        f(self);
+        try!(write!(self.wr, r"\}"));
+    }
+
+    fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+        use std::str::from_utf8;
+        if idx != 0 { try!(write!(self.wr, ",")) }
+        // 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();
+        let mut check_encoder = Encoder::new(&mut buf);
+        f(&mut check_encoder);
+        let buf = buf.unwrap();
+        let out = from_utf8(buf).unwrap();
+        let needs_wrapping = out.char_at(0) != '"' &&
+            out.char_at_reverse(out.len()) != '"';
+        if needs_wrapping { try!(write!(self.wr, "\"")); }
+        f(self);
+        if needs_wrapping { try!(write!(self.wr, "\"")); }
+    }
+
+    fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
+        try!(write!(self.wr, ":"));
+        f(self)
+    }
+}
+
+/// Another encoder for JSON, but prints out human-readable JSON instead of
+/// compact data
+pub struct PrettyEncoder<'a> {
+    priv wr: &'a mut io::Writer,
+    priv indent: uint,
+    priv error: io::IoResult<()>,
+}
+
+impl<'a> PrettyEncoder<'a> {
+    /// Creates a new encoder whose output will be written to the specified writer
+    pub fn new<'a>(wr: &'a mut io::Writer) -> PrettyEncoder<'a> {
+        PrettyEncoder {
+            wr: wr,
+            indent: 0,
+            error: Ok(())
+        }
+    }
+}
+
+impl<'a> ::Encoder for PrettyEncoder<'a> {
+    fn emit_nil(&mut self) { try!(write!(self.wr, "null")); }
+
+    fn emit_uint(&mut self, v: uint) { self.emit_f64(v as f64); }
+    fn emit_u64(&mut self, v: u64) { self.emit_f64(v as f64); }
+    fn emit_u32(&mut self, v: u32) { self.emit_f64(v as f64); }
+    fn emit_u16(&mut self, v: u16) { self.emit_f64(v as f64); }
+    fn emit_u8(&mut self, v: u8)   { self.emit_f64(v as f64); }
+
+    fn emit_int(&mut self, v: int) { self.emit_f64(v as f64); }
+    fn emit_i64(&mut self, v: i64) { self.emit_f64(v as f64); }
+    fn emit_i32(&mut self, v: i32) { self.emit_f64(v as f64); }
+    fn emit_i16(&mut self, v: i16) { self.emit_f64(v as f64); }
+    fn emit_i8(&mut self, v: i8)   { self.emit_f64(v as f64); }
+
+    fn emit_bool(&mut self, v: bool) {
+        if v {
+            try!(write!(self.wr, "true"));
+        } else {
+            try!(write!(self.wr, "false"));
+        }
+    }
+
+    fn emit_f64(&mut self, v: f64) {
+        try!(write!(self.wr, "{}", f64::to_str_digits(v, 6u)));
+    }
+    fn emit_f32(&mut self, v: f32) { self.emit_f64(v as f64); }
+
+    fn emit_char(&mut self, v: char) { self.emit_str(str::from_char(v)) }
+    fn emit_str(&mut self, v: &str) {
+        try!(write!(self.wr, "{}", escape_str(v)));
+    }
+
+    fn emit_enum(&mut self, _name: &str, f: |&mut PrettyEncoder<'a>|) {
+        f(self)
+    }
+
+    fn emit_enum_variant(&mut self,
+                         name: &str,
+                         _: uint,
+                         cnt: uint,
+                         f: |&mut PrettyEncoder<'a>|) {
+        if cnt == 0 {
+            try!(write!(self.wr, "{}", escape_str(name)));
+        } else {
+            self.indent += 2;
+            try!(write!(self.wr, "[\n{}{},\n", spaces(self.indent),
+                          escape_str(name)));
+            f(self);
+            self.indent -= 2;
+            try!(write!(self.wr, "\n{}]", spaces(self.indent)));
+        }
+    }
+
+    fn emit_enum_variant_arg(&mut self,
+                             idx: uint,
+                             f: |&mut PrettyEncoder<'a>|) {
+        if idx != 0 {
+            try!(write!(self.wr, ",\n"));
+        }
+        try!(write!(self.wr, "{}", spaces(self.indent)));
+        f(self)
+    }
+
+    fn emit_enum_struct_variant(&mut self,
+                                name: &str,
+                                id: uint,
+                                cnt: uint,
+                                f: |&mut PrettyEncoder<'a>|) {
+        self.emit_enum_variant(name, id, cnt, f)
+    }
+
+    fn emit_enum_struct_variant_field(&mut self,
+                                      _: &str,
+                                      idx: uint,
+                                      f: |&mut PrettyEncoder<'a>|) {
+        self.emit_enum_variant_arg(idx, f)
+    }
+
+
+    fn emit_struct(&mut self,
+                   _: &str,
+                   len: uint,
+                   f: |&mut PrettyEncoder<'a>|) {
+        if len == 0 {
+            try!(write!(self.wr, "\\{\\}"));
+        } else {
+            try!(write!(self.wr, "\\{"));
+            self.indent += 2;
+            f(self);
+            self.indent -= 2;
+            try!(write!(self.wr, "\n{}\\}", spaces(self.indent)));
+        }
+    }
+
+    fn emit_struct_field(&mut self,
+                         name: &str,
+                         idx: uint,
+                         f: |&mut PrettyEncoder<'a>|) {
+        if idx == 0 {
+            try!(write!(self.wr, "\n"));
+        } else {
+            try!(write!(self.wr, ",\n"));
+        }
+        try!(write!(self.wr, "{}{}: ", spaces(self.indent), escape_str(name)));
+        f(self);
+    }
+
+    fn emit_tuple(&mut self, len: uint, f: |&mut PrettyEncoder<'a>|) {
+        self.emit_seq(len, f)
+    }
+    fn emit_tuple_arg(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
+        self.emit_seq_elt(idx, f)
+    }
+
+    fn emit_tuple_struct(&mut self,
+                         _: &str,
+                         len: uint,
+                         f: |&mut PrettyEncoder<'a>|) {
+        self.emit_seq(len, f)
+    }
+    fn emit_tuple_struct_arg(&mut self,
+                             idx: uint,
+                             f: |&mut PrettyEncoder<'a>|) {
+        self.emit_seq_elt(idx, f)
+    }
+
+    fn emit_option(&mut self, f: |&mut PrettyEncoder<'a>|) { f(self); }
+    fn emit_option_none(&mut self) { self.emit_nil(); }
+    fn emit_option_some(&mut self, f: |&mut PrettyEncoder<'a>|) { f(self); }
+
+    fn emit_seq(&mut self, len: uint, f: |&mut PrettyEncoder<'a>|) {
+        if len == 0 {
+            try!(write!(self.wr, "[]"));
+        } else {
+            try!(write!(self.wr, "["));
+            self.indent += 2;
+            f(self);
+            self.indent -= 2;
+            try!(write!(self.wr, "\n{}]", spaces(self.indent)));
+        }
+    }
+
+    fn emit_seq_elt(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
+        if idx == 0 {
+            try!(write!(self.wr, "\n"));
+        } else {
+            try!(write!(self.wr, ",\n"));
+        }
+        try!(write!(self.wr, "{}", spaces(self.indent)));
+        f(self)
+    }
+
+    fn emit_map(&mut self, len: uint, f: |&mut PrettyEncoder<'a>|) {
+        if len == 0 {
+            try!(write!(self.wr, "\\{\\}"));
+        } else {
+            try!(write!(self.wr, "\\{"));
+            self.indent += 2;
+            f(self);
+            self.indent -= 2;
+            try!(write!(self.wr, "\n{}\\}", spaces(self.indent)));
+        }
+    }
+
+    fn emit_map_elt_key(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
+        use std::str::from_utf8;
+        if idx == 0 {
+            try!(write!(self.wr, "\n"));
+        } else {
+            try!(write!(self.wr, ",\n"));
+        }
+        try!(write!(self.wr, "{}", spaces(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();
+        let mut check_encoder = PrettyEncoder::new(&mut buf);
+        f(&mut check_encoder);
+        let buf = buf.unwrap();
+        let out = from_utf8(buf).unwrap();
+        let needs_wrapping = out.char_at(0) != '"' &&
+            out.char_at_reverse(out.len()) != '"';
+        if needs_wrapping { try!(write!(self.wr, "\"")); }
+        f(self);
+        if needs_wrapping { try!(write!(self.wr, "\"")); }
+    }
+
+    fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut PrettyEncoder<'a>|) {
+        try!(write!(self.wr, ": "));
+        f(self);
+    }
+}
+
+impl<E: ::Encoder> Encodable<E> for Json {
+    fn encode(&self, e: &mut E) {
+        match *self {
+            Number(v) => v.encode(e),
+            String(ref v) => v.encode(e),
+            Boolean(v) => v.encode(e),
+            List(ref v) => v.encode(e),
+            Object(ref v) => v.encode(e),
+            Null => e.emit_nil(),
+        }
+    }
+}
+
+impl Json {
+    /// Encodes a json value into a io::writer.  Uses a single line.
+    pub fn to_writer(&self, wr: &mut io::Writer) -> io::IoResult<()> {
+        let mut encoder = Encoder::new(wr);
+        self.encode(&mut encoder);
+        encoder.error
+    }
+
+    /// Encodes a json value into a io::writer.
+    /// Pretty-prints in a more readable format.
+    pub fn to_pretty_writer(&self, wr: &mut io::Writer) -> io::IoResult<()> {
+        let mut encoder = PrettyEncoder::new(wr);
+        self.encode(&mut encoder);
+        encoder.error
+    }
+
+    /// Encodes a json value into a string
+    pub fn to_pretty_str(&self) -> ~str {
+        let mut s = MemWriter::new();
+        self.to_pretty_writer(&mut s as &mut io::Writer).unwrap();
+        str::from_utf8_owned(s.unwrap()).unwrap()
+    }
+
+     /// If the Json value is an Object, returns the value associated with the provided key.
+    /// Otherwise, returns None.
+    pub fn find<'a>(&'a self, key: &~str) -> Option<&'a Json>{
+        match self {
+            &Object(ref map) => map.find(key),
+            _ => None
+        }
+    }
+
+    /// Attempts to get a nested Json Object for each key in `keys`.
+    /// If any key is found not to exist, find_path will return None.
+    /// Otherwise, it will return the Json value associated with the final key.
+    pub fn find_path<'a>(&'a self, keys: &[&~str]) -> Option<&'a Json>{
+        let mut target = self;
+        for key in keys.iter() {
+            match target.find(*key) {
+                Some(t) => { target = t; },
+                None => return None
+            }
+        }
+        Some(target)
+    }
+
+    /// If the Json value is an Object, performs a depth-first search until
+    /// a value associated with the provided key is found. If no value is found
+    /// or the Json value is not an Object, returns None.
+    pub fn search<'a>(&'a self, key: &~str) -> Option<&'a Json> {
+        match self {
+            &Object(ref map) => {
+                match map.find(key) {
+                    Some(json_value) => Some(json_value),
+                    None => {
+                        let mut value : Option<&'a Json> = None;
+                        for (_, v) in map.iter() {
+                            value = v.search(key);
+                            if value.is_some() {
+                                break;
+                            }
+                        }
+                        value
+                    }
+                }
+            },
+            _ => None
+        }
+    }
+
+    /// Returns true if the Json value is an Object. Returns false otherwise.
+    pub fn is_object<'a>(&'a self) -> bool {
+        self.as_object().is_some()
+    }
+
+    /// If the Json value is an Object, returns the associated TreeMap.
+    /// Returns None otherwise.
+    pub fn as_object<'a>(&'a self) -> Option<&'a Object> {
+        match self {
+            &Object(ref map) => Some(&**map),
+            _ => None
+        }
+    }
+
+    /// Returns true if the Json value is a List. Returns false otherwise.
+    pub fn is_list<'a>(&'a self) -> bool {
+        self.as_list().is_some()
+    }
+
+    /// If the Json value is a List, returns the associated vector.
+    /// Returns None otherwise.
+    pub fn as_list<'a>(&'a self) -> Option<&'a List> {
+        match self {
+            &List(ref list) => Some(&*list),
+            _ => None
+        }
+    }
+
+    /// Returns true if the Json value is a String. Returns false otherwise.
+    pub fn is_string<'a>(&'a self) -> bool {
+        self.as_string().is_some()
+    }
+
+    /// If the Json value is a String, returns the associated str.
+    /// Returns None otherwise.
+    pub fn as_string<'a>(&'a self) -> Option<&'a str> {
+        match *self {
+            String(ref s) => Some(s.as_slice()),
+            _ => None
+        }
+    }
+
+    /// Returns true if the Json value is a Number. Returns false otherwise.
+    pub fn is_number(&self) -> bool {
+        self.as_number().is_some()
+    }
+
+    /// If the Json value is a Number, returns the associated f64.
+    /// Returns None otherwise.
+    pub fn as_number(&self) -> Option<f64> {
+        match self {
+            &Number(n) => Some(n),
+            _ => None
+        }
+    }
+
+    /// Returns true if the Json value is a Boolean. Returns false otherwise.
+    pub fn is_boolean(&self) -> bool {
+        self.as_boolean().is_some()
+    }
+
+    /// If the Json value is a Boolean, returns the associated bool.
+    /// Returns None otherwise.
+    pub fn as_boolean(&self) -> Option<bool> {
+        match self {
+            &Boolean(b) => Some(b),
+            _ => None
+        }
+    }
+
+    /// Returns true if the Json value is a Null. Returns false otherwise.
+    pub fn is_null(&self) -> bool {
+        self.as_null().is_some()
+    }
+
+    /// If the Json value is a Null, returns ().
+    /// Returns None otherwise.
+    pub fn as_null(&self) -> Option<()> {
+        match self {
+            &Null => Some(()),
+            _ => None
+        }
+    }
+}
+
+pub struct Parser<T> {
+    priv rdr: T,
+    priv ch: Option<char>,
+    priv line: uint,
+    priv col: uint,
+}
+
+impl<T: Iterator<char>> Parser<T> {
+    /// Decode a json value from an Iterator<char>
+    pub fn new(rdr: T) -> Parser<T> {
+        let mut p = Parser {
+            rdr: rdr,
+            ch: Some('\x00'),
+            line: 1,
+            col: 0,
+        };
+        p.bump();
+        p
+    }
+}
+
+impl<T: Iterator<char>> Parser<T> {
+    pub fn parse(&mut self) -> Result<Json, Error> {
+        match self.parse_value() {
+          Ok(value) => {
+            // Skip trailing whitespaces.
+            self.parse_whitespace();
+            // Make sure there is no trailing characters.
+            if self.eof() {
+                Ok(value)
+            } else {
+                self.error(~"trailing characters")
+            }
+          }
+          Err(e) => Err(e)
+        }
+    }
+}
+
+impl<T : Iterator<char>> Parser<T> {
+    fn eof(&self) -> bool { self.ch.is_none() }
+    fn ch_or_null(&self) -> char { self.ch.unwrap_or('\x00') }
+    fn bump(&mut self) {
+        self.ch = self.rdr.next();
+
+        if self.ch_is('\n') {
+            self.line += 1u;
+            self.col = 1u;
+        } else {
+            self.col += 1u;
+        }
+    }
+
+    fn next_char(&mut self) -> Option<char> {
+        self.bump();
+        self.ch
+    }
+    fn ch_is(&self, c: char) -> bool {
+        self.ch == Some(c)
+    }
+
+    fn error<T>(&self, msg: ~str) -> Result<T, Error> {
+        Err(Error { line: self.line, col: self.col, msg: msg })
+    }
+
+    fn parse_value(&mut self) -> Result<Json, Error> {
+        self.parse_whitespace();
+
+        if self.eof() { return self.error(~"EOF while parsing value"); }
+
+        match self.ch_or_null() {
+            'n' => self.parse_ident("ull", Null),
+            't' => self.parse_ident("rue", Boolean(true)),
+            'f' => self.parse_ident("alse", Boolean(false)),
+            '0' .. '9' | '-' => self.parse_number(),
+            '"' => {
+                match self.parse_str() {
+                    Ok(s) => Ok(String(s)),
+                    Err(e) => Err(e),
+                }
+            },
+            '[' => self.parse_list(),
+            '{' => self.parse_object(),
+            _ => self.error(~"invalid syntax"),
+        }
+    }
+
+    fn parse_whitespace(&mut self) {
+        while self.ch_is(' ') ||
+              self.ch_is('\n') ||
+              self.ch_is('\t') ||
+              self.ch_is('\r') { self.bump(); }
+    }
+
+    fn parse_ident(&mut self, ident: &str, value: Json) -> Result<Json, Error> {
+        if ident.chars().all(|c| Some(c) == self.next_char()) {
+            self.bump();
+            Ok(value)
+        } else {
+            self.error(~"invalid syntax")
+        }
+    }
+
+    fn parse_number(&mut self) -> Result<Json, Error> {
+        let mut neg = 1.0;
+
+        if self.ch_is('-') {
+            self.bump();
+            neg = -1.0;
+        }
+
+        let mut res = match self.parse_integer() {
+          Ok(res) => res,
+          Err(e) => return Err(e)
+        };
+
+        if self.ch_is('.') {
+            match self.parse_decimal(res) {
+              Ok(r) => res = r,
+              Err(e) => return Err(e)
+            }
+        }
+
+        if self.ch_is('e') || self.ch_is('E') {
+            match self.parse_exponent(res) {
+              Ok(r) => res = r,
+              Err(e) => return Err(e)
+            }
+        }
+
+        Ok(Number(neg * res))
+    }
+
+    fn parse_integer(&mut self) -> Result<f64, Error> {
+        let mut res = 0.0;
+
+        match self.ch_or_null() {
+            '0' => {
+                self.bump();
+
+                // There can be only one leading '0'.
+                match self.ch_or_null() {
+                    '0' .. '9' => return self.error(~"invalid number"),
+                    _ => ()
+                }
+            },
+            '1' .. '9' => {
+                while !self.eof() {
+                    match self.ch_or_null() {
+                        c @ '0' .. '9' => {
+                            res *= 10.0;
+                            res += ((c as int) - ('0' as int)) as f64;
+
+                            self.bump();
+                        }
+                        _ => break,
+                    }
+                }
+            }
+            _ => return self.error(~"invalid number"),
+        }
+        Ok(res)
+    }
+
+    fn parse_decimal(&mut self, res: f64) -> Result<f64, Error> {
+        self.bump();
+
+        // Make sure a digit follows the decimal place.
+        match self.ch_or_null() {
+            '0' .. '9' => (),
+             _ => return self.error(~"invalid number")
+        }
+
+        let mut res = res;
+        let mut dec = 1.0;
+        while !self.eof() {
+            match self.ch_or_null() {
+                c @ '0' .. '9' => {
+                    dec /= 10.0;
+                    res += (((c as int) - ('0' as int)) as f64) * dec;
+
+                    self.bump();
+                }
+                _ => break,
+            }
+        }
+
+        Ok(res)
+    }
+
+    fn parse_exponent(&mut self, mut res: f64) -> Result<f64, Error> {
+        self.bump();
+
+        let mut exp = 0u;
+        let mut neg_exp = false;
+
+        if self.ch_is('+') {
+            self.bump();
+        } else if self.ch_is('-') {
+            self.bump();
+            neg_exp = true;
+        }
+
+        // Make sure a digit follows the exponent place.
+        match self.ch_or_null() {
+            '0' .. '9' => (),
+            _ => return self.error(~"invalid number")
+        }
+        while !self.eof() {
+            match self.ch_or_null() {
+                c @ '0' .. '9' => {
+                    exp *= 10;
+                    exp += (c as uint) - ('0' as uint);
+
+                    self.bump();
+                }
+                _ => break
+            }
+        }
+
+        let exp: f64 = num::pow(10u as f64, exp);
+        if neg_exp {
+            res /= exp;
+        } else {
+            res *= exp;
+        }
+
+        Ok(res)
+    }
+
+    fn parse_str(&mut self) -> Result<~str, Error> {
+        let mut escape = false;
+        let mut res = ~"";
+
+        loop {
+            self.bump();
+            if self.eof() {
+                return self.error(~"EOF while parsing string");
+            }
+
+            if escape {
+                match self.ch_or_null() {
+                    '"' => res.push_char('"'),
+                    '\\' => res.push_char('\\'),
+                    '/' => res.push_char('/'),
+                    'b' => res.push_char('\x08'),
+                    'f' => res.push_char('\x0c'),
+                    'n' => res.push_char('\n'),
+                    'r' => res.push_char('\r'),
+                    't' => res.push_char('\t'),
+                    'u' => {
+                        // Parse \u1234.
+                        let mut i = 0u;
+                        let mut n = 0u;
+                        while i < 4u && !self.eof() {
+                            self.bump();
+                            n = match self.ch_or_null() {
+                                c @ '0' .. '9' => n * 16u + (c as uint) - ('0' as uint),
+                                'a' | 'A' => n * 16u + 10u,
+                                'b' | 'B' => n * 16u + 11u,
+                                'c' | 'C' => n * 16u + 12u,
+                                'd' | 'D' => n * 16u + 13u,
+                                'e' | 'E' => n * 16u + 14u,
+                                'f' | 'F' => n * 16u + 15u,
+                                _ => return self.error(
+                                    ~"invalid \\u escape (unrecognized hex)")
+                            };
+
+                            i += 1u;
+                        }
+
+                        // Error out if we didn't parse 4 digits.
+                        if i != 4u {
+                            return self.error(
+                                ~"invalid \\u escape (not four digits)");
+                        }
+
+                        res.push_char(char::from_u32(n as u32).unwrap());
+                    }
+                    _ => return self.error(~"invalid escape"),
+                }
+                escape = false;
+            } else if self.ch_is('\\') {
+                escape = true;
+            } else {
+                match self.ch {
+                    Some('"') => { self.bump(); return Ok(res); },
+                    Some(c) => res.push_char(c),
+                    None => unreachable!()
+                }
+            }
+        }
+    }
+
+    fn parse_list(&mut self) -> Result<Json, Error> {
+        self.bump();
+        self.parse_whitespace();
+
+        let mut values = ~[];
+
+        if self.ch_is(']') {
+            self.bump();
+            return Ok(List(values));
+        }
+
+        loop {
+            match self.parse_value() {
+              Ok(v) => values.push(v),
+              Err(e) => return Err(e)
+            }
+
+            self.parse_whitespace();
+            if self.eof() {
+                return self.error(~"EOF while parsing list");
+            }
+
+            if self.ch_is(',') {
+                self.bump();
+            } else if self.ch_is(']') {
+                self.bump();
+                return Ok(List(values));
+            } else {
+                return self.error(~"expected `,` or `]`")
+            }
+        };
+    }
+
+    fn parse_object(&mut self) -> Result<Json, Error> {
+        self.bump();
+        self.parse_whitespace();
+
+        let mut values = ~TreeMap::new();
+
+        if self.ch_is('}') {
+          self.bump();
+          return Ok(Object(values));
+        }
+
+        while !self.eof() {
+            self.parse_whitespace();
+
+            if !self.ch_is('"') {
+                return self.error(~"key must be a string");
+            }
+
+            let key = match self.parse_str() {
+              Ok(key) => key,
+              Err(e) => return Err(e)
+            };
+
+            self.parse_whitespace();
+
+            if !self.ch_is(':') {
+                if self.eof() { break; }
+                return self.error(~"expected `:`");
+            }
+            self.bump();
+
+            match self.parse_value() {
+              Ok(value) => { values.insert(key, value); }
+              Err(e) => return Err(e)
+            }
+            self.parse_whitespace();
+
+            match self.ch_or_null() {
+                ',' => self.bump(),
+                '}' => { self.bump(); return Ok(Object(values)); },
+                _ => {
+                    if self.eof() { break; }
+                    return self.error(~"expected `,` or `}`");
+                }
+            }
+        }
+
+        return self.error(~"EOF while parsing object");
+    }
+}
+
+/// Decodes a json value from an `&mut io::Reader`
+pub fn from_reader(rdr: &mut io::Reader) -> Result<Json, Error> {
+    let contents = match rdr.read_to_end() {
+        Ok(c) => c,
+        Err(e) => return Err(io_error_to_error(e))
+    };
+    let s = match str::from_utf8_owned(contents) {
+        Some(s) => s,
+        None => return Err(Error { line: 0, col: 0, msg: ~"contents not utf-8" })
+    };
+    let mut parser = Parser::new(s.chars());
+    parser.parse()
+}
+
+/// Decodes a json value from a string
+pub fn from_str(s: &str) -> Result<Json, Error> {
+    let mut parser = Parser::new(s.chars());
+    parser.parse()
+}
+
+/// A structure to decode JSON to values in rust.
+pub struct Decoder {
+    priv stack: ~[Json],
+}
+
+impl Decoder {
+    /// Creates a new decoder instance for decoding the specified JSON value.
+    pub fn new(json: Json) -> Decoder {
+        Decoder {
+            stack: ~[json]
+        }
+    }
+}
+
+impl Decoder {
+    fn err(&self, msg: &str) -> ! {
+        fail!("JSON decode error: {}", msg);
+    }
+    fn missing_field(&self, field: &str, object: ~Object) -> ! {
+        self.err(format!("missing required '{}' field in object: {}",
+                         field, Object(object).to_str()))
+    }
+    fn expected(&self, expected: &str, found: &Json) -> ! {
+        let found_s = match *found {
+            Null => "null",
+            List(..) => "list",
+            Object(..) => "object",
+            Number(..) => "number",
+            String(..) => "string",
+            Boolean(..) => "boolean"
+        };
+        self.err(format!("expected {expct} but found {fnd}: {val}",
+                         expct=expected, fnd=found_s, val=found.to_str()))
+    }
+}
+
+impl ::Decoder for Decoder {
+    fn read_nil(&mut self) -> () {
+        debug!("read_nil");
+        match self.stack.pop().unwrap() {
+            Null => (),
+            value => self.expected("null", &value)
+        }
+    }
+
+    fn read_u64(&mut self)  -> u64  { self.read_f64() as u64 }
+    fn read_u32(&mut self)  -> u32  { self.read_f64() as u32 }
+    fn read_u16(&mut self)  -> u16  { self.read_f64() as u16 }
+    fn read_u8 (&mut self)  -> u8   { self.read_f64() as u8 }
+    fn read_uint(&mut self) -> uint { self.read_f64() as uint }
+
+    fn read_i64(&mut self) -> i64 { self.read_f64() as i64 }
+    fn read_i32(&mut self) -> i32 { self.read_f64() as i32 }
+    fn read_i16(&mut self) -> i16 { self.read_f64() as i16 }
+    fn read_i8 (&mut self) -> i8  { self.read_f64() as i8 }
+    fn read_int(&mut self) -> int { self.read_f64() as int }
+
+    fn read_bool(&mut self) -> bool {
+        debug!("read_bool");
+        match self.stack.pop().unwrap() {
+            Boolean(b) => b,
+            value => self.expected("boolean", &value)
+        }
+    }
+
+    fn read_f64(&mut self) -> f64 {
+        use std::from_str::FromStr;
+        debug!("read_f64");
+        match self.stack.pop().unwrap() {
+            Number(f) => f,
+            String(s) => {
+                // re: #12967.. a type w/ numeric keys (ie HashMap<uint, V> etc)
+                // is going to have a string here, as per JSON spec..
+                FromStr::from_str(s).unwrap()
+            },
+            value => self.expected("number", &value)
+        }
+    }
+
+    fn read_f32(&mut self) -> f32 { self.read_f64() as f32 }
+
+    fn read_char(&mut self) -> char {
+        let s = self.read_str();
+        {
+            let mut it = s.chars();
+            match (it.next(), it.next()) {
+                // exactly one character
+                (Some(c), None) => return c,
+                _ => ()
+            }
+        }
+        self.expected("single character string", &String(s))
+    }
+
+    fn read_str(&mut self) -> ~str {
+        debug!("read_str");
+        match self.stack.pop().unwrap() {
+            String(s) => s,
+            value => self.expected("string", &value)
+        }
+    }
+
+    fn read_enum<T>(&mut self, name: &str, f: |&mut Decoder| -> T) -> T {
+        debug!("read_enum({})", name);
+        f(self)
+    }
+
+    fn read_enum_variant<T>(&mut self,
+                            names: &[&str],
+                            f: |&mut Decoder, uint| -> T)
+                            -> T {
+        debug!("read_enum_variant(names={:?})", names);
+        let name = match self.stack.pop().unwrap() {
+            String(s) => s,
+            Object(mut o) => {
+                let n = match o.pop(&~"variant") {
+                    Some(String(s)) => s,
+                    Some(val) => self.expected("string", &val),
+                    None => self.missing_field("variant", o)
+                };
+                match o.pop(&~"fields") {
+                    Some(List(l)) => {
+                        for field in l.move_rev_iter() {
+                            self.stack.push(field.clone());
+                        }
+                    },
+                    Some(val) => self.expected("list", &val),
+                    None => {
+                        // re-insert the variant field so we're
+                        // printing the "whole" struct in the error
+                        // message... ick.
+                        o.insert(~"variant", String(n));
+                        self.missing_field("fields", o);
+                    }
+                }
+                n
+            }
+            json => self.expected("string or object", &json)
+        };
+        let idx = match names.iter().position(|n| str::eq_slice(*n, name)) {
+            Some(idx) => idx,
+            None => self.err(format!("unknown variant name: {}", name))
+        };
+        f(self, idx)
+    }
+
+    fn read_enum_variant_arg<T>(&mut self, idx: uint, f: |&mut Decoder| -> T)
+                                -> T {
+        debug!("read_enum_variant_arg(idx={})", idx);
+        f(self)
+    }
+
+    fn read_enum_struct_variant<T>(&mut self,
+                                   names: &[&str],
+                                   f: |&mut Decoder, uint| -> T)
+                                   -> T {
+        debug!("read_enum_struct_variant(names={:?})", names);
+        self.read_enum_variant(names, f)
+    }
+
+
+    fn read_enum_struct_variant_field<T>(&mut self,
+                                         name: &str,
+                                         idx: uint,
+                                         f: |&mut Decoder| -> T)
+                                         -> T {
+        debug!("read_enum_struct_variant_field(name={}, idx={})", name, idx);
+        self.read_enum_variant_arg(idx, f)
+    }
+
+    fn read_struct<T>(&mut self,
+                      name: &str,
+                      len: uint,
+                      f: |&mut Decoder| -> T)
+                      -> T {
+        debug!("read_struct(name={}, len={})", name, len);
+        let value = f(self);
+        self.stack.pop().unwrap();
+        value
+    }
+
+    fn read_struct_field<T>(&mut self,
+                            name: &str,
+                            idx: uint,
+                            f: |&mut Decoder| -> T)
+                            -> T {
+        debug!("read_struct_field(name={}, idx={})", name, idx);
+        match self.stack.pop().unwrap() {
+            Object(mut obj) => {
+                let value = match obj.pop(&name.to_owned()) {
+                    None => self.missing_field(name, obj),
+                    Some(json) => {
+                        self.stack.push(json);
+                        f(self)
+                    }
+                };
+                self.stack.push(Object(obj));
+                value
+            }
+            value => self.expected("object", &value)
+        }
+    }
+
+    fn read_tuple<T>(&mut self, f: |&mut Decoder, uint| -> T) -> T {
+        debug!("read_tuple()");
+        self.read_seq(f)
+    }
+
+    fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder| -> T) -> T {
+        debug!("read_tuple_arg(idx={})", idx);
+        self.read_seq_elt(idx, f)
+    }
+
+    fn read_tuple_struct<T>(&mut self,
+                            name: &str,
+                            f: |&mut Decoder, uint| -> T)
+                            -> T {
+        debug!("read_tuple_struct(name={})", name);
+        self.read_tuple(f)
+    }
+
+    fn read_tuple_struct_arg<T>(&mut self,
+                                idx: uint,
+                                f: |&mut Decoder| -> T)
+                                -> T {
+        debug!("read_tuple_struct_arg(idx={})", idx);
+        self.read_tuple_arg(idx, f)
+    }
+
+    fn read_option<T>(&mut self, f: |&mut Decoder, bool| -> T) -> T {
+        match self.stack.pop().unwrap() {
+            Null => f(self, false),
+            value => { self.stack.push(value); f(self, true) }
+        }
+    }
+
+    fn read_seq<T>(&mut self, f: |&mut Decoder, uint| -> T) -> T {
+        debug!("read_seq()");
+        let len = match self.stack.pop().unwrap() {
+            List(list) => {
+                let len = list.len();
+                for v in list.move_rev_iter() {
+                    self.stack.push(v);
+                }
+                len
+            }
+            value => self.expected("list", &value)
+        };
+        f(self, len)
+    }
+
+    fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder| -> T) -> T {
+        debug!("read_seq_elt(idx={})", idx);
+        f(self)
+    }
+
+    fn read_map<T>(&mut self, f: |&mut Decoder, uint| -> T) -> T {
+        debug!("read_map()");
+        let len = match self.stack.pop().unwrap() {
+            Object(obj) => {
+                let len = obj.len();
+                for (key, value) in obj.move_iter() {
+                    self.stack.push(value);
+                    self.stack.push(String(key));
+                }
+                len
+            }
+            value => self.expected("object", &value)
+        };
+        f(self, len)
+    }
+
+    fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder| -> T)
+                           -> T {
+        debug!("read_map_elt_key(idx={})", idx);
+        f(self)
+    }
+
+    fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder| -> T)
+                           -> T {
+        debug!("read_map_elt_val(idx={})", idx);
+        f(self)
+    }
+}
+
+/// Test if two json values are less than one another
+impl Ord for Json {
+    fn lt(&self, other: &Json) -> bool {
+        match *self {
+            Number(f0) => {
+                match *other {
+                    Number(f1) => f0 < f1,
+                    String(_) | Boolean(_) | List(_) | Object(_) |
+                    Null => true
+                }
+            }
+
+            String(ref s0) => {
+                match *other {
+                    Number(_) => false,
+                    String(ref s1) => s0 < s1,
+                    Boolean(_) | List(_) | Object(_) | Null => true
+                }
+            }
+
+            Boolean(b0) => {
+                match *other {
+                    Number(_) | String(_) => false,
+                    Boolean(b1) => b0 < b1,
+                    List(_) | Object(_) | Null => true
+                }
+            }
+
+            List(ref l0) => {
+                match *other {
+                    Number(_) | String(_) | Boolean(_) => false,
+                    List(ref l1) => (*l0) < (*l1),
+                    Object(_) | Null => true
+                }
+            }
+
+            Object(ref d0) => {
+                match *other {
+                    Number(_) | String(_) | Boolean(_) | List(_) => false,
+                    Object(ref d1) => d0 < d1,
+                    Null => true
+                }
+            }
+
+            Null => {
+                match *other {
+                    Number(_) | String(_) | Boolean(_) | List(_) |
+                    Object(_) =>
+                        false,
+                    Null => true
+                }
+            }
+        }
+    }
+}
+
+/// A trait for converting values to JSON
+pub trait ToJson {
+    /// Converts the value of `self` to an instance of JSON
+    fn to_json(&self) -> Json;
+}
+
+impl ToJson for Json {
+    fn to_json(&self) -> Json { (*self).clone() }
+}
+
+impl ToJson for int {
+    fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for i8 {
+    fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for i16 {
+    fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for i32 {
+    fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for i64 {
+    fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for uint {
+    fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for u8 {
+    fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for u16 {
+    fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for u32 {
+    fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for u64 {
+    fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for f32 {
+    fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for f64 {
+    fn to_json(&self) -> Json { Number(*self) }
+}
+
+impl ToJson for () {
+    fn to_json(&self) -> Json { Null }
+}
+
+impl ToJson for bool {
+    fn to_json(&self) -> Json { Boolean(*self) }
+}
+
+impl ToJson for ~str {
+    fn to_json(&self) -> Json { String((*self).clone()) }
+}
+
+impl<A:ToJson,B:ToJson> ToJson for (A, B) {
+    fn to_json(&self) -> Json {
+        match *self {
+          (ref a, ref b) => {
+            List(~[a.to_json(), b.to_json()])
+          }
+        }
+    }
+}
+
+impl<A:ToJson,B:ToJson,C:ToJson> ToJson for (A, B, C) {
+    fn to_json(&self) -> Json {
+        match *self {
+          (ref a, ref b, ref c) => {
+            List(~[a.to_json(), b.to_json(), c.to_json()])
+          }
+        }
+    }
+}
+
+impl<A:ToJson> ToJson for ~[A] {
+    fn to_json(&self) -> Json { List(self.map(|elt| elt.to_json())) }
+}
+
+impl<A:ToJson> ToJson for TreeMap<~str, A> {
+    fn to_json(&self) -> Json {
+        let mut d = TreeMap::new();
+        for (key, value) in self.iter() {
+            d.insert((*key).clone(), value.to_json());
+        }
+        Object(~d)
+    }
+}
+
+impl<A:ToJson> ToJson for HashMap<~str, A> {
+    fn to_json(&self) -> Json {
+        let mut d = TreeMap::new();
+        for (key, value) in self.iter() {
+            d.insert((*key).clone(), value.to_json());
+        }
+        Object(~d)
+    }
+}
+
+impl<A:ToJson> ToJson for Option<A> {
+    fn to_json(&self) -> Json {
+        match *self {
+          None => Null,
+          Some(ref value) => value.to_json()
+        }
+    }
+}
+
+impl fmt::Show for Json {
+    /// Encodes a json value into a string
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.to_writer(f.buf)
+    }
+}
+
+impl fmt::Show for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f.buf, "{}:{}: {}", self.line, self.col, self.msg)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use {Encodable, Decodable};
+    use super::{Encoder, Decoder, Error, Boolean, Number, List, String, Null,
+                PrettyEncoder, Object, Json, from_str};
+    use std::io;
+    use collections::TreeMap;
+
+    #[deriving(Eq, Encodable, Decodable, Show)]
+    enum Animal {
+        Dog,
+        Frog(~str, int)
+    }
+
+    #[deriving(Eq, Encodable, Decodable, Show)]
+    struct Inner {
+        a: (),
+        b: uint,
+        c: ~[~str],
+    }
+
+    #[deriving(Eq, Encodable, Decodable, Show)]
+    struct Outer {
+        inner: ~[Inner],
+    }
+
+    fn mk_object(items: &[(~str, Json)]) -> Json {
+        let mut d = ~TreeMap::new();
+
+        for item in items.iter() {
+            match *item {
+                (ref key, ref value) => { d.insert((*key).clone(), (*value).clone()); },
+            }
+        };
+
+        Object(d)
+    }
+
+    #[test]
+    fn test_write_null() {
+        assert_eq!(Null.to_str(), ~"null");
+        assert_eq!(Null.to_pretty_str(), ~"null");
+    }
+
+
+    #[test]
+    fn test_write_number() {
+        assert_eq!(Number(3.0).to_str(), ~"3");
+        assert_eq!(Number(3.0).to_pretty_str(), ~"3");
+
+        assert_eq!(Number(3.1).to_str(), ~"3.1");
+        assert_eq!(Number(3.1).to_pretty_str(), ~"3.1");
+
+        assert_eq!(Number(-1.5).to_str(), ~"-1.5");
+        assert_eq!(Number(-1.5).to_pretty_str(), ~"-1.5");
+
+        assert_eq!(Number(0.5).to_str(), ~"0.5");
+        assert_eq!(Number(0.5).to_pretty_str(), ~"0.5");
+    }
+
+    #[test]
+    fn test_write_str() {
+        assert_eq!(String(~"").to_str(), ~"\"\"");
+        assert_eq!(String(~"").to_pretty_str(), ~"\"\"");
+
+        assert_eq!(String(~"foo").to_str(), ~"\"foo\"");
+        assert_eq!(String(~"foo").to_pretty_str(), ~"\"foo\"");
+    }
+
+    #[test]
+    fn test_write_bool() {
+        assert_eq!(Boolean(true).to_str(), ~"true");
+        assert_eq!(Boolean(true).to_pretty_str(), ~"true");
+
+        assert_eq!(Boolean(false).to_str(), ~"false");
+        assert_eq!(Boolean(false).to_pretty_str(), ~"false");
+    }
+
+    #[test]
+    fn test_write_list() {
+        assert_eq!(List(~[]).to_str(), ~"[]");
+        assert_eq!(List(~[]).to_pretty_str(), ~"[]");
+
+        assert_eq!(List(~[Boolean(true)]).to_str(), ~"[true]");
+        assert_eq!(
+            List(~[Boolean(true)]).to_pretty_str(),
+            ~"\
+            [\n  \
+                true\n\
+            ]"
+        );
+
+        let long_test_list = List(~[
+            Boolean(false),
+            Null,
+            List(~[String(~"foo\nbar"), Number(3.5)])]);
+
+        assert_eq!(long_test_list.to_str(),
+            ~"[false,null,[\"foo\\nbar\",3.5]]");
+        assert_eq!(
+            long_test_list.to_pretty_str(),
+            ~"\
+            [\n  \
+                false,\n  \
+                null,\n  \
+                [\n    \
+                    \"foo\\nbar\",\n    \
+                    3.5\n  \
+                ]\n\
+            ]"
+        );
+    }
+
+    #[test]
+    fn test_write_object() {
+        assert_eq!(mk_object([]).to_str(), ~"{}");
+        assert_eq!(mk_object([]).to_pretty_str(), ~"{}");
+
+        assert_eq!(
+            mk_object([(~"a", Boolean(true))]).to_str(),
+            ~"{\"a\":true}"
+        );
+        assert_eq!(
+            mk_object([(~"a", Boolean(true))]).to_pretty_str(),
+            ~"\
+            {\n  \
+                \"a\": true\n\
+            }"
+        );
+
+        let complex_obj = mk_object([
+                (~"b", List(~[
+                    mk_object([(~"c", String(~"\x0c\r"))]),
+                    mk_object([(~"d", String(~""))])
+                ]))
+            ]);
+
+        assert_eq!(
+            complex_obj.to_str(),
+            ~"{\
+                \"b\":[\
+                    {\"c\":\"\\f\\r\"},\
+                    {\"d\":\"\"}\
+                ]\
+            }"
+        );
+        assert_eq!(
+            complex_obj.to_pretty_str(),
+            ~"\
+            {\n  \
+                \"b\": [\n    \
+                    {\n      \
+                        \"c\": \"\\f\\r\"\n    \
+                    },\n    \
+                    {\n      \
+                        \"d\": \"\"\n    \
+                    }\n  \
+                ]\n\
+            }"
+        );
+
+        let a = mk_object([
+            (~"a", Boolean(true)),
+            (~"b", List(~[
+                mk_object([(~"c", String(~"\x0c\r"))]),
+                mk_object([(~"d", String(~""))])
+            ]))
+        ]);
+
+        // We can't compare the strings directly because the object fields be
+        // printed in a different order.
+        assert_eq!(a.clone(), from_str(a.to_str()).unwrap());
+        assert_eq!(a.clone(), from_str(a.to_pretty_str()).unwrap());
+    }
+
+    fn with_str_writer(f: |&mut io::Writer|) -> ~str {
+        use std::io::MemWriter;
+        use std::str;
+
+        let mut m = MemWriter::new();
+        f(&mut m as &mut io::Writer);
+        str::from_utf8_owned(m.unwrap()).unwrap()
+    }
+
+    #[test]
+    fn test_write_enum() {
+        let animal = Dog;
+        assert_eq!(
+            with_str_writer(|wr| {
+                let mut encoder = Encoder::new(wr);
+                animal.encode(&mut encoder);
+            }),
+            ~"\"Dog\""
+        );
+        assert_eq!(
+            with_str_writer(|wr| {
+                let mut encoder = PrettyEncoder::new(wr);
+                animal.encode(&mut encoder);
+            }),
+            ~"\"Dog\""
+        );
+
+        let animal = Frog(~"Henry", 349);
+        assert_eq!(
+            with_str_writer(|wr| {
+                let mut encoder = Encoder::new(wr);
+                animal.encode(&mut encoder);
+            }),
+            ~"{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}"
+        );
+        assert_eq!(
+            with_str_writer(|wr| {
+                let mut encoder = PrettyEncoder::new(wr);
+                animal.encode(&mut encoder);
+            }),
+            ~"\
+            [\n  \
+                \"Frog\",\n  \
+                \"Henry\",\n  \
+                349\n\
+            ]"
+        );
+    }
+
+    #[test]
+    fn test_write_some() {
+        let value = Some(~"jodhpurs");
+        let s = with_str_writer(|wr| {
+            let mut encoder = Encoder::new(wr);
+            value.encode(&mut encoder);
+        });
+        assert_eq!(s, ~"\"jodhpurs\"");
+
+        let value = Some(~"jodhpurs");
+        let s = with_str_writer(|wr| {
+            let mut encoder = PrettyEncoder::new(wr);
+            value.encode(&mut encoder);
+        });
+        assert_eq!(s, ~"\"jodhpurs\"");
+    }
+
+    #[test]
+    fn test_write_none() {
+        let value: Option<~str> = None;
+        let s = with_str_writer(|wr| {
+            let mut encoder = Encoder::new(wr);
+            value.encode(&mut encoder);
+        });
+        assert_eq!(s, ~"null");
+
+        let s = with_str_writer(|wr| {
+            let mut encoder = Encoder::new(wr);
+            value.encode(&mut encoder);
+        });
+        assert_eq!(s, ~"null");
+    }
+
+    #[test]
+    fn test_trailing_characters() {
+        assert_eq!(from_str("nulla"),
+            Err(Error {line: 1u, col: 5u, msg: ~"trailing characters"}));
+        assert_eq!(from_str("truea"),
+            Err(Error {line: 1u, col: 5u, msg: ~"trailing characters"}));
+        assert_eq!(from_str("falsea"),
+            Err(Error {line: 1u, col: 6u, msg: ~"trailing characters"}));
+        assert_eq!(from_str("1a"),
+            Err(Error {line: 1u, col: 2u, msg: ~"trailing characters"}));
+        assert_eq!(from_str("[]a"),
+            Err(Error {line: 1u, col: 3u, msg: ~"trailing characters"}));
+        assert_eq!(from_str("{}a"),
+            Err(Error {line: 1u, col: 3u, msg: ~"trailing characters"}));
+    }
+
+    #[test]
+    fn test_read_identifiers() {
+        assert_eq!(from_str("n"),
+            Err(Error {line: 1u, col: 2u, msg: ~"invalid syntax"}));
+        assert_eq!(from_str("nul"),
+            Err(Error {line: 1u, col: 4u, msg: ~"invalid syntax"}));
+
+        assert_eq!(from_str("t"),
+            Err(Error {line: 1u, col: 2u, msg: ~"invalid syntax"}));
+        assert_eq!(from_str("truz"),
+            Err(Error {line: 1u, col: 4u, msg: ~"invalid syntax"}));
+
+        assert_eq!(from_str("f"),
+            Err(Error {line: 1u, col: 2u, msg: ~"invalid syntax"}));
+        assert_eq!(from_str("faz"),
+            Err(Error {line: 1u, col: 3u, msg: ~"invalid syntax"}));
+
+        assert_eq!(from_str("null"), Ok(Null));
+        assert_eq!(from_str("true"), Ok(Boolean(true)));
+        assert_eq!(from_str("false"), Ok(Boolean(false)));
+        assert_eq!(from_str(" null "), Ok(Null));
+        assert_eq!(from_str(" true "), Ok(Boolean(true)));
+        assert_eq!(from_str(" false "), Ok(Boolean(false)));
+    }
+
+    #[test]
+    fn test_decode_identifiers() {
+        let mut decoder = Decoder::new(from_str("null").unwrap());
+        let v: () = Decodable::decode(&mut decoder);
+        assert_eq!(v, ());
+
+        let mut decoder = Decoder::new(from_str("true").unwrap());
+        let v: bool = Decodable::decode(&mut decoder);
+        assert_eq!(v, true);
+
+        let mut decoder = Decoder::new(from_str("false").unwrap());
+        let v: bool = Decodable::decode(&mut decoder);
+        assert_eq!(v, false);
+    }
+
+    #[test]
+    fn test_read_number() {
+        assert_eq!(from_str("+"),
+            Err(Error {line: 1u, col: 1u, msg: ~"invalid syntax"}));
+        assert_eq!(from_str("."),
+            Err(Error {line: 1u, col: 1u, msg: ~"invalid syntax"}));
+
+        assert_eq!(from_str("-"),
+            Err(Error {line: 1u, col: 2u, msg: ~"invalid number"}));
+        assert_eq!(from_str("00"),
+            Err(Error {line: 1u, col: 2u, msg: ~"invalid number"}));
+        assert_eq!(from_str("1."),
+            Err(Error {line: 1u, col: 3u, msg: ~"invalid number"}));
+        assert_eq!(from_str("1e"),
+            Err(Error {line: 1u, col: 3u, msg: ~"invalid number"}));
+        assert_eq!(from_str("1e+"),
+            Err(Error {line: 1u, col: 4u, msg: ~"invalid number"}));
+
+        assert_eq!(from_str("3"), Ok(Number(3.0)));
+        assert_eq!(from_str("3.1"), Ok(Number(3.1)));
+        assert_eq!(from_str("-1.2"), Ok(Number(-1.2)));
+        assert_eq!(from_str("0.4"), Ok(Number(0.4)));
+        assert_eq!(from_str("0.4e5"), Ok(Number(0.4e5)));
+        assert_eq!(from_str("0.4e+15"), Ok(Number(0.4e15)));
+        assert_eq!(from_str("0.4e-01"), Ok(Number(0.4e-01)));
+        assert_eq!(from_str(" 3 "), Ok(Number(3.0)));
+    }
+
+    #[test]
+    fn test_decode_numbers() {
+        let mut decoder = Decoder::new(from_str("3").unwrap());
+        let v: f64 = Decodable::decode(&mut decoder);
+        assert_eq!(v, 3.0);
+
+        let mut decoder = Decoder::new(from_str("3.1").unwrap());
+        let v: f64 = Decodable::decode(&mut decoder);
+        assert_eq!(v, 3.1);
+
+        let mut decoder = Decoder::new(from_str("-1.2").unwrap());
+        let v: f64 = Decodable::decode(&mut decoder);
+        assert_eq!(v, -1.2);
+
+        let mut decoder = Decoder::new(from_str("0.4").unwrap());
+        let v: f64 = Decodable::decode(&mut decoder);
+        assert_eq!(v, 0.4);
+
+        let mut decoder = Decoder::new(from_str("0.4e5").unwrap());
+        let v: f64 = Decodable::decode(&mut decoder);
+        assert_eq!(v, 0.4e5);
+
+        let mut decoder = Decoder::new(from_str("0.4e15").unwrap());
+        let v: f64 = Decodable::decode(&mut decoder);
+        assert_eq!(v, 0.4e15);
+
+        let mut decoder = Decoder::new(from_str("0.4e-01").unwrap());
+        let v: f64 = Decodable::decode(&mut decoder);
+        assert_eq!(v, 0.4e-01);
+    }
+
+    #[test]
+    fn test_read_str() {
+        assert_eq!(from_str("\""),
+            Err(Error {line: 1u, col: 2u, msg: ~"EOF while parsing string"
+        }));
+        assert_eq!(from_str("\"lol"),
+            Err(Error {line: 1u, col: 5u, msg: ~"EOF while parsing string"
+        }));
+
+        assert_eq!(from_str("\"\""), Ok(String(~"")));
+        assert_eq!(from_str("\"foo\""), Ok(String(~"foo")));
+        assert_eq!(from_str("\"\\\"\""), Ok(String(~"\"")));
+        assert_eq!(from_str("\"\\b\""), Ok(String(~"\x08")));
+        assert_eq!(from_str("\"\\n\""), Ok(String(~"\n")));
+        assert_eq!(from_str("\"\\r\""), Ok(String(~"\r")));
+        assert_eq!(from_str("\"\\t\""), Ok(String(~"\t")));
+        assert_eq!(from_str(" \"foo\" "), Ok(String(~"foo")));
+        assert_eq!(from_str("\"\\u12ab\""), Ok(String(~"\u12ab")));
+        assert_eq!(from_str("\"\\uAB12\""), Ok(String(~"\uAB12")));
+    }
+
+    #[test]
+    fn test_decode_str() {
+        let mut decoder = Decoder::new(from_str("\"\"").unwrap());
+        let v: ~str = Decodable::decode(&mut decoder);
+        assert_eq!(v, ~"");
+
+        let mut decoder = Decoder::new(from_str("\"foo\"").unwrap());
+        let v: ~str = Decodable::decode(&mut decoder);
+        assert_eq!(v, ~"foo");
+
+        let mut decoder = Decoder::new(from_str("\"\\\"\"").unwrap());
+        let v: ~str = Decodable::decode(&mut decoder);
+        assert_eq!(v, ~"\"");
+
+        let mut decoder = Decoder::new(from_str("\"\\b\"").unwrap());
+        let v: ~str = Decodable::decode(&mut decoder);
+        assert_eq!(v, ~"\x08");
+
+        let mut decoder = Decoder::new(from_str("\"\\n\"").unwrap());
+        let v: ~str = Decodable::decode(&mut decoder);
+        assert_eq!(v, ~"\n");
+
+        let mut decoder = Decoder::new(from_str("\"\\r\"").unwrap());
+        let v: ~str = Decodable::decode(&mut decoder);
+        assert_eq!(v, ~"\r");
+
+        let mut decoder = Decoder::new(from_str("\"\\t\"").unwrap());
+        let v: ~str = Decodable::decode(&mut decoder);
+        assert_eq!(v, ~"\t");
+
+        let mut decoder = Decoder::new(from_str("\"\\u12ab\"").unwrap());
+        let v: ~str = Decodable::decode(&mut decoder);
+        assert_eq!(v, ~"\u12ab");
+
+        let mut decoder = Decoder::new(from_str("\"\\uAB12\"").unwrap());
+        let v: ~str = Decodable::decode(&mut decoder);
+        assert_eq!(v, ~"\uAB12");
+    }
+
+    #[test]
+    fn test_read_list() {
+        assert_eq!(from_str("["),
+            Err(Error {line: 1u, col: 2u, msg: ~"EOF while parsing value"}));
+        assert_eq!(from_str("[1"),
+            Err(Error {line: 1u, col: 3u, msg: ~"EOF while parsing list"}));
+        assert_eq!(from_str("[1,"),
+            Err(Error {line: 1u, col: 4u, msg: ~"EOF while parsing value"}));
+        assert_eq!(from_str("[1,]"),
+            Err(Error {line: 1u, col: 4u, msg: ~"invalid syntax"}));
+        assert_eq!(from_str("[6 7]"),
+            Err(Error {line: 1u, col: 4u, msg: ~"expected `,` or `]`"}));
+
+        assert_eq!(from_str("[]"), Ok(List(~[])));
+        assert_eq!(from_str("[ ]"), Ok(List(~[])));
+        assert_eq!(from_str("[true]"), Ok(List(~[Boolean(true)])));
+        assert_eq!(from_str("[ false ]"), Ok(List(~[Boolean(false)])));
+        assert_eq!(from_str("[null]"), Ok(List(~[Null])));
+        assert_eq!(from_str("[3, 1]"),
+                     Ok(List(~[Number(3.0), Number(1.0)])));
+        assert_eq!(from_str("\n[3, 2]\n"),
+                     Ok(List(~[Number(3.0), Number(2.0)])));
+        assert_eq!(from_str("[2, [4, 1]]"),
+               Ok(List(~[Number(2.0), List(~[Number(4.0), Number(1.0)])])));
+    }
+
+    #[test]
+    fn test_decode_list() {
+        let mut decoder = Decoder::new(from_str("[]").unwrap());
+        let v: ~[()] = Decodable::decode(&mut decoder);
+        assert_eq!(v, ~[]);
+
+        let mut decoder = Decoder::new(from_str("[null]").unwrap());
+        let v: ~[()] = Decodable::decode(&mut decoder);
+        assert_eq!(v, ~[()]);
+
+        let mut decoder = Decoder::new(from_str("[true]").unwrap());
+        let v: ~[bool] = Decodable::decode(&mut decoder);
+        assert_eq!(v, ~[true]);
+
+        let mut decoder = Decoder::new(from_str("[true]").unwrap());
+        let v: ~[bool] = Decodable::decode(&mut decoder);
+        assert_eq!(v, ~[true]);
+
+        let mut decoder = Decoder::new(from_str("[3, 1]").unwrap());
+        let v: ~[int] = Decodable::decode(&mut decoder);
+        assert_eq!(v, ~[3, 1]);
+
+        let mut decoder = Decoder::new(from_str("[[3], [1, 2]]").unwrap());
+        let v: ~[~[uint]] = Decodable::decode(&mut decoder);
+        assert_eq!(v, ~[~[3], ~[1, 2]]);
+    }
+
+    #[test]
+    fn test_read_object() {
+        assert_eq!(from_str("{"),
+            Err(Error {
+                line: 1u,
+                col: 2u,
+                msg: ~"EOF while parsing object"}));
+        assert_eq!(from_str("{ "),
+            Err(Error {
+                line: 1u,
+                col: 3u,
+                msg: ~"EOF while parsing object"}));
+        assert_eq!(from_str("{1"),
+            Err(Error {
+                line: 1u,
+                col: 2u,
+                msg: ~"key must be a string"}));
+        assert_eq!(from_str("{ \"a\""),
+            Err(Error {
+                line: 1u,
+                col: 6u,
+                msg: ~"EOF while parsing object"}));
+        assert_eq!(from_str("{\"a\""),
+            Err(Error {
+                line: 1u,
+                col: 5u,
+                msg: ~"EOF while parsing object"}));
+        assert_eq!(from_str("{\"a\" "),
+            Err(Error {
+                line: 1u,
+                col: 6u,
+                msg: ~"EOF while parsing object"}));
+
+        assert_eq!(from_str("{\"a\" 1"),
+            Err(Error {line: 1u, col: 6u, msg: ~"expected `:`"}));
+        assert_eq!(from_str("{\"a\":"),
+            Err(Error {line: 1u, col: 6u, msg: ~"EOF while parsing value"}));
+        assert_eq!(from_str("{\"a\":1"),
+            Err(Error {
+                line: 1u,
+                col: 7u,
+                msg: ~"EOF while parsing object"}));
+        assert_eq!(from_str("{\"a\":1 1"),
+            Err(Error {line: 1u, col: 8u, msg: ~"expected `,` or `}`"}));
+        assert_eq!(from_str("{\"a\":1,"),
+            Err(Error {
+                line: 1u,
+                col: 8u,
+                msg: ~"EOF while parsing object"}));
+
+        assert_eq!(from_str("{}").unwrap(), mk_object([]));
+        assert_eq!(from_str("{\"a\": 3}").unwrap(),
+                  mk_object([(~"a", Number(3.0))]));
+
+        assert_eq!(from_str(
+                      "{ \"a\": null, \"b\" : true }").unwrap(),
+                  mk_object([
+                      (~"a", Null),
+                      (~"b", Boolean(true))]));
+        assert_eq!(from_str("\n{ \"a\": null, \"b\" : true }\n").unwrap(),
+                  mk_object([
+                      (~"a", Null),
+                      (~"b", Boolean(true))]));
+        assert_eq!(from_str(
+                      "{\"a\" : 1.0 ,\"b\": [ true ]}").unwrap(),
+                  mk_object([
+                      (~"a", Number(1.0)),
+                      (~"b", List(~[Boolean(true)]))
+                  ]));
+        assert_eq!(from_str(
+                      ~"{" +
+                          "\"a\": 1.0, " +
+                          "\"b\": [" +
+                              "true," +
+                              "\"foo\\nbar\", " +
+                              "{ \"c\": {\"d\": null} } " +
+                          "]" +
+                      "}").unwrap(),
+                  mk_object([
+                      (~"a", Number(1.0)),
+                      (~"b", List(~[
+                          Boolean(true),
+                          String(~"foo\nbar"),
+                          mk_object([
+                              (~"c", mk_object([(~"d", Null)]))
+                          ])
+                      ]))
+                  ]));
+    }
+
+    #[test]
+    fn test_decode_struct() {
+        let s = ~"{
+            \"inner\": [
+                { \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] }
+            ]
+        }";
+        let mut decoder = Decoder::new(from_str(s).unwrap());
+        let v: Outer = Decodable::decode(&mut decoder);
+        assert_eq!(
+            v,
+            Outer {
+                inner: ~[
+                    Inner { a: (), b: 2, c: ~[~"abc", ~"xyz"] }
+                ]
+            }
+        );
+    }
+
+    #[test]
+    fn test_decode_option() {
+        let mut decoder = Decoder::new(from_str("null").unwrap());
+        let value: Option<~str> = Decodable::decode(&mut decoder);
+        assert_eq!(value, None);
+
+        let mut decoder = Decoder::new(from_str("\"jodhpurs\"").unwrap());
+        let value: Option<~str> = Decodable::decode(&mut decoder);
+        assert_eq!(value, Some(~"jodhpurs"));
+    }
+
+    #[test]
+    fn test_decode_enum() {
+        let mut decoder = Decoder::new(from_str("\"Dog\"").unwrap());
+        let value: Animal = Decodable::decode(&mut decoder);
+        assert_eq!(value, Dog);
+
+        let s = "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}";
+        let mut decoder = Decoder::new(from_str(s).unwrap());
+        let value: Animal = Decodable::decode(&mut decoder);
+        assert_eq!(value, Frog(~"Henry", 349));
+    }
+
+    #[test]
+    fn test_decode_map() {
+        let s = ~"{\"a\": \"Dog\", \"b\": {\"variant\":\"Frog\",\"fields\":[\"Henry\", 349]}}";
+        let mut decoder = Decoder::new(from_str(s).unwrap());
+        let mut map: TreeMap<~str, Animal> = Decodable::decode(&mut decoder);
+
+        assert_eq!(map.pop(&~"a"), Some(Dog));
+        assert_eq!(map.pop(&~"b"), Some(Frog(~"Henry", 349)));
+    }
+
+    #[test]
+    fn test_multiline_errors() {
+        assert_eq!(from_str("{\n  \"foo\":\n \"bar\""),
+            Err(Error {
+                line: 3u,
+                col: 8u,
+                msg: ~"EOF while parsing object"}));
+    }
+
+    #[deriving(Decodable)]
+    struct DecodeStruct {
+        x: f64,
+        y: bool,
+        z: ~str,
+        w: ~[DecodeStruct]
+    }
+    #[deriving(Decodable)]
+    enum DecodeEnum {
+        A(f64),
+        B(~str)
+    }
+    fn check_err<T: Decodable<Decoder>>(to_parse: &'static str, expected_error: &str) {
+        use std::any::AnyRefExt;
+        use std::task;
+        let res = task::try(proc() {
+            // either fails in `decode` (which is what we want), or
+            // returns Some(error_message)/None if the string was
+            // invalid or valid JSON.
+            match from_str(to_parse) {
+                Err(e) => Some(e.to_str()),
+                Ok(json) => {
+                    let _: T = Decodable::decode(&mut Decoder::new(json));
+                    None
+                }
+            }
+        });
+        match res {
+            Ok(Some(parse_error)) => fail!("`{}` is not valid json: {}",
+                                           to_parse, parse_error),
+            Ok(None) => fail!("`{}` parsed & decoded ok, expecting error `{}`",
+                              to_parse, expected_error),
+            Err(e) => {
+                let err = e.as_ref::<~str>().unwrap();
+                assert!(err.contains(expected_error),
+                        "`{}` errored incorrectly, found `{}` expecting `{}`",
+                        to_parse, *err, expected_error);
+            }
+        }
+    }
+    #[test]
+    fn test_decode_errors_struct() {
+        check_err::<DecodeStruct>("[]", "object but found list");
+        check_err::<DecodeStruct>("{\"x\": true, \"y\": true, \"z\": \"\", \"w\": []}",
+                                  "number but found boolean");
+        check_err::<DecodeStruct>("{\"x\": 1, \"y\": [], \"z\": \"\", \"w\": []}",
+                                  "boolean but found list");
+        check_err::<DecodeStruct>("{\"x\": 1, \"y\": true, \"z\": {}, \"w\": []}",
+                                  "string but found object");
+        check_err::<DecodeStruct>("{\"x\": 1, \"y\": true, \"z\": \"\", \"w\": null}",
+                                  "list but found null");
+        check_err::<DecodeStruct>("{\"x\": 1, \"y\": true, \"z\": \"\"}",
+                                  "'w' field in object");
+    }
+    #[test]
+    fn test_decode_errors_enum() {
+        check_err::<DecodeEnum>("{}",
+                                "'variant' field in object");
+        check_err::<DecodeEnum>("{\"variant\": 1}",
+                                "string but found number");
+        check_err::<DecodeEnum>("{\"variant\": \"A\"}",
+                                "'fields' field in object");
+        check_err::<DecodeEnum>("{\"variant\": \"A\", \"fields\": null}",
+                                "list but found null");
+        check_err::<DecodeEnum>("{\"variant\": \"C\", \"fields\": []}",
+                                "unknown variant name");
+    }
+
+    #[test]
+    fn test_find(){
+        let json_value = from_str("{\"dog\" : \"cat\"}").unwrap();
+        let found_str = json_value.find(&~"dog");
+        assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == &"cat");
+    }
+
+    #[test]
+    fn test_find_path(){
+        let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap();
+        let found_str = json_value.find_path(&[&~"dog", &~"cat", &~"mouse"]);
+        assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == &"cheese");
+    }
+
+    #[test]
+    fn test_search(){
+        let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap();
+        let found_str = json_value.search(&~"mouse").and_then(|j| j.as_string());
+        assert!(found_str.is_some());
+        assert!(found_str.unwrap() == &"cheese");
+    }
+
+    #[test]
+    fn test_is_object(){
+        let json_value = from_str("{}").unwrap();
+        assert!(json_value.is_object());
+    }
+
+    #[test]
+    fn test_as_object(){
+        let json_value = from_str("{}").unwrap();
+        let json_object = json_value.as_object();
+        assert!(json_object.is_some());
+    }
+
+    #[test]
+    fn test_is_list(){
+        let json_value = from_str("[1, 2, 3]").unwrap();
+        assert!(json_value.is_list());
+    }
+
+    #[test]
+    fn test_as_list(){
+        let json_value = from_str("[1, 2, 3]").unwrap();
+        let json_list = json_value.as_list();
+        let expected_length = 3;
+        assert!(json_list.is_some() && json_list.unwrap().len() == expected_length);
+    }
+
+    #[test]
+    fn test_is_string(){
+        let json_value = from_str("\"dog\"").unwrap();
+        assert!(json_value.is_string());
+    }
+
+    #[test]
+    fn test_as_string(){
+        let json_value = from_str("\"dog\"").unwrap();
+        let json_str = json_value.as_string();
+        let expected_str = &"dog";
+        assert_eq!(json_str, Some(expected_str));
+    }
+
+    #[test]
+    fn test_is_number(){
+        let json_value = from_str("12").unwrap();
+        assert!(json_value.is_number());
+    }
+
+    #[test]
+    fn test_as_number(){
+        let json_value = from_str("12").unwrap();
+        let json_num = json_value.as_number();
+        let expected_num = 12f64;
+        assert!(json_num.is_some() && json_num.unwrap() == expected_num);
+    }
+
+    #[test]
+    fn test_is_boolean(){
+        let json_value = from_str("false").unwrap();
+        assert!(json_value.is_boolean());
+    }
+
+    #[test]
+    fn test_as_boolean(){
+        let json_value = from_str("false").unwrap();
+        let json_bool = json_value.as_boolean();
+        let expected_bool = false;
+        assert!(json_bool.is_some() && json_bool.unwrap() == expected_bool);
+    }
+
+    #[test]
+    fn test_is_null(){
+        let json_value = from_str("null").unwrap();
+        assert!(json_value.is_null());
+    }
+
+    #[test]
+    fn test_as_null(){
+        let json_value = from_str("null").unwrap();
+        let json_null = json_value.as_null();
+        let expected_null = ();
+        assert!(json_null.is_some() && json_null.unwrap() == expected_null);
+    }
+
+    #[test]
+    fn test_encode_hashmap_with_numeric_key() {
+        use std::str::from_utf8;
+        use std::io::Writer;
+        use std::io::MemWriter;
+        use collections::HashMap;
+        let mut hm: HashMap<uint, bool> = HashMap::new();
+        hm.insert(1, true);
+        let mut mem_buf = MemWriter::new();
+        {
+            let mut encoder = Encoder::new(&mut mem_buf as &mut io::Writer);
+            hm.encode(&mut encoder)
+        }
+        let bytes = mem_buf.unwrap();
+        let json_str = from_utf8(bytes).unwrap();
+        match from_str(json_str) {
+            Err(_) => fail!("Unable to parse json_str: {:?}", json_str),
+            _ => {} // it parsed and we are good to go
+        }
+    }
+    #[test]
+    fn test_prettyencode_hashmap_with_numeric_key() {
+        use std::str::from_utf8;
+        use std::io::Writer;
+        use std::io::MemWriter;
+        use collections::HashMap;
+        let mut hm: HashMap<uint, bool> = HashMap::new();
+        hm.insert(1, true);
+        let mut mem_buf = MemWriter::new();
+        {
+            let mut encoder = PrettyEncoder::new(&mut mem_buf as &mut io::Writer);
+            hm.encode(&mut encoder)
+        }
+        let bytes = mem_buf.unwrap();
+        let json_str = from_utf8(bytes).unwrap();
+        match from_str(json_str) {
+            Err(_) => fail!("Unable to parse json_str: {:?}", json_str),
+            _ => {} // it parsed and we are good to go
+        }
+    }
+    #[test]
+    fn test_hashmap_with_numeric_key_can_handle_double_quote_delimited_key() {
+        use collections::HashMap;
+        use Decodable;
+        let json_str = "{\"1\":true}";
+        let json_obj = match from_str(json_str) {
+            Err(_) => fail!("Unable to parse json_str: {:?}", json_str),
+            Ok(o) => o
+        };
+        let mut decoder = Decoder::new(json_obj);
+        let _hm: HashMap<uint, bool> = Decodable::decode(&mut decoder);
+    }
+}
+
index 8a5829da9d6ffad120e3574829335bb54052abbf..86e03aae6733ce565415c5d395e75c461f082ef9 100644 (file)
 pub use self::serialize::{Decoder, Encoder, Decodable, Encodable,
                           DecoderHelpers, EncoderHelpers};
 
+// FIXME: remove _old.rs files after snapshot
+#[cfg(not(stage0))]
 mod serialize;
+#[cfg(not(stage0))]
 mod collection_impls;
 
 pub mod base64;
+#[cfg(not(stage0))]
 pub mod ebml;
 pub mod hex;
+#[cfg(not(stage0))]
+pub mod json;
+
+#[cfg(stage0)]
+#[path="./serialize_old.rs"]
+pub mod serialize;
+
+#[cfg(stage0)]
+#[path="./collection_impls_old.rs"]
+mod collection_impls;
+
+#[cfg(stage0)]
+#[path="./ebml_old.rs"]
+pub mod ebml;
+
+#[cfg(stage0)]
+#[path="./json_old.rs"]
 pub mod json;
index a65443653cc4871d0da70ee9e89db910c8d79135..6cda8d9ffb5801f8d6fed88a3606bf03f43914fb 100644 (file)
 use std::rc::Rc;
 use std::slice;
 
-pub trait Encoder {
+pub trait Encoder<E> {
     // Primitive types:
-    fn emit_nil(&mut self);
-    fn emit_uint(&mut self, v: uint);
-    fn emit_u64(&mut self, v: u64);
-    fn emit_u32(&mut self, v: u32);
-    fn emit_u16(&mut self, v: u16);
-    fn emit_u8(&mut self, v: u8);
-    fn emit_int(&mut self, v: int);
-    fn emit_i64(&mut self, v: i64);
-    fn emit_i32(&mut self, v: i32);
-    fn emit_i16(&mut self, v: i16);
-    fn emit_i8(&mut self, v: i8);
-    fn emit_bool(&mut self, v: bool);
-    fn emit_f64(&mut self, v: f64);
-    fn emit_f32(&mut self, v: f32);
-    fn emit_char(&mut self, v: char);
-    fn emit_str(&mut self, v: &str);
+    fn emit_nil(&mut self) -> Result<(), E>;
+    fn emit_uint(&mut self, v: uint) -> Result<(), E>;
+    fn emit_u64(&mut self, v: u64) -> Result<(), E>;
+    fn emit_u32(&mut self, v: u32) -> Result<(), E>;
+    fn emit_u16(&mut self, v: u16) -> Result<(), E>;
+    fn emit_u8(&mut self, v: u8) -> Result<(), E>;
+    fn emit_int(&mut self, v: int) -> Result<(), E>;
+    fn emit_i64(&mut self, v: i64) -> Result<(), E>;
+    fn emit_i32(&mut self, v: i32) -> Result<(), E>;
+    fn emit_i16(&mut self, v: i16) -> Result<(), E>;
+    fn emit_i8(&mut self, v: i8) -> Result<(), E>;
+    fn emit_bool(&mut self, v: bool) -> Result<(), E>;
+    fn emit_f64(&mut self, v: f64) -> Result<(), E>;
+    fn emit_f32(&mut self, v: f32) -> Result<(), E>;
+    fn emit_char(&mut self, v: char) -> Result<(), E>;
+    fn emit_str(&mut self, v: &str) -> Result<(), E>;
 
     // Compound types:
-    fn emit_enum(&mut self, name: &str, f: |&mut Self|);
+    fn emit_enum(&mut self, name: &str, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
 
     fn emit_enum_variant(&mut self,
                          v_name: &str,
                          v_id: uint,
                          len: uint,
-                         f: |&mut Self|);
-    fn emit_enum_variant_arg(&mut self, a_idx: uint, f: |&mut Self|);
+                         f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
+    fn emit_enum_variant_arg(&mut self,
+                             a_idx: uint,
+                             f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
 
     fn emit_enum_struct_variant(&mut self,
                                 v_name: &str,
                                 v_id: uint,
                                 len: uint,
-                                f: |&mut Self|);
+                                f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
     fn emit_enum_struct_variant_field(&mut self,
                                       f_name: &str,
                                       f_idx: uint,
-                                      f: |&mut Self|);
+                                      f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
 
-    fn emit_struct(&mut self, name: &str, len: uint, f: |&mut Self|);
+    fn emit_struct(&mut self,
+                   name: &str,
+                   len: uint,
+                   f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
     fn emit_struct_field(&mut self,
                          f_name: &str,
                          f_idx: uint,
-                         f: |&mut Self|);
+                         f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
 
-    fn emit_tuple(&mut self, len: uint, f: |&mut Self|);
-    fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Self|);
+    fn emit_tuple(&mut self, len: uint, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
+    fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
 
-    fn emit_tuple_struct(&mut self, name: &str, len: uint, f: |&mut Self|);
-    fn emit_tuple_struct_arg(&mut self, f_idx: uint, f: |&mut Self|);
+    fn emit_tuple_struct(&mut self,
+                         name: &str,
+                         len: uint,
+                         f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
+    fn emit_tuple_struct_arg(&mut self,
+                             f_idx: uint,
+                             f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
 
     // Specialized types:
-    fn emit_option(&mut self, f: |&mut Self|);
-    fn emit_option_none(&mut self);
-    fn emit_option_some(&mut self, f: |&mut Self|);
+    fn emit_option(&mut self, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
+    fn emit_option_none(&mut self) -> Result<(), E>;
+    fn emit_option_some(&mut self, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
 
-    fn emit_seq(&mut self, len: uint, f: |this: &mut Self|);
-    fn emit_seq_elt(&mut self, idx: uint, f: |this: &mut Self|);
+    fn emit_seq(&mut self, len: uint, f: |this: &mut Self| -> Result<(), E>) -> Result<(), E>;
+    fn emit_seq_elt(&mut self, idx: uint, f: |this: &mut Self| -> Result<(), E>) -> Result<(), E>;
 
-    fn emit_map(&mut self, len: uint, f: |&mut Self|);
-    fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Self|);
-    fn emit_map_elt_val(&mut self, idx: uint, f: |&mut Self|);
+    fn emit_map(&mut self, len: uint, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
+    fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
+    fn emit_map_elt_val(&mut self, idx: uint, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
 }
 
-pub trait Decoder {
+pub trait Decoder<E> {
     // Primitive types:
-    fn read_nil(&mut self) -> ();
-    fn read_uint(&mut self) -> uint;
-    fn read_u64(&mut self) -> u64;
-    fn read_u32(&mut self) -> u32;
-    fn read_u16(&mut self) -> u16;
-    fn read_u8(&mut self) -> u8;
-    fn read_int(&mut self) -> int;
-    fn read_i64(&mut self) -> i64;
-    fn read_i32(&mut self) -> i32;
-    fn read_i16(&mut self) -> i16;
-    fn read_i8(&mut self) -> i8;
-    fn read_bool(&mut self) -> bool;
-    fn read_f64(&mut self) -> f64;
-    fn read_f32(&mut self) -> f32;
-    fn read_char(&mut self) -> char;
-    fn read_str(&mut self) -> ~str;
+    fn read_nil(&mut self) -> Result<(), E>;
+    fn read_uint(&mut self) -> Result<uint, E>;
+    fn read_u64(&mut self) -> Result<u64, E>;
+    fn read_u32(&mut self) -> Result<u32, E>;
+    fn read_u16(&mut self) -> Result<u16, E>;
+    fn read_u8(&mut self) -> Result<u8, E>;
+    fn read_int(&mut self) -> Result<int, E>;
+    fn read_i64(&mut self) -> Result<i64, E>;
+    fn read_i32(&mut self) -> Result<i32, E>;
+    fn read_i16(&mut self) -> Result<i16, E>;
+    fn read_i8(&mut self) -> Result<i8, E>;
+    fn read_bool(&mut self) -> Result<bool, E>;
+    fn read_f64(&mut self) -> Result<f64, E>;
+    fn read_f32(&mut self) -> Result<f32, E>;
+    fn read_char(&mut self) -> Result<char, E>;
+    fn read_str(&mut self) -> Result<~str, E>;
 
     // Compound types:
-    fn read_enum<T>(&mut self, name: &str, f: |&mut Self| -> T) -> T;
+    fn read_enum<T>(&mut self, name: &str, f: |&mut Self| -> Result<T, E>) -> Result<T, E>;
 
     fn read_enum_variant<T>(&mut self,
                             names: &[&str],
-                            f: |&mut Self, uint| -> T)
-                            -> T;
+                            f: |&mut Self, uint| -> Result<T, E>)
+                            -> Result<T, E>;
     fn read_enum_variant_arg<T>(&mut self,
                                 a_idx: uint,
-                                f: |&mut Self| -> T)
-                                -> T;
+                                f: |&mut Self| -> Result<T, E>)
+                                -> Result<T, E>;
 
     fn read_enum_struct_variant<T>(&mut self,
                                    names: &[&str],
-                                   f: |&mut Self, uint| -> T)
-                                   -> T;
+                                   f: |&mut Self, uint| -> Result<T, E>)
+                                   -> Result<T, E>;
     fn read_enum_struct_variant_field<T>(&mut self,
                                          &f_name: &str,
                                          f_idx: uint,
-                                         f: |&mut Self| -> T)
-                                         -> T;
+                                         f: |&mut Self| -> Result<T, E>)
+                                         -> Result<T, E>;
 
-    fn read_struct<T>(&mut self, s_name: &str, len: uint, f: |&mut Self| -> T)
-                      -> T;
+    fn read_struct<T>(&mut self, s_name: &str, len: uint, f: |&mut Self| -> Result<T, E>)
+                      -> Result<T, E>;
     fn read_struct_field<T>(&mut self,
                             f_name: &str,
                             f_idx: uint,
-                            f: |&mut Self| -> T)
-                            -> T;
+                            f: |&mut Self| -> Result<T, E>)
+                            -> Result<T, E>;
 
-    fn read_tuple<T>(&mut self, f: |&mut Self, uint| -> T) -> T;
-    fn read_tuple_arg<T>(&mut self, a_idx: uint, f: |&mut Self| -> T) -> T;
+    fn read_tuple<T>(&mut self, f: |&mut Self, uint| -> Result<T, E>) -> Result<T, E>;
+    fn read_tuple_arg<T>(&mut self, a_idx: uint, f: |&mut Self| -> Result<T, E>) -> Result<T, E>;
 
     fn read_tuple_struct<T>(&mut self,
                             s_name: &str,
-                            f: |&mut Self, uint| -> T)
-                            -> T;
+                            f: |&mut Self, uint| -> Result<T, E>)
+                            -> Result<T, E>;
     fn read_tuple_struct_arg<T>(&mut self,
                                 a_idx: uint,
-                                f: |&mut Self| -> T)
-                                -> T;
+                                f: |&mut Self| -> Result<T, E>)
+                                -> Result<T, E>;
 
     // Specialized types:
-    fn read_option<T>(&mut self, f: |&mut Self, bool| -> T) -> T;
+    fn read_option<T>(&mut self, f: |&mut Self, bool| -> Result<T, E>) -> Result<T, E>;
 
-    fn read_seq<T>(&mut self, f: |&mut Self, uint| -> T) -> T;
-    fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Self| -> T) -> T;
+    fn read_seq<T>(&mut self, f: |&mut Self, uint| -> Result<T, E>) -> Result<T, E>;
+    fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Self| -> Result<T, E>) -> Result<T, E>;
 
-    fn read_map<T>(&mut self, f: |&mut Self, uint| -> T) -> T;
-    fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Self| -> T) -> T;
-    fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Self| -> T) -> T;
+    fn read_map<T>(&mut self, f: |&mut Self, uint| -> Result<T, E>) -> Result<T, E>;
+    fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Self| -> Result<T, E>) -> Result<T, E>;
+    fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Self| -> Result<T, E>) -> Result<T, E>;
 }
 
-pub trait Encodable<S:Encoder> {
-    fn encode(&self, s: &mut S);
+pub trait Encodable<S:Encoder<E>, E> {
+    fn encode(&self, s: &mut S) -> Result<(), E>;
 }
 
-pub trait Decodable<D:Decoder> {
-    fn decode(d: &mut D) -> Self;
+pub trait Decodable<D:Decoder<E>, E> {
+    fn decode(d: &mut D) -> Result<Self, E>;
 }
 
-impl<S:Encoder> Encodable<S> for uint {
-    fn encode(&self, s: &mut S) {
+macro_rules! try ( ($e:expr) => (
+    match $e { Ok(v) => v, Err(e) => return Err(e) }
+))
+
+impl<E, S:Encoder<E>> Encodable<S, E> for uint {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_uint(*self)
     }
 }
 
-impl<D:Decoder> Decodable<D> for uint {
-    fn decode(d: &mut D) -> uint {
+impl<E, D:Decoder<E>> Decodable<D, E> for uint {
+    fn decode(d: &mut D) -> Result<uint, E> {
         d.read_uint()
     }
 }
 
-impl<S:Encoder> Encodable<S> for u8 {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for u8 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_u8(*self)
     }
 }
 
-impl<D:Decoder> Decodable<D> for u8 {
-    fn decode(d: &mut D) -> u8 {
+impl<E, D:Decoder<E>> Decodable<D, E> for u8 {
+    fn decode(d: &mut D) -> Result<u8, E> {
         d.read_u8()
     }
 }
 
-impl<S:Encoder> Encodable<S> for u16 {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for u16 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_u16(*self)
     }
 }
 
-impl<D:Decoder> Decodable<D> for u16 {
-    fn decode(d: &mut D) -> u16 {
+impl<E, D:Decoder<E>> Decodable<D, E> for u16 {
+    fn decode(d: &mut D) -> Result<u16, E> {
         d.read_u16()
     }
 }
 
-impl<S:Encoder> Encodable<S> for u32 {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for u32 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_u32(*self)
     }
 }
 
-impl<D:Decoder> Decodable<D> for u32 {
-    fn decode(d: &mut D) -> u32 {
+impl<E, D:Decoder<E>> Decodable<D, E> for u32 {
+    fn decode(d: &mut D) -> Result<u32, E> {
         d.read_u32()
     }
 }
 
-impl<S:Encoder> Encodable<S> for u64 {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for u64 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_u64(*self)
     }
 }
 
-impl<D:Decoder> Decodable<D> for u64 {
-    fn decode(d: &mut D) -> u64 {
+impl<E, D:Decoder<E>> Decodable<D, E> for u64 {
+    fn decode(d: &mut D) -> Result<u64, E> {
         d.read_u64()
     }
 }
 
-impl<S:Encoder> Encodable<S> for int {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for int {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_int(*self)
     }
 }
 
-impl<D:Decoder> Decodable<D> for int {
-    fn decode(d: &mut D) -> int {
+impl<E, D:Decoder<E>> Decodable<D, E> for int {
+    fn decode(d: &mut D) -> Result<int, E> {
         d.read_int()
     }
 }
 
-impl<S:Encoder> Encodable<S> for i8 {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for i8 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_i8(*self)
     }
 }
 
-impl<D:Decoder> Decodable<D> for i8 {
-    fn decode(d: &mut D) -> i8 {
+impl<E, D:Decoder<E>> Decodable<D, E> for i8 {
+    fn decode(d: &mut D) -> Result<i8, E> {
         d.read_i8()
     }
 }
 
-impl<S:Encoder> Encodable<S> for i16 {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for i16 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_i16(*self)
     }
 }
 
-impl<D:Decoder> Decodable<D> for i16 {
-    fn decode(d: &mut D) -> i16 {
+impl<E, D:Decoder<E>> Decodable<D, E> for i16 {
+    fn decode(d: &mut D) -> Result<i16, E> {
         d.read_i16()
     }
 }
 
-impl<S:Encoder> Encodable<S> for i32 {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for i32 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_i32(*self)
     }
 }
 
-impl<D:Decoder> Decodable<D> for i32 {
-    fn decode(d: &mut D) -> i32 {
+impl<E, D:Decoder<E>> Decodable<D, E> for i32 {
+    fn decode(d: &mut D) -> Result<i32, E> {
         d.read_i32()
     }
 }
 
-impl<S:Encoder> Encodable<S> for i64 {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for i64 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_i64(*self)
     }
 }
 
-impl<D:Decoder> Decodable<D> for i64 {
-    fn decode(d: &mut D) -> i64 {
+impl<E, D:Decoder<E>> Decodable<D, E> for i64 {
+    fn decode(d: &mut D) -> Result<i64, E> {
         d.read_i64()
     }
 }
 
-impl<'a, S:Encoder> Encodable<S> for &'a str {
-    fn encode(&self, s: &mut S) {
+impl<'a, E, S:Encoder<E>> Encodable<S, E> for &'a str {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_str(*self)
     }
 }
 
-impl<S:Encoder> Encodable<S> for ~str {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for ~str {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_str(*self)
     }
 }
 
-impl<D:Decoder> Decodable<D> for ~str {
-    fn decode(d: &mut D) -> ~str {
+impl<E, D:Decoder<E>> Decodable<D, E> for ~str {
+    fn decode(d: &mut D) -> Result<~str, E> {
         d.read_str()
     }
 }
 
-impl<S:Encoder> Encodable<S> for f32 {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for f32 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_f32(*self)
     }
 }
 
-impl<D:Decoder> Decodable<D> for f32 {
-    fn decode(d: &mut D) -> f32 {
+impl<E, D:Decoder<E>> Decodable<D, E> for f32 {
+    fn decode(d: &mut D) -> Result<f32, E> {
         d.read_f32()
     }
 }
 
-impl<S:Encoder> Encodable<S> for f64 {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for f64 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_f64(*self)
     }
 }
 
-impl<D:Decoder> Decodable<D> for f64 {
-    fn decode(d: &mut D) -> f64 {
+impl<E, D:Decoder<E>> Decodable<D, E> for f64 {
+    fn decode(d: &mut D) -> Result<f64, E> {
         d.read_f64()
     }
 }
 
-impl<S:Encoder> Encodable<S> for bool {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for bool {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_bool(*self)
     }
 }
 
-impl<D:Decoder> Decodable<D> for bool {
-    fn decode(d: &mut D) -> bool {
+impl<E, D:Decoder<E>> Decodable<D, E> for bool {
+    fn decode(d: &mut D) -> Result<bool, E> {
         d.read_bool()
     }
 }
 
-impl<S:Encoder> Encodable<S> for char {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for char {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_char(*self)
     }
 }
 
-impl<D:Decoder> Decodable<D> for char {
-    fn decode(d: &mut D) -> char {
+impl<E, D:Decoder<E>> Decodable<D, E> for char {
+    fn decode(d: &mut D) -> Result<char, E> {
         d.read_char()
     }
 }
 
-impl<S:Encoder> Encodable<S> for () {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for () {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_nil()
     }
 }
 
-impl<D:Decoder> Decodable<D> for () {
-    fn decode(d: &mut D) -> () {
+impl<E, D:Decoder<E>> Decodable<D, E> for () {
+    fn decode(d: &mut D) -> Result<(), E> {
         d.read_nil()
     }
 }
 
-impl<'a, S:Encoder,T:Encodable<S>> Encodable<S> for &'a T {
-    fn encode(&self, s: &mut S) {
+impl<'a, E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for &'a T {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         (**self).encode(s)
     }
 }
 
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for ~T {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for ~T {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         (**self).encode(s)
     }
 }
 
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for ~T {
-    fn decode(d: &mut D) -> ~T {
-        ~Decodable::decode(d)
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for ~T {
+    fn decode(d: &mut D) -> Result<~T, E> {
+        Ok(~try!(Decodable::decode(d)))
     }
 }
 
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for @T {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for @T {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         (**self).encode(s)
     }
 }
 
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for Rc<T> {
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Rc<T> {
     #[inline]
-    fn encode(&self, s: &mut S) {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         (**self).encode(s)
     }
 }
 
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for Rc<T> {
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Rc<T> {
     #[inline]
-    fn decode(d: &mut D) -> Rc<T> {
-        Rc::new(Decodable::decode(d))
+    fn decode(d: &mut D) -> Result<Rc<T>, E> {
+        Ok(Rc::new(try!(Decodable::decode(d))))
     }
 }
 
-impl<D:Decoder,T:Decodable<D> + 'static> Decodable<D> for @T {
-    fn decode(d: &mut D) -> @T {
-        @Decodable::decode(d)
+impl<E, D:Decoder<E>,T:Decodable<D, E> + 'static> Decodable<D, E> for @T {
+    fn decode(d: &mut D) -> Result<@T, E> {
+        Ok(@try!(Decodable::decode(d)))
     }
 }
 
-impl<'a, S:Encoder,T:Encodable<S>> Encodable<S> for &'a [T] {
-    fn encode(&self, s: &mut S) {
+impl<'a, E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for &'a [T] {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
-                s.emit_seq_elt(i, |s| e.encode(s))
+                try!(s.emit_seq_elt(i, |s| e.encode(s)))
             }
+            Ok(())
         })
     }
 }
 
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for ~[T] {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for ~[T] {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
-                s.emit_seq_elt(i, |s| e.encode(s))
+                try!(s.emit_seq_elt(i, |s| e.encode(s)))
             }
+            Ok(())
         })
     }
 }
 
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for ~[T] {
-    fn decode(d: &mut D) -> ~[T] {
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for ~[T] {
+    fn decode(d: &mut D) -> Result<~[T], E> {
         d.read_seq(|d, len| {
-            slice::from_fn(len, |i| {
-                d.read_seq_elt(i, |d| Decodable::decode(d))
-            })
+            let mut v: ~[T] = slice::with_capacity(len);
+            for i in range(0, len) {
+                v.push(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
+            }
+            Ok(v)
         })
     }
 }
 
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for Vec<T> {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Vec<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
-                s.emit_seq_elt(i, |s| e.encode(s))
+                try!(s.emit_seq_elt(i, |s| e.encode(s)))
             }
+            Ok(())
         })
     }
 }
 
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for Vec<T> {
-    fn decode(d: &mut D) -> Vec<T> {
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Vec<T> {
+    fn decode(d: &mut D) -> Result<Vec<T>, E> {
         d.read_seq(|d, len| {
-            Vec::from_fn(len, |i| {
-                d.read_seq_elt(i, |d| Decodable::decode(d))
-            })
+            let mut v = Vec::with_capacity(len);
+            for i in range(0, len) {
+                v.push(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
+            }
+            Ok(v)
         })
     }
 }
 
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for Option<T> {
-    fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Option<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_option(|s| {
             match *self {
                 None => s.emit_option_none(),
@@ -465,13 +486,13 @@ fn encode(&self, s: &mut S) {
     }
 }
 
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for Option<T> {
-    fn decode(d: &mut D) -> Option<T> {
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Option<T> {
+    fn decode(d: &mut D) -> Result<Option<T>, E> {
         d.read_option(|d, b| {
             if b {
-                Some(Decodable::decode(d))
+                Ok(Some(try!(Decodable::decode(d))))
             } else {
-                None
+                Ok(None)
             }
         })
     }
@@ -482,30 +503,31 @@ macro_rules! peel(($name:ident, $($other:ident,)*) => (tuple!($($other,)*)))
 macro_rules! tuple (
     () => ();
     ( $($name:ident,)+ ) => (
-        impl<D:Decoder,$($name:Decodable<D>),*> Decodable<D> for ($($name,)*) {
+        impl<E, D:Decoder<E>,$($name:Decodable<D, E>),*> Decodable<D,E> for ($($name,)*) {
             #[allow(uppercase_variables)]
-            fn decode(d: &mut D) -> ($($name,)*) {
+            fn decode(d: &mut D) -> Result<($($name,)*), E> {
                 d.read_tuple(|d, amt| {
                     let mut i = 0;
-                    let ret = ($(d.read_tuple_arg({ i+=1; i-1 }, |d| -> $name {
+                    let ret = ($(try!(d.read_tuple_arg({ i+=1; i-1 }, |d| -> Result<$name,E> {
                         Decodable::decode(d)
-                    }),)*);
+                    })),)*);
                     assert!(amt == i,
                             "expected tuple of length `{}`, found tuple \
                              of length `{}`", i, amt);
-                    return ret;
+                    return Ok(ret);
                 })
             }
         }
-        impl<S:Encoder,$($name:Encodable<S>),*> Encodable<S> for ($($name,)*) {
+        impl<E, S:Encoder<E>,$($name:Encodable<S, E>),*> Encodable<S, E> for ($($name,)*) {
             #[allow(uppercase_variables)]
-            fn encode(&self, s: &mut S) {
+            fn encode(&self, s: &mut S) -> Result<(), E> {
                 let ($(ref $name,)*) = *self;
                 let mut n = 0;
                 $(let $name = $name; n += 1;)*
                 s.emit_tuple(n, |s| {
                     let mut i = 0;
-                    $(s.emit_seq_elt({ i+=1; i-1 }, |s| $name.encode(s));)*
+                    $(try!(s.emit_seq_elt({ i+=1; i-1 }, |s| $name.encode(s)));)*
+                    Ok(())
                 })
             }
         }
@@ -515,29 +537,29 @@ fn encode(&self, s: &mut S) {
 
 tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
 
-impl<E: Encoder> Encodable<E> for path::posix::Path {
-    fn encode(&self, e: &mut E) {
+impl<E, S: Encoder<E>> Encodable<S, E> for path::posix::Path {
+    fn encode(&self, e: &mut S) -> Result<(), E> {
         self.as_vec().encode(e)
     }
 }
 
-impl<D: Decoder> Decodable<D> for path::posix::Path {
-    fn decode(d: &mut D) -> path::posix::Path {
-        let bytes: ~[u8] = Decodable::decode(d);
-        path::posix::Path::new(bytes)
+impl<E, D: Decoder<E>> Decodable<D, E> for path::posix::Path {
+    fn decode(d: &mut D) -> Result<path::posix::Path, E> {
+        let bytes: ~[u8] = try!(Decodable::decode(d));
+        Ok(path::posix::Path::new(bytes))
     }
 }
 
-impl<E: Encoder> Encodable<E> for path::windows::Path {
-    fn encode(&self, e: &mut E) {
+impl<E, S: Encoder<E>> Encodable<S, E> for path::windows::Path {
+    fn encode(&self, e: &mut S) -> Result<(), E> {
         self.as_vec().encode(e)
     }
 }
 
-impl<D: Decoder> Decodable<D> for path::windows::Path {
-    fn decode(d: &mut D) -> path::windows::Path {
-        let bytes: ~[u8] = Decodable::decode(d);
-        path::windows::Path::new(bytes)
+impl<E, D: Decoder<E>> Decodable<D, E> for path::windows::Path {
+    fn decode(d: &mut D) -> Result<path::windows::Path, E> {
+        let bytes: ~[u8] = try!(Decodable::decode(d));
+        Ok(path::windows::Path::new(bytes))
     }
 }
 
@@ -546,32 +568,37 @@ fn decode(d: &mut D) -> path::windows::Path {
 //
 // In some cases, these should eventually be coded as traits.
 
-pub trait EncoderHelpers {
-    fn emit_from_vec<T>(&mut self, v: &[T], f: |&mut Self, v: &T|);
+pub trait EncoderHelpers<E> {
+    fn emit_from_vec<T>(&mut self,
+                        v: &[T],
+                        f: |&mut Self, v: &T| -> Result<(), E>) -> Result<(), E>;
 }
 
-impl<S:Encoder> EncoderHelpers for S {
-    fn emit_from_vec<T>(&mut self, v: &[T], f: |&mut S, &T|) {
+impl<E, S:Encoder<E>> EncoderHelpers<E> for S {
+    fn emit_from_vec<T>(&mut self, v: &[T], f: |&mut S, &T| -> Result<(), E>) -> Result<(), E> {
         self.emit_seq(v.len(), |this| {
             for (i, e) in v.iter().enumerate() {
-                this.emit_seq_elt(i, |this| {
+                try!(this.emit_seq_elt(i, |this| {
                     f(this, e)
-                })
+                }));
             }
+            Ok(())
         })
     }
 }
 
-pub trait DecoderHelpers {
-    fn read_to_vec<T>(&mut self, f: |&mut Self| -> T) -> ~[T];
+pub trait DecoderHelpers<E> {
+    fn read_to_vec<T>(&mut self, f: |&mut Self| -> Result<T, E>) -> Result<~[T], E>;
 }
 
-impl<D:Decoder> DecoderHelpers for D {
-    fn read_to_vec<T>(&mut self, f: |&mut D| -> T) -> ~[T] {
+impl<E, D:Decoder<E>> DecoderHelpers<E> for D {
+    fn read_to_vec<T>(&mut self, f: |&mut D| -> Result<T, E>) -> Result<~[T], E> {
         self.read_seq(|this, len| {
-            slice::from_fn(len, |i| {
-                this.read_seq_elt(i, |this| f(this))
-            })
+            let mut v = slice::with_capacity(len);
+            for i in range(0, len) {
+                v.push(try!(this.read_seq_elt(i, |this| f(this))));
+            }
+            Ok(v)
         })
     }
 }
diff --git a/src/libserialize/serialize_old.rs b/src/libserialize/serialize_old.rs
new file mode 100644 (file)
index 0000000..4043cbe
--- /dev/null
@@ -0,0 +1,688 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Support code for encoding and decoding types.
+
+/*
+Core encoding and decoding interfaces.
+*/
+
+use std::path;
+use std::rc::Rc;
+use std::slice;
+
+pub trait Encoder {
+    // Primitive types:
+    fn emit_nil(&mut self);
+    fn emit_uint(&mut self, v: uint);
+    fn emit_u64(&mut self, v: u64);
+    fn emit_u32(&mut self, v: u32);
+    fn emit_u16(&mut self, v: u16);
+    fn emit_u8(&mut self, v: u8);
+    fn emit_int(&mut self, v: int);
+    fn emit_i64(&mut self, v: i64);
+    fn emit_i32(&mut self, v: i32);
+    fn emit_i16(&mut self, v: i16);
+    fn emit_i8(&mut self, v: i8);
+    fn emit_bool(&mut self, v: bool);
+    fn emit_f64(&mut self, v: f64);
+    fn emit_f32(&mut self, v: f32);
+    fn emit_char(&mut self, v: char);
+    fn emit_str(&mut self, v: &str);
+
+    // Compound types:
+    fn emit_enum(&mut self, name: &str, f: |&mut Self|);
+
+    fn emit_enum_variant(&mut self,
+                         v_name: &str,
+                         v_id: uint,
+                         len: uint,
+                         f: |&mut Self|);
+    fn emit_enum_variant_arg(&mut self, a_idx: uint, f: |&mut Self|);
+
+    fn emit_enum_struct_variant(&mut self,
+                                v_name: &str,
+                                v_id: uint,
+                                len: uint,
+                                f: |&mut Self|);
+    fn emit_enum_struct_variant_field(&mut self,
+                                      f_name: &str,
+                                      f_idx: uint,
+                                      f: |&mut Self|);
+
+    fn emit_struct(&mut self, name: &str, len: uint, f: |&mut Self|);
+    fn emit_struct_field(&mut self,
+                         f_name: &str,
+                         f_idx: uint,
+                         f: |&mut Self|);
+
+    fn emit_tuple(&mut self, len: uint, f: |&mut Self|);
+    fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Self|);
+
+    fn emit_tuple_struct(&mut self, name: &str, len: uint, f: |&mut Self|);
+    fn emit_tuple_struct_arg(&mut self, f_idx: uint, f: |&mut Self|);
+
+    // Specialized types:
+    fn emit_option(&mut self, f: |&mut Self|);
+    fn emit_option_none(&mut self);
+    fn emit_option_some(&mut self, f: |&mut Self|);
+
+    fn emit_seq(&mut self, len: uint, f: |this: &mut Self|);
+    fn emit_seq_elt(&mut self, idx: uint, f: |this: &mut Self|);
+
+    fn emit_map(&mut self, len: uint, f: |&mut Self|);
+    fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Self|);
+    fn emit_map_elt_val(&mut self, idx: uint, f: |&mut Self|);
+}
+
+pub trait Decoder {
+    // Primitive types:
+    fn read_nil(&mut self) -> ();
+    fn read_uint(&mut self) -> uint;
+    fn read_u64(&mut self) -> u64;
+    fn read_u32(&mut self) -> u32;
+    fn read_u16(&mut self) -> u16;
+    fn read_u8(&mut self) -> u8;
+    fn read_int(&mut self) -> int;
+    fn read_i64(&mut self) -> i64;
+    fn read_i32(&mut self) -> i32;
+    fn read_i16(&mut self) -> i16;
+    fn read_i8(&mut self) -> i8;
+    fn read_bool(&mut self) -> bool;
+    fn read_f64(&mut self) -> f64;
+    fn read_f32(&mut self) -> f32;
+    fn read_char(&mut self) -> char;
+    fn read_str(&mut self) -> ~str;
+
+    // Compound types:
+    fn read_enum<T>(&mut self, name: &str, f: |&mut Self| -> T) -> T;
+
+    fn read_enum_variant<T>(&mut self,
+                            names: &[&str],
+                            f: |&mut Self, uint| -> T)
+                            -> T;
+    fn read_enum_variant_arg<T>(&mut self,
+                                a_idx: uint,
+                                f: |&mut Self| -> T)
+                                -> T;
+
+    fn read_enum_struct_variant<T>(&mut self,
+                                   names: &[&str],
+                                   f: |&mut Self, uint| -> T)
+                                   -> T;
+    fn read_enum_struct_variant_field<T>(&mut self,
+                                         &f_name: &str,
+                                         f_idx: uint,
+                                         f: |&mut Self| -> T)
+                                         -> T;
+
+    fn read_struct<T>(&mut self, s_name: &str, len: uint, f: |&mut Self| -> T)
+                      -> T;
+    fn read_struct_field<T>(&mut self,
+                            f_name: &str,
+                            f_idx: uint,
+                            f: |&mut Self| -> T)
+                            -> T;
+
+    fn read_tuple<T>(&mut self, f: |&mut Self, uint| -> T) -> T;
+    fn read_tuple_arg<T>(&mut self, a_idx: uint, f: |&mut Self| -> T) -> T;
+
+    fn read_tuple_struct<T>(&mut self,
+                            s_name: &str,
+                            f: |&mut Self, uint| -> T)
+                            -> T;
+    fn read_tuple_struct_arg<T>(&mut self,
+                                a_idx: uint,
+                                f: |&mut Self| -> T)
+                                -> T;
+
+    // Specialized types:
+    fn read_option<T>(&mut self, f: |&mut Self, bool| -> T) -> T;
+
+    fn read_seq<T>(&mut self, f: |&mut Self, uint| -> T) -> T;
+    fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Self| -> T) -> T;
+
+    fn read_map<T>(&mut self, f: |&mut Self, uint| -> T) -> T;
+    fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Self| -> T) -> T;
+    fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Self| -> T) -> T;
+}
+
+pub trait Encodable<S:Encoder> {
+    fn encode(&self, s: &mut S);
+}
+
+pub trait Decodable<D:Decoder> {
+    fn decode(d: &mut D) -> Self;
+}
+
+impl<S:Encoder> Encodable<S> for uint {
+    fn encode(&self, s: &mut S) {
+        s.emit_uint(*self)
+    }
+}
+
+impl<D:Decoder> Decodable<D> for uint {
+    fn decode(d: &mut D) -> uint {
+        d.read_uint()
+    }
+}
+
+impl<S:Encoder> Encodable<S> for u8 {
+    fn encode(&self, s: &mut S) {
+        s.emit_u8(*self)
+    }
+}
+
+impl<D:Decoder> Decodable<D> for u8 {
+    fn decode(d: &mut D) -> u8 {
+        d.read_u8()
+    }
+}
+
+impl<S:Encoder> Encodable<S> for u16 {
+    fn encode(&self, s: &mut S) {
+        s.emit_u16(*self)
+    }
+}
+
+impl<D:Decoder> Decodable<D> for u16 {
+    fn decode(d: &mut D) -> u16 {
+        d.read_u16()
+    }
+}
+
+impl<S:Encoder> Encodable<S> for u32 {
+    fn encode(&self, s: &mut S) {
+        s.emit_u32(*self)
+    }
+}
+
+impl<D:Decoder> Decodable<D> for u32 {
+    fn decode(d: &mut D) -> u32 {
+        d.read_u32()
+    }
+}
+
+impl<S:Encoder> Encodable<S> for u64 {
+    fn encode(&self, s: &mut S) {
+        s.emit_u64(*self)
+    }
+}
+
+impl<D:Decoder> Decodable<D> for u64 {
+    fn decode(d: &mut D) -> u64 {
+        d.read_u64()
+    }
+}
+
+impl<S:Encoder> Encodable<S> for int {
+    fn encode(&self, s: &mut S) {
+        s.emit_int(*self)
+    }
+}
+
+impl<D:Decoder> Decodable<D> for int {
+    fn decode(d: &mut D) -> int {
+        d.read_int()
+    }
+}
+
+impl<S:Encoder> Encodable<S> for i8 {
+    fn encode(&self, s: &mut S) {
+        s.emit_i8(*self)
+    }
+}
+
+impl<D:Decoder> Decodable<D> for i8 {
+    fn decode(d: &mut D) -> i8 {
+        d.read_i8()
+    }
+}
+
+impl<S:Encoder> Encodable<S> for i16 {
+    fn encode(&self, s: &mut S) {
+        s.emit_i16(*self)
+    }
+}
+
+impl<D:Decoder> Decodable<D> for i16 {
+    fn decode(d: &mut D) -> i16 {
+        d.read_i16()
+    }
+}
+
+impl<S:Encoder> Encodable<S> for i32 {
+    fn encode(&self, s: &mut S) {
+        s.emit_i32(*self)
+    }
+}
+
+impl<D:Decoder> Decodable<D> for i32 {
+    fn decode(d: &mut D) -> i32 {
+        d.read_i32()
+    }
+}
+
+impl<S:Encoder> Encodable<S> for i64 {
+    fn encode(&self, s: &mut S) {
+        s.emit_i64(*self)
+    }
+}
+
+impl<D:Decoder> Decodable<D> for i64 {
+    fn decode(d: &mut D) -> i64 {
+        d.read_i64()
+    }
+}
+
+impl<'a, S:Encoder> Encodable<S> for &'a str {
+    fn encode(&self, s: &mut S) {
+        s.emit_str(*self)
+    }
+}
+
+impl<S:Encoder> Encodable<S> for ~str {
+    fn encode(&self, s: &mut S) {
+        s.emit_str(*self)
+    }
+}
+
+impl<D:Decoder> Decodable<D> for ~str {
+    fn decode(d: &mut D) -> ~str {
+        d.read_str()
+    }
+}
+
+impl<S:Encoder> Encodable<S> for f32 {
+    fn encode(&self, s: &mut S) {
+        s.emit_f32(*self)
+    }
+}
+
+impl<D:Decoder> Decodable<D> for f32 {
+    fn decode(d: &mut D) -> f32 {
+        d.read_f32()
+    }
+}
+
+impl<S:Encoder> Encodable<S> for f64 {
+    fn encode(&self, s: &mut S) {
+        s.emit_f64(*self)
+    }
+}
+
+impl<D:Decoder> Decodable<D> for f64 {
+    fn decode(d: &mut D) -> f64 {
+        d.read_f64()
+    }
+}
+
+impl<S:Encoder> Encodable<S> for bool {
+    fn encode(&self, s: &mut S) {
+        s.emit_bool(*self)
+    }
+}
+
+impl<D:Decoder> Decodable<D> for bool {
+    fn decode(d: &mut D) -> bool {
+        d.read_bool()
+    }
+}
+
+impl<S:Encoder> Encodable<S> for char {
+    fn encode(&self, s: &mut S) {
+        s.emit_char(*self)
+    }
+}
+
+impl<D:Decoder> Decodable<D> for char {
+    fn decode(d: &mut D) -> char {
+        d.read_char()
+    }
+}
+
+impl<S:Encoder> Encodable<S> for () {
+    fn encode(&self, s: &mut S) {
+        s.emit_nil()
+    }
+}
+
+impl<D:Decoder> Decodable<D> for () {
+    fn decode(d: &mut D) -> () {
+        d.read_nil()
+    }
+}
+
+impl<'a, S:Encoder,T:Encodable<S>> Encodable<S> for &'a T {
+    fn encode(&self, s: &mut S) {
+        (**self).encode(s)
+    }
+}
+
+impl<S:Encoder,T:Encodable<S>> Encodable<S> for ~T {
+    fn encode(&self, s: &mut S) {
+        (**self).encode(s)
+    }
+}
+
+impl<D:Decoder,T:Decodable<D>> Decodable<D> for ~T {
+    fn decode(d: &mut D) -> ~T {
+        ~Decodable::decode(d)
+    }
+}
+
+impl<S:Encoder,T:Encodable<S>> Encodable<S> for @T {
+    fn encode(&self, s: &mut S) {
+        (**self).encode(s)
+    }
+}
+
+impl<S:Encoder,T:Encodable<S>> Encodable<S> for Rc<T> {
+    #[inline]
+    fn encode(&self, s: &mut S) {
+        (**self).encode(s)
+    }
+}
+
+impl<D:Decoder,T:Decodable<D>> Decodable<D> for Rc<T> {
+    #[inline]
+    fn decode(d: &mut D) -> Rc<T> {
+        Rc::new(Decodable::decode(d))
+    }
+}
+
+impl<D:Decoder,T:Decodable<D> + 'static> Decodable<D> for @T {
+    fn decode(d: &mut D) -> @T {
+        @Decodable::decode(d)
+    }
+}
+
+impl<'a, S:Encoder,T:Encodable<S>> Encodable<S> for &'a [T] {
+    fn encode(&self, s: &mut S) {
+        s.emit_seq(self.len(), |s| {
+            for (i, e) in self.iter().enumerate() {
+                s.emit_seq_elt(i, |s| e.encode(s))
+            }
+        })
+    }
+}
+
+impl<S:Encoder,T:Encodable<S>> Encodable<S> for ~[T] {
+    fn encode(&self, s: &mut S) {
+        s.emit_seq(self.len(), |s| {
+            for (i, e) in self.iter().enumerate() {
+                s.emit_seq_elt(i, |s| e.encode(s))
+            }
+        })
+    }
+}
+
+impl<D:Decoder,T:Decodable<D>> Decodable<D> for ~[T] {
+    fn decode(d: &mut D) -> ~[T] {
+        d.read_seq(|d, len| {
+            slice::from_fn(len, |i| {
+                d.read_seq_elt(i, |d| Decodable::decode(d))
+            })
+        })
+    }
+}
+
+impl<S:Encoder,T:Encodable<S>> Encodable<S> for Vec<T> {
+    fn encode(&self, s: &mut S) {
+        s.emit_seq(self.len(), |s| {
+            for (i, e) in self.iter().enumerate() {
+                s.emit_seq_elt(i, |s| e.encode(s))
+            }
+        })
+    }
+}
+
+impl<D:Decoder,T:Decodable<D>> Decodable<D> for Vec<T> {
+    fn decode(d: &mut D) -> Vec<T> {
+        d.read_seq(|d, len| {
+            Vec::from_fn(len, |i| {
+                d.read_seq_elt(i, |d| Decodable::decode(d))
+            })
+        })
+    }
+}
+
+impl<S:Encoder,T:Encodable<S>> Encodable<S> for Option<T> {
+    fn encode(&self, s: &mut S) {
+        s.emit_option(|s| {
+            match *self {
+                None => s.emit_option_none(),
+                Some(ref v) => s.emit_option_some(|s| v.encode(s)),
+            }
+        })
+    }
+}
+
+impl<D:Decoder,T:Decodable<D>> Decodable<D> for Option<T> {
+    fn decode(d: &mut D) -> Option<T> {
+        d.read_option(|d, b| {
+            if b {
+                Some(Decodable::decode(d))
+            } else {
+                None
+            }
+        })
+    }
+}
+
+impl<S:Encoder,T0:Encodable<S>,T1:Encodable<S>> Encodable<S> for (T0, T1) {
+    fn encode(&self, s: &mut S) {
+        match *self {
+            (ref t0, ref t1) => {
+                s.emit_seq(2, |s| {
+                    s.emit_seq_elt(0, |s| t0.encode(s));
+                    s.emit_seq_elt(1, |s| t1.encode(s));
+                })
+            }
+        }
+    }
+}
+
+impl<D:Decoder,T0:Decodable<D>,T1:Decodable<D>> Decodable<D> for (T0, T1) {
+    fn decode(d: &mut D) -> (T0, T1) {
+        d.read_seq(|d, len| {
+            assert_eq!(len, 2);
+            (
+                d.read_seq_elt(0, |d| Decodable::decode(d)),
+                d.read_seq_elt(1, |d| Decodable::decode(d))
+            )
+        })
+    }
+}
+
+impl<
+    S: Encoder,
+    T0: Encodable<S>,
+    T1: Encodable<S>,
+    T2: Encodable<S>
+> Encodable<S> for (T0, T1, T2) {
+    fn encode(&self, s: &mut S) {
+        match *self {
+            (ref t0, ref t1, ref t2) => {
+                s.emit_seq(3, |s| {
+                    s.emit_seq_elt(0, |s| t0.encode(s));
+                    s.emit_seq_elt(1, |s| t1.encode(s));
+                    s.emit_seq_elt(2, |s| t2.encode(s));
+                })
+            }
+        }
+    }
+}
+
+impl<
+    D: Decoder,
+    T0: Decodable<D>,
+    T1: Decodable<D>,
+    T2: Decodable<D>
+> Decodable<D> for (T0, T1, T2) {
+    fn decode(d: &mut D) -> (T0, T1, T2) {
+        d.read_seq(|d, len| {
+            assert_eq!(len, 3);
+            (
+                d.read_seq_elt(0, |d| Decodable::decode(d)),
+                d.read_seq_elt(1, |d| Decodable::decode(d)),
+                d.read_seq_elt(2, |d| Decodable::decode(d))
+            )
+        })
+    }
+}
+
+impl<
+    S: Encoder,
+    T0: Encodable<S>,
+    T1: Encodable<S>,
+    T2: Encodable<S>,
+    T3: Encodable<S>
+> Encodable<S> for (T0, T1, T2, T3) {
+    fn encode(&self, s: &mut S) {
+        match *self {
+            (ref t0, ref t1, ref t2, ref t3) => {
+                s.emit_seq(4, |s| {
+                    s.emit_seq_elt(0, |s| t0.encode(s));
+                    s.emit_seq_elt(1, |s| t1.encode(s));
+                    s.emit_seq_elt(2, |s| t2.encode(s));
+                    s.emit_seq_elt(3, |s| t3.encode(s));
+                })
+            }
+        }
+    }
+}
+
+impl<
+    D: Decoder,
+    T0: Decodable<D>,
+    T1: Decodable<D>,
+    T2: Decodable<D>,
+    T3: Decodable<D>
+> Decodable<D> for (T0, T1, T2, T3) {
+    fn decode(d: &mut D) -> (T0, T1, T2, T3) {
+        d.read_seq(|d, len| {
+            assert_eq!(len, 4);
+            (
+                d.read_seq_elt(0, |d| Decodable::decode(d)),
+                d.read_seq_elt(1, |d| Decodable::decode(d)),
+                d.read_seq_elt(2, |d| Decodable::decode(d)),
+                d.read_seq_elt(3, |d| Decodable::decode(d))
+            )
+        })
+    }
+}
+
+impl<
+    S: Encoder,
+    T0: Encodable<S>,
+    T1: Encodable<S>,
+    T2: Encodable<S>,
+    T3: Encodable<S>,
+    T4: Encodable<S>
+> Encodable<S> for (T0, T1, T2, T3, T4) {
+    fn encode(&self, s: &mut S) {
+        match *self {
+            (ref t0, ref t1, ref t2, ref t3, ref t4) => {
+                s.emit_seq(5, |s| {
+                    s.emit_seq_elt(0, |s| t0.encode(s));
+                    s.emit_seq_elt(1, |s| t1.encode(s));
+                    s.emit_seq_elt(2, |s| t2.encode(s));
+                    s.emit_seq_elt(3, |s| t3.encode(s));
+                    s.emit_seq_elt(4, |s| t4.encode(s));
+                })
+            }
+        }
+    }
+}
+
+impl<
+    D: Decoder,
+    T0: Decodable<D>,
+    T1: Decodable<D>,
+    T2: Decodable<D>,
+    T3: Decodable<D>,
+    T4: Decodable<D>
+> Decodable<D> for (T0, T1, T2, T3, T4) {
+    fn decode(d: &mut D) -> (T0, T1, T2, T3, T4) {
+        d.read_seq(|d, len| {
+            assert_eq!(len, 5);
+            (
+                d.read_seq_elt(0, |d| Decodable::decode(d)),
+                d.read_seq_elt(1, |d| Decodable::decode(d)),
+                d.read_seq_elt(2, |d| Decodable::decode(d)),
+                d.read_seq_elt(3, |d| Decodable::decode(d)),
+                d.read_seq_elt(4, |d| Decodable::decode(d))
+            )
+        })
+    }
+}
+
+impl<E: Encoder> Encodable<E> for path::posix::Path {
+    fn encode(&self, e: &mut E) {
+        self.as_vec().encode(e)
+    }
+}
+
+impl<D: Decoder> Decodable<D> for path::posix::Path {
+    fn decode(d: &mut D) -> path::posix::Path {
+        let bytes: ~[u8] = Decodable::decode(d);
+        path::posix::Path::new(bytes)
+    }
+}
+
+impl<E: Encoder> Encodable<E> for path::windows::Path {
+    fn encode(&self, e: &mut E) {
+        self.as_vec().encode(e)
+    }
+}
+
+impl<D: Decoder> Decodable<D> for path::windows::Path {
+    fn decode(d: &mut D) -> path::windows::Path {
+        let bytes: ~[u8] = Decodable::decode(d);
+        path::windows::Path::new(bytes)
+    }
+}
+
+// ___________________________________________________________________________
+// Helper routines
+//
+// In some cases, these should eventually be coded as traits.
+
+pub trait EncoderHelpers {
+    fn emit_from_vec<T>(&mut self, v: &[T], f: |&mut Self, v: &T|);
+}
+
+impl<S:Encoder> EncoderHelpers for S {
+    fn emit_from_vec<T>(&mut self, v: &[T], f: |&mut S, &T|) {
+        self.emit_seq(v.len(), |this| {
+            for (i, e) in v.iter().enumerate() {
+                this.emit_seq_elt(i, |this| {
+                    f(this, e)
+                })
+            }
+        })
+    }
+}
+
+pub trait DecoderHelpers {
+    fn read_to_vec<T>(&mut self, f: |&mut Self| -> T) -> ~[T];
+}
+
+impl<D:Decoder> DecoderHelpers for D {
+    fn read_to_vec<T>(&mut self, f: |&mut D| -> T) -> ~[T] {
+        self.read_seq(|this, len| {
+            slice::from_fn(len, |i| {
+                this.read_seq_elt(i, |this| f(this))
+            })
+        })
+    }
+}
+
index a7d458df0cf85f1e40eb40e4fd3fc0339025bab7..a44fbce421b441413b757630b50040a707ad970b 100644 (file)
@@ -98,18 +98,35 @@ fn ne(&self, other: &Ident) -> bool {
 /// A mark represents a unique id associated with a macro expansion
 pub type Mrk = u32;
 
+// FIXME: remove stage0 Encodables after snapshot
+#[cfg(stage0)]
 impl<S: Encoder> Encodable<S> for Ident {
     fn encode(&self, s: &mut S) {
         s.emit_str(token::get_ident(*self).get());
     }
 }
 
+#[cfg(stage0)]
 impl<D:Decoder> Decodable<D> for Ident {
     fn decode(d: &mut D) -> Ident {
         str_to_ident(d.read_str())
     }
 }
 
+#[cfg(not(stage0))]
+impl<S: Encoder<E>, E> Encodable<S, E> for Ident {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_str(token::get_ident(*self).get())
+    }
+}
+
+#[cfg(not(stage0))]
+impl<D:Decoder<E>, E> Decodable<D, E> for Ident {
+    fn decode(d: &mut D) -> Result<Ident, E> {
+        Ok(str_to_ident(try!(d.read_str())))
+    }
+}
+
 /// Function name (not all functions have names)
 pub type FnIdent = Option<Ident>;
 
@@ -1166,7 +1183,9 @@ mod test {
     use super::*;
 
     // are ASTs encodable?
+    // FIXME: remove stage0 test after snapshot
     #[test]
+    #[cfg(stage0)]
     fn check_asts_encodable() {
         let e = Crate {
             module: Mod {view_items: Vec::new(), items: Vec::new()},
@@ -1181,4 +1200,22 @@ fn check_asts_encodable() {
         // doesn't matter which encoder we use....
         let _f = &e as &serialize::Encodable<json::Encoder>;
     }
+
+    #[test]
+    #[cfg(not(stage0))]
+    fn check_asts_encodable() {
+        use std::io;
+        let e = Crate {
+            module: Mod {view_items: Vec::new(), items: Vec::new()},
+            attrs: Vec::new(),
+            config: Vec::new(),
+            span: Span {
+                lo: BytePos(10),
+                hi: BytePos(20),
+                expn_info: None,
+            },
+        };
+        // doesn't matter which encoder we use....
+        let _f = &e as &serialize::Encodable<json::Encoder, io::IoError>;
+    }
 }
index 4a9e53c63e7bf6ed7404e13269320deb371e37d9..f3ff7f97ee2e1b22e0f3356c8d864ee793899e0d 100644 (file)
@@ -110,6 +110,8 @@ fn ne(&self, other: &Span) -> bool { !(*self).eq(other) }
 
 impl TotalEq for Span {}
 
+// FIXME: remove stage0 Encodables/Decodables after snapshot
+#[cfg(stage0)]
 impl<S:Encoder> Encodable<S> for Span {
     /* Note #1972 -- spans are encoded but not decoded */
     fn encode(&self, s: &mut S) {
@@ -117,12 +119,28 @@ fn encode(&self, s: &mut S) {
     }
 }
 
+#[cfg(stage0)]
 impl<D:Decoder> Decodable<D> for Span {
     fn decode(_d: &mut D) -> Span {
         DUMMY_SP
     }
 }
 
+#[cfg(not(stage0))]
+impl<S:Encoder<E>, E> Encodable<S, E> for Span {
+    /* Note #1972 -- spans are encoded but not decoded */
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_nil()
+    }
+}
+
+#[cfg(not(stage0))]
+impl<D:Decoder<E>, E> Decodable<D, E> for Span {
+    fn decode(_d: &mut D) -> Result<Span, E> {
+        Ok(DUMMY_SP)
+    }
+}
+
 pub fn spanned<T>(lo: BytePos, hi: BytePos, t: T) -> Spanned<T> {
     respan(mk_sp(lo, hi), t)
 }
index bdb16f176c0812544d35f11733a718e563f1eaac..1c2c63cd91974c25ba5df368a98c1897d5259f82 100644 (file)
@@ -142,6 +142,10 @@ fn expr_method_call(&self, span: Span,
     fn expr_fail(&self, span: Span, msg: InternedString) -> @ast::Expr;
     fn expr_unreachable(&self, span: Span) -> @ast::Expr;
 
+    fn expr_ok(&self, span: Span, expr: @ast::Expr) -> @ast::Expr;
+    fn expr_err(&self, span: Span, expr: @ast::Expr) -> @ast::Expr;
+    fn expr_try(&self, span: Span, head: @ast::Expr) -> @ast::Expr;
+
     fn pat(&self, span: Span, pat: ast::Pat_) -> @ast::Pat;
     fn pat_wild(&self, span: Span) -> @ast::Pat;
     fn pat_lit(&self, span: Span, expr: @ast::Expr) -> @ast::Pat;
@@ -638,6 +642,50 @@ fn expr_unreachable(&self, span: Span) -> @ast::Expr {
                            "internal error: entered unreachable code"))
     }
 
+    fn expr_ok(&self, sp: Span, expr: @ast::Expr) -> @ast::Expr {
+        let ok = vec!(
+            self.ident_of("std"),
+            self.ident_of("result"),
+            self.ident_of("Ok"));
+        self.expr_call_global(sp, ok, vec!(expr))
+    }
+
+    fn expr_err(&self, sp: Span, expr: @ast::Expr) -> @ast::Expr {
+        let err = vec!(
+            self.ident_of("std"),
+            self.ident_of("result"),
+            self.ident_of("Err"));
+        self.expr_call_global(sp, err, vec!(expr))
+    }
+
+    fn expr_try(&self, sp: Span, head: @ast::Expr) -> @ast::Expr {
+        let ok = self.ident_of("Ok");
+        let ok_path = self.path_ident(sp, ok);
+        let err = self.ident_of("Err");
+        let err_path = self.path_ident(sp, err);
+
+        let binding_variable = self.ident_of("__try_var");
+        let binding_pat = self.pat_ident(sp, binding_variable);
+        let binding_expr = self.expr_ident(sp, binding_variable);
+
+        // Ok(__try_var) pattern
+        let ok_pat = self.pat_enum(sp, ok_path, vec!(binding_pat));
+
+        // Err(__try_var)  (pattern and expression resp.)
+        let err_pat = self.pat_enum(sp, err_path, vec!(binding_pat));
+        let err_inner_expr = self.expr_call_ident(sp, err, vec!(binding_expr));
+        // return Err(__try_var)
+        let err_expr = self.expr(sp, ast::ExprRet(Some(err_inner_expr)));
+
+        // Ok(__try_var) => __try_var
+        let ok_arm = self.arm(sp, vec!(ok_pat), binding_expr);
+        // Err(__try_var) => return Err(__try_var)
+        let err_arm = self.arm(sp, vec!(err_pat), err_expr);
+
+        // match head { Ok() => ..., Err() => ... }
+        self.expr_match(sp, head, vec!(ok_arm, err_arm))
+    }
+
 
     fn pat(&self, span: Span, pat: ast::Pat_) -> @ast::Pat {
         @ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, span: span }
index 4c9a58c46f733270232df7b94900672ef8617329..579de82c8db376efe4a73c536ff3746c437765fa 100644 (file)
@@ -30,11 +30,15 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
         span: span,
         attributes: Vec::new(),
         path: Path::new_(vec!("serialize", "Decodable"), None,
-                         vec!(~Literal(Path::new_local("__D"))), true),
+                         vec!(~Literal(Path::new_local("__D")),
+                              ~Literal(Path::new_local("__E"))), true),
         additional_bounds: Vec::new(),
         generics: LifetimeBounds {
             lifetimes: Vec::new(),
-            bounds: vec!(("__D", vec!(Path::new(vec!("serialize", "Decoder"))))),
+            bounds: vec!(("__D", vec!(Path::new_(
+                            vec!("serialize", "Decoder"), None,
+                            vec!(~Literal(Path::new_local("__E"))), true))),
+                         ("__E", vec!()))
         },
         methods: vec!(
             MethodDef {
@@ -43,7 +47,8 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
                 explicit_self: None,
                 args: vec!(Ptr(~Literal(Path::new_local("__D")),
                             Borrowed(None, MutMutable))),
-                ret_ty: Self,
+                ret_ty: Literal(Path::new_(vec!("std", "result", "Result"), None,
+                                          vec!(~Self, ~Literal(Path::new_local("__E"))), true)),
                 inline: false,
                 const_nonmatching: true,
                 combine_substructure: decodable_substructure,
@@ -78,11 +83,13 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                                               substr.type_ident,
                                               summary,
                                               |cx, span, name, field| {
-                cx.expr_method_call(span, blkdecoder, read_struct_field,
-                                    vec!(cx.expr_str(span, name),
-                                      cx.expr_uint(span, field),
-                                      lambdadecode))
+                cx.expr_try(span,
+                    cx.expr_method_call(span, blkdecoder, read_struct_field,
+                                        vec!(cx.expr_str(span, name),
+                                          cx.expr_uint(span, field),
+                                          lambdadecode)))
             });
+            let result = cx.expr_ok(trait_span, result);
             cx.expr_method_call(trait_span,
                                 decoder,
                                 cx.ident_of("read_struct"),
@@ -108,8 +115,9 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                                                    parts,
                                                    |cx, span, _, field| {
                     let idx = cx.expr_uint(span, field);
-                    cx.expr_method_call(span, blkdecoder, rvariant_arg,
-                                        vec!(idx, lambdadecode))
+                    cx.expr_try(span,
+                        cx.expr_method_call(span, blkdecoder, rvariant_arg,
+                                            vec!(idx, lambdadecode)))
                 });
 
                 arms.push(cx.arm(v_span,
@@ -119,7 +127,9 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
 
             arms.push(cx.arm_unreachable(trait_span));
 
-            let result = cx.expr_match(trait_span, cx.expr_ident(trait_span, variant), arms);
+            let result = cx.expr_ok(trait_span,
+                                    cx.expr_match(trait_span,
+                                                  cx.expr_ident(trait_span, variant), arms));
             let lambda = cx.lambda_expr(trait_span, vec!(blkarg, variant), result);
             let variant_vec = cx.expr_vec(trait_span, variants);
             let result = cx.expr_method_call(trait_span, blkdecoder,
index 2fa6ec6888b6b41d189f2ad145e9564f352b70b2..90ea8701562e632fb842e3f4593fc9d8139bce50 100644 (file)
@@ -82,7 +82,7 @@ fn decode(d: &D) -> spanned<T> {
 ```
 */
 
-use ast::{MetaItem, Item, Expr, MutMutable};
+use ast::{MetaItem, Item, Expr, ExprRet, MutMutable, LitNil};
 use codemap::Span;
 use ext::base::ExtCtxt;
 use ext::build::AstBuilder;
@@ -98,20 +98,28 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
         span: span,
         attributes: Vec::new(),
         path: Path::new_(vec!("serialize", "Encodable"), None,
-                         vec!(~Literal(Path::new_local("__E"))), true),
+                         vec!(~Literal(Path::new_local("__S")),
+                              ~Literal(Path::new_local("__E"))), true),
         additional_bounds: Vec::new(),
         generics: LifetimeBounds {
             lifetimes: Vec::new(),
-            bounds: vec!(("__E", vec!(Path::new(vec!("serialize", "Encoder"))))),
+            bounds: vec!(("__S", vec!(Path::new_(
+                            vec!("serialize", "Encoder"), None,
+                            vec!(~Literal(Path::new_local("__E"))), true))),
+                         ("__E", vec!()))
         },
         methods: vec!(
             MethodDef {
                 name: "encode",
                 generics: LifetimeBounds::empty(),
                 explicit_self: borrowed_explicit_self(),
-                args: vec!(Ptr(~Literal(Path::new_local("__E")),
+                args: vec!(Ptr(~Literal(Path::new_local("__S")),
                             Borrowed(None, MutMutable))),
-                ret_ty: nil_ty(),
+                ret_ty: Literal(Path::new_(vec!("std", "result", "Result"),
+                                           None,
+                                           vec!(~Tuple(Vec::new()),
+                                                ~Literal(Path::new_local("__E"))),
+                                           true)),
                 inline: false,
                 const_nonmatching: true,
                 combine_substructure: encodable_substructure,
@@ -133,6 +141,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
         Struct(ref fields) => {
             let emit_struct_field = cx.ident_of("emit_struct_field");
             let mut stmts = Vec::new();
+            let last = fields.len() - 1;
             for (i, &FieldInfo {
                     name,
                     self_,
@@ -152,6 +161,13 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                                                vec!(cx.expr_str(span, name),
                                                  cx.expr_uint(span, i),
                                                  lambda));
+
+                // last call doesn't need a try!
+                let call = if i != last {
+                    cx.expr_try(span, call)
+                } else {
+                    cx.expr(span, ExprRet(Some(call)))
+                };
                 stmts.push(cx.stmt_expr(call));
             }
 
@@ -175,6 +191,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
             let encoder = cx.expr_ident(trait_span, blkarg);
             let emit_variant_arg = cx.ident_of("emit_enum_variant_arg");
             let mut stmts = Vec::new();
+            let last = fields.len() - 1;
             for (i, &FieldInfo { self_, span, .. }) in fields.iter().enumerate() {
                 let enc = cx.expr_method_call(span, self_, encode, vec!(blkencoder));
                 let lambda = cx.lambda_expr_1(span, enc, blkarg);
@@ -182,9 +199,22 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                                                emit_variant_arg,
                                                vec!(cx.expr_uint(span, i),
                                                  lambda));
+                let call = if i != last {
+                    cx.expr_try(span, call)
+                } else {
+                    cx.expr(span, ExprRet(Some(call)))
+                };
                 stmts.push(cx.stmt_expr(call));
             }
 
+            // enums with no fields need to return Ok()
+            if stmts.len() == 0 {
+                let ret_ok = cx.expr(trait_span,
+                                     ExprRet(Some(cx.expr_ok(trait_span,
+                                                             cx.expr_lit(trait_span, LitNil)))));
+                stmts.push(cx.stmt_expr(ret_ok));
+            }
+
             let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg);
             let name = cx.expr_str(trait_span, token::get_ident(variant.node.name));
             let call = cx.expr_method_call(trait_span, blkencoder,
index 57051e78667149cf37d2644a235cb65f553e1f9d..c4ce3c5cb551c986a603c4db0b94dbc250123511 100644 (file)
@@ -131,14 +131,34 @@ fn from_iterator<I: Iterator<T>>(mut iter: I) -> OwnedSlice<T> {
     }
 }
 
+// FIXME: remove stage0 Encodables/Decodables after snapshot
+#[cfg(stage0)]
 impl<S: Encoder, T: Encodable<S>> Encodable<S> for OwnedSlice<T> {
     fn encode(&self, s: &mut S) {
        self.as_slice().encode(s)
     }
 }
 
+#[cfg(stage0)]
 impl<D: Decoder, T: Decodable<D>> Decodable<D> for OwnedSlice<T> {
     fn decode(d: &mut D) -> OwnedSlice<T> {
         OwnedSlice::from_vec(Decodable::decode(d))
     }
 }
+
+#[cfg(not(stage0))]
+impl<S: Encoder<E>, T: Encodable<S, E>, E> Encodable<S, E> for OwnedSlice<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+       self.as_slice().encode(s)
+    }
+}
+
+#[cfg(not(stage0))]
+impl<D: Decoder<E>, T: Decodable<D, E>, E> Decodable<D, E> for OwnedSlice<T> {
+    fn decode(d: &mut D) -> Result<OwnedSlice<T>, E> {
+        Ok(OwnedSlice::from_vec(match Decodable::decode(d) {
+            Ok(t) => t,
+            Err(e) => return Err(e)
+        }))
+    }
+}
index eb6b462fb94fc9761c60d20fa50e61a9855459c2..2df93deea14b66669f4b718ac81d15fdb37d217b 100644 (file)
@@ -288,7 +288,8 @@ mod test {
     use util::parser_testing::{string_to_expr, string_to_item};
     use util::parser_testing::string_to_stmt;
 
-    #[cfg(test)]
+    // FIXME: remove stage0 to_json_str after snapshot
+    #[cfg(stage0)]
     fn to_json_str<'a, E: Encodable<json::Encoder<'a>>>(val: &E) -> ~str {
         let mut writer = MemWriter::new();
         let mut encoder = json::Encoder::new(&mut writer as &mut io::Writer);
@@ -296,6 +297,14 @@ fn to_json_str<'a, E: Encodable<json::Encoder<'a>>>(val: &E) -> ~str {
         str::from_utf8_owned(writer.unwrap()).unwrap()
     }
 
+    #[cfg(not(stage0))]
+    fn to_json_str<'a, E: Encodable<json::Encoder<'a>, io::IoError>>(val: &E) -> ~str {
+        let mut writer = MemWriter::new();
+        let mut encoder = json::Encoder::new(&mut writer as &mut io::Writer);
+        let _ = val.encode(&mut encoder);
+        str::from_utf8_owned(writer.unwrap()).unwrap()
+    }
+
     // produce a codemap::span
     fn sp(a: u32, b: u32) -> Span {
         Span{lo:BytePos(a),hi:BytePos(b),expn_info:None}
index 15525912955fcce4f15a82b2231607744e91b492..7bb920bdf56dc3b2f1228b8ea594046049c40c26 100644 (file)
@@ -602,18 +602,35 @@ fn equiv(&self, other: & &'a str) -> bool {
     }
 }
 
+// FIXME: remove stage0 Encodables/Decodables after snapshot
+#[cfg(stage0)]
 impl<D:Decoder> Decodable<D> for InternedString {
     fn decode(d: &mut D) -> InternedString {
         get_name(get_ident_interner().intern(d.read_str()))
     }
 }
 
+#[cfg(stage0)]
 impl<E:Encoder> Encodable<E> for InternedString {
     fn encode(&self, e: &mut E) {
         e.emit_str(self.string.as_slice())
     }
 }
 
+#[cfg(not(stage0))]
+impl<D:Decoder<E>, E> Decodable<D, E> for InternedString {
+    fn decode(d: &mut D) -> Result<InternedString, E> {
+        Ok(get_name(get_ident_interner().intern(try!(d.read_str()))))
+    }
+}
+
+#[cfg(not(stage0))]
+impl<S:Encoder<E>, E> Encodable<S, E> for InternedString {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_str(self.string.as_slice())
+    }
+}
+
 /// Returns the string contents of a name, using the task-local interner.
 #[inline]
 pub fn get_name(name: Name) -> InternedString {
index 039b118b327f19172eb68ebdad85787b345b773b..751dc58450f91ceeb5058581f631d96ec29af8a0 100644 (file)
@@ -46,7 +46,7 @@
 use time::precise_time_ns;
 use getopts::{OptGroup, optflag, optopt};
 use serialize::{json, Decodable};
-use serialize::json::ToJson;
+use serialize::json::{Json, ToJson};
 use term::Terminal;
 use term::color::{Color, RED, YELLOW, GREEN, CYAN};
 
@@ -1018,6 +1018,23 @@ fn to_json(&self) -> json::Json {
     }
 }
 
+// FIXME: remove decode_ after snapshot
+#[cfg(stage0)]
+fn decode_(json: Json) -> MetricMap {
+    let mut decoder = json::Decoder::new(json);
+    MetricMap(Decodable::decode(&mut decoder))
+}
+
+#[cfg(not(stage0))]
+fn decode_(json: Json) -> MetricMap {
+    let mut decoder = json::Decoder::new(json);
+    MetricMap(match Decodable::decode(&mut decoder) {
+        Ok(t) => t,
+        Err(e) => fail!("failure decoding JSON: {}", e)
+    })
+}
+
+
 impl MetricMap {
 
     pub fn new() -> MetricMap {
@@ -1034,8 +1051,7 @@ pub fn load(p: &Path) -> MetricMap {
         assert!(p.exists());
         let mut f = File::open(p).unwrap();
         let value = json::from_reader(&mut f as &mut io::Reader).unwrap();
-        let mut decoder = json::Decoder::new(value);
-        MetricMap(Decodable::decode(&mut decoder))
+        decode_(value)
     }
 
     /// Write MetricDiff to a file.
index d31b0f43a090bdb8e39e8a1585a82f8ed10ae749..0065c90c91a12cac92d6af752263fb7a4602a3c1 100644 (file)
@@ -490,13 +490,16 @@ fn eq(&self, other: &Uuid) -> bool {
 impl TotalEq for Uuid {}
 
 // FIXME #9845: Test these more thoroughly
+// FIXME: remove stage0 Encodable/Decodable after snapshot
+#[cfg(stage0)]
 impl<T: Encoder> Encodable<T> for Uuid {
     /// Encode a UUID as a hypenated string
     fn encode(&self, e: &mut T) {
-        e.emit_str(self.to_hyphenated_str());
+        e.emit_str(self.to_hyphenated_str())
     }
 }
 
+#[cfg(stage0)]
 impl<T: Decoder> Decodable<T> for Uuid {
     /// Decode a UUID from a string
     fn decode(d: &mut T) -> Uuid {
@@ -504,6 +507,22 @@ fn decode(d: &mut T) -> Uuid {
     }
 }
 
+#[cfg(not(stage0))]
+impl<T: Encoder<E>, E> Encodable<T, E> for Uuid {
+    /// Encode a UUID as a hypenated string
+    fn encode(&self, e: &mut T) -> Result<(), E> {
+        e.emit_str(self.to_hyphenated_str())
+    }
+}
+
+#[cfg(not(stage0))]
+impl<T: Decoder<E>, E> Decodable<T, E> for Uuid {
+    /// Decode a UUID from a string
+    fn decode(d: &mut T) -> Result<Uuid, E> {
+        Ok(from_str(try!(d.read_str())).unwrap())
+    }
+}
+
 /// Generates a random instance of UUID (V4 conformant)
 impl rand::Rand for Uuid {
     #[inline]
@@ -528,6 +547,17 @@ mod test {
     use std::str;
     use std::io::MemWriter;
 
+    // FIXME: remove unwrap_ after snapshot
+    #[cfg(stage0)]
+    fn unwrap_<T>(t: T) -> T {
+        t
+    }
+
+    #[cfg(not(stage0))]
+    fn unwrap_<T, E>(t: Result<T, E>) -> T {
+        t.unwrap()
+    }
+
     #[test]
     fn test_nil() {
         let nil = Uuid::nil();
@@ -797,9 +827,9 @@ fn test_serialize_round_trip() {
 
         let u = Uuid::new_v4();
         let mut wr = MemWriter::new();
-        u.encode(&mut ebml::writer::Encoder(&mut wr));
+        let _ = u.encode(&mut ebml::writer::Encoder(&mut wr));
         let doc = ebml::reader::Doc(wr.get_ref());
-        let u2 = Decodable::decode(&mut ebml::reader::Decoder(doc));
+        let u2 = unwrap_(Decodable::decode(&mut ebml::reader::Decoder(doc)));
         assert_eq!(u, u2);
     }
 
index 3e5134720276d29733fabc2851fe0ef4ca001b76..a049279c5c40b4d21851a605d80728e71f315ab0 100644 (file)
@@ -203,7 +203,7 @@ fn load(&mut self) {
                                     self.db_filename.display(), e.to_str()),
                     Ok(r) => {
                         let mut decoder = json::Decoder::new(r);
-                        self.db_cache = Decodable::decode(&mut decoder);
+                        self.db_cache = Decodable::decode(&mut decoder).unwrap();
                     }
                 }
             }
@@ -252,19 +252,19 @@ enum Work<'a, T> {
     WorkFromTask(&'a Prep<'a>, Receiver<(Exec, T)>),
 }
 
-fn json_encode<'a, T:Encodable<json::Encoder<'a>>>(t: &T) -> ~str {
+fn json_encode<'a, T:Encodable<json::Encoder<'a>, io::IoError>>(t: &T) -> ~str {
     let mut writer = MemWriter::new();
     let mut encoder = json::Encoder::new(&mut writer as &mut io::Writer);
-    t.encode(&mut encoder);
+    let _ = t.encode(&mut encoder);
     str::from_utf8_owned(writer.unwrap()).unwrap()
 }
 
 // FIXME(#5121)
-fn json_decode<T:Decodable<json::Decoder>>(s: &str) -> T {
+fn json_decode<T:Decodable<json::Decoder, json::Error>>(s: &str) -> T {
     debug!("json decoding: {}", s);
     let j = json::from_str(s).unwrap();
     let mut decoder = json::Decoder::new(j);
-    Decodable::decode(&mut decoder)
+    Decodable::decode(&mut decoder).unwrap()
 }
 
 impl Context {
@@ -392,15 +392,15 @@ fn all_fresh(&self, cat: &str, map: &WorkMap) -> bool {
     }
 
     pub fn exec<'a, T:Send +
-        Encodable<json::Encoder<'a>> +
-        Decodable<json::Decoder>>(
+        Encodable<json::Encoder<'a>, io::IoError> +
+        Decodable<json::Decoder, json::Error>>(
             &'a self, blk: proc:Send(&mut Exec) -> T) -> T {
         self.exec_work(blk).unwrap()
     }
 
     fn exec_work<'a, T:Send +
-        Encodable<json::Encoder<'a>> +
-        Decodable<json::Decoder>>( // FIXME(#5121)
+        Encodable<json::Encoder<'a>, io::IoError> +
+        Decodable<json::Decoder, json::Error>>( // FIXME(#5121)
             &'a self, blk: proc:Send(&mut Exec) -> T) -> Work<'a, T> {
         let mut bo = Some(blk);
 
@@ -443,8 +443,8 @@ fn exec_work<'a, T:Send +
 }
 
 impl<'a, T:Send +
-       Encodable<json::Encoder<'a>> +
-       Decodable<json::Decoder>>
+       Encodable<json::Encoder<'a>, io::IoError> +
+       Decodable<json::Decoder, json::Error>>
     Work<'a, T> { // FIXME(#5121)
 
     pub fn from_value(elt: T) -> Work<'a, T> {
index 4b9a23538620473d52c5b5b26ca9954031bb41ba..7f72850aaaf4fbfd00e3e1dd835eccc1a474e403 100644 (file)
 
 use serialize::{json, Decodable};
 
-trait JD : Decodable<json::Decoder> { }
+trait JD : Decodable<json::Decoder, json::Error> { }
 
 fn exec<T: JD>() {
     let doc = json::from_str("").unwrap();
     let mut decoder = json::Decoder::new(doc);
-    let _v: T = Decodable::decode(&mut decoder);
+    let _v: T = Decodable::decode(&mut decoder).unwrap();
     fail!()
 }
 
index 1033b953305d58fa4821d60a25189eccfe58c8ae..72efd25251264ff18c7db5d9c6f0fd53728a60b1 100644 (file)
@@ -20,5 +20,5 @@
 pub fn main() {
     let json = json::from_str("[1]").unwrap();
     let mut decoder = json::Decoder::new(json);
-    let _x: Vec<int> = Decodable::decode(&mut decoder);
+    let _x: Vec<int> = Decodable::decode(&mut decoder).unwrap();
 }