diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 9ee0bb4a107..610764f17ad 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -168,6 +168,18 @@ impl Input { } } +// FIXME: remove unwrap_ after snapshot +#[cfg(stage0)] +fn unwrap_(t: T) -> T { + t +} + +#[cfg(not(stage0))] +fn unwrap_(r: Result) -> 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) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 0ea47d28551..f61e85f3f3f 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -47,6 +47,17 @@ use syntax::crateid::CrateId; pub type Cmd = @crate_metadata; +// FIXME: remove unwrap_ after a snapshot +#[cfg(stage0)] +fn unwrap_(t: T) -> T { + t +} + +#[cfg(not(stage0))] +fn unwrap_(r: Result) -> 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, diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index be1a7abe51d..5b47f1f5621 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -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 { 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], index: @RefCell> >, @@ -378,7 +385,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext, } } -fn encode_path + Clone>(ebml_w: &mut writer::Encoder, +fn encode_path + 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 + 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_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::Explic } } -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) { 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> { @@ -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> >, @@ -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> >, 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> >) { index.borrow_mut().push(entry { val: item.id as i64, @@ -1211,7 +1218,7 @@ fn encode_info_for_item(ecx: &EncodeContext, } fn encode_info_for_foreign_item(ecx: &EncodeContext, - ebml_w: &mut writer::Encoder, + ebml_w: &mut Encoder, nitem: &ForeignItem, index: @RefCell> >, 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> >) { 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> >) { // 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> >, } @@ -1313,7 +1320,7 @@ impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> { } fn encode_info_for_items(ecx: &EncodeContext, - ebml_w: &mut writer::Encoder, + ebml_w: &mut Encoder, krate: &Crate) -> Vec> { let index = @RefCell::new(Vec::new()); @@ -1369,7 +1376,7 @@ fn create_index( } fn encode_index( - ebml_w: &mut writer::Encoder, + ebml_w: &mut Encoder, buckets: Vec<@Vec> > , 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_crate_attrs(ecx: &EncodeContext, 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 { // Pull the cnums and name,vers,hash out of cstore let mut deps = Vec::new(); @@ -1518,7 +1525,7 @@ fn encode_crate_deps(ebml_w: &mut writer::Encoder, cstore: &cstore::CStore) { 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 @@ impl<'a, 'b> Visitor<()> for MacroDefVisitor<'a, 'b> { 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 @@ impl<'a,'b> Visitor<()> for ImplVisitor<'a,'b> { /// * 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(); diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 94947b95cd3..fd72a5f838a 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -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::libc; 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 +} + +#[cfg(not(stage0))] +fn unwrap_(r: Result) -> T { + r.unwrap() +} + +#[cfg(stage0)] +fn wrap_(t: T) -> T { + t +} + +#[cfg(not(stage0))] +fn wrap_(t: T) -> Result { + 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 def_id_encoder_helpers for S { fn emit_def_id(&mut self, did: ast::DefId) { did.encode(self) } } +#[cfg(not(stage0))] +impl, 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 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, 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 @@ impl def_id_decoder_helpers for D { // 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 @@ impl tr for 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 @@ trait ebml_decoder_helper { 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 @@ trait capture_var_helper { 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 @@ impl tr for 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 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> { 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 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> { 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 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> { 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 @@ trait ebml_writer_helpers { 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 @@ impl<'a> ebml_writer_helpers for writer::Encoder<'a> { 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 @@ impl<'a> ebml_writer_helpers for writer::Encoder<'a> { 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 @@ impl<'a> ebml_writer_helpers for writer::Encoder<'a> { 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 @@ impl<'a,'b> ast_util::IdVisitingOperation for 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 @@ trait ebml_decoder_decoder_helpers { 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 { - 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 @@ impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> { // 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 @@ impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> { 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 @@ impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> { } fn read_tys(&mut self, xcx: &ExtendedDecodeContext) -> Vec { - 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 = - 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 @@ impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> { 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)] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 6fcd1f83cf4..38b3901a0ee 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -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 +} + +#[cfg(not(stage0))] +fn unwrap_(r: Result) -> 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 { @@ -352,7 +363,7 @@ fn json_input(input: &str) -> Result { 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 , 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() }; diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index bb823c2d8ca..8631fef5168 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -20,272 +20,294 @@ use collections::{DList, RingBuf, TreeMap, TreeSet, Deque, HashMap, HashSet, use collections::enum_set::{EnumSet, CLike}; impl< - S: Encoder, - T: Encodable -> Encodable for DList { - fn encode(&self, s: &mut S) { + E, + S: Encoder, + T: Encodable +> Encodable for DList { + 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> Decodable for DList { - fn decode(d: &mut D) -> DList { - let mut list = DList::new(); +impl,T:Decodable> Decodable for DList { + fn decode(d: &mut D) -> Result, 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 - } -} - -impl< - S: Encoder, - T: Encodable -> Encodable for RingBuf { - 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)); + list.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d)))); } + Ok(list) }) } } -impl> Decodable for RingBuf { - fn decode(d: &mut D) -> RingBuf { - 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))); +impl< + E, + S: Encoder, + T: Encodable +> Encodable for RingBuf { + fn encode(&self, s: &mut S) -> Result<(), E> { + s.emit_seq(self.len(), |s| { + for (i, e) in self.iter().enumerate() { + try!(s.emit_seq_elt(i, |s| e.encode(s))); } - }); - deque + Ok(()) + }) + } +} + +impl,T:Decodable> Decodable for RingBuf { + fn decode(d: &mut D) -> Result, E> { + d.read_seq(|d, len| { + let mut deque: RingBuf = RingBuf::new(); + for i in range(0u, len) { + deque.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d)))); + } + Ok(deque) + }) } } impl< - E: Encoder, - K: Encodable + Eq + TotalOrd, - V: Encodable + Eq -> Encodable for TreeMap { - fn encode(&self, e: &mut E) { + E, + S: Encoder, + K: Encodable + Eq + TotalOrd, + V: Encodable + Eq +> Encodable for TreeMap { + 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 + Eq + TotalOrd, - V: Decodable + Eq -> Decodable for TreeMap { - fn decode(d: &mut D) -> TreeMap { + E, + D: Decoder, + K: Decodable + Eq + TotalOrd, + V: Decodable + Eq +> Decodable for TreeMap { + fn decode(d: &mut D) -> Result, 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 + Eq + TotalOrd -> Encodable for TreeSet { - fn encode(&self, s: &mut S) { + E, + S: Encoder, + T: Encodable + Eq + TotalOrd +> Encodable for TreeSet { + 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 + Eq + TotalOrd -> Decodable for TreeSet { - fn decode(d: &mut D) -> TreeSet { + E, + D: Decoder, + T: Decodable + Eq + TotalOrd +> Decodable for TreeSet { + fn decode(d: &mut D) -> Result, 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 + CLike -> Encodable for EnumSet { - fn encode(&self, s: &mut S) { + E, + S: Encoder, + T: Encodable + CLike +> Encodable for EnumSet { + 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 + CLike -> Decodable for EnumSet { - fn decode(d: &mut D) -> EnumSet { - let bits = d.read_uint(); + E, + D: Decoder, + T: Decodable + CLike +> Decodable for EnumSet { + fn decode(d: &mut D) -> Result, 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 + Hash + TotalEq, - V: Encodable, - S, - H: Hasher -> Encodable for HashMap { - fn encode(&self, e: &mut E) { + E, + S: Encoder, + K: Encodable + Hash + TotalEq, + V: Encodable, + X, + H: Hasher +> Encodable for HashMap { + 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 + Hash + TotalEq, - V: Decodable, + E, + D: Decoder, + K: Decodable + Hash + TotalEq, + V: Decodable, S, H: Hasher + Default -> Decodable for HashMap { - fn decode(d: &mut D) -> HashMap { +> Decodable for HashMap { + fn decode(d: &mut D) -> Result, 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 + Hash + TotalEq, - S, - H: Hasher -> Encodable for HashSet { - fn encode(&self, s: &mut E) { + E, + S: Encoder, + T: Encodable + Hash + TotalEq, + X, + H: Hasher +> Encodable for HashSet { + 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 + Hash + TotalEq, + E, + D: Decoder, + T: Decodable + Hash + TotalEq, S, H: Hasher + Default -> Decodable for HashSet { - fn decode(d: &mut D) -> HashSet { +> Decodable for HashSet { + fn decode(d: &mut D) -> Result, 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 -> Encodable for TrieMap { - fn encode(&self, e: &mut E) { + E, + S: Encoder, + V: Encodable +> Encodable for TrieMap { + 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)); - } - }); - } -} - -impl< - D: Decoder, - V: Decodable -> Decodable for TrieMap { - fn decode(d: &mut D) -> TrieMap { - 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 Encodable 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)); + try!(e.emit_map_elt_key(i, |e| key.encode(e))); + try!(e.emit_map_elt_val(i, |e| val.encode(e))); } + Ok(()) }) } } -impl Decodable for TrieSet { - fn decode(d: &mut D) -> TrieSet { - d.read_seq(|d, len| { - let mut set = TrieSet::new(); +impl< + E, + D: Decoder, + V: Decodable +> Decodable for TrieMap { + fn decode(d: &mut D) -> Result, E> { + d.read_map(|d, len| { + let mut map = TrieMap::new(); for i in range(0u, len) { - set.insert(d.read_seq_elt(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); } - set + Ok(map) + }) + } +} + +impl> Encodable for TrieSet { + fn encode(&self, s: &mut S) -> Result<(), E> { + s.emit_seq(self.len(), |s| { + for (i, e) in self.iter().enumerate() { + try!(s.emit_seq_elt(i, |s| e.encode(s))); + } + Ok(()) + }) + } +} + +impl> Decodable for TrieSet { + fn decode(d: &mut D) -> Result { + d.read_seq(|d, len| { + let mut set = TrieSet::new(); + for i in range(0u, len) { + set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d)))); + } + Ok(set) }) } } diff --git a/src/libserialize/collection_impls_old.rs b/src/libserialize/collection_impls_old.rs new file mode 100644 index 00000000000..5994fbc5d10 --- /dev/null +++ b/src/libserialize/collection_impls_old.rs @@ -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 or the MIT license +// , 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 +> Encodable for DList { + 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> Decodable for DList { + fn decode(d: &mut D) -> DList { + 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 +> Encodable for RingBuf { + 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> Decodable for RingBuf { + fn decode(d: &mut D) -> RingBuf { + 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 + Eq + TotalOrd, + V: Encodable + Eq +> Encodable for TreeMap { + 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 + Eq + TotalOrd, + V: Decodable + Eq +> Decodable for TreeMap { + fn decode(d: &mut D) -> TreeMap { + 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 + Eq + TotalOrd +> Encodable for TreeSet { + 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 + Eq + TotalOrd +> Decodable for TreeSet { + fn decode(d: &mut D) -> TreeSet { + 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 + CLike +> Encodable for EnumSet { + 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 + CLike +> Decodable for EnumSet { + fn decode(d: &mut D) -> EnumSet { + 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 + Hash + TotalEq, + V: Encodable, + S, + H: Hasher +> Encodable for HashMap { + 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 + Hash + TotalEq, + V: Decodable, + S, + H: Hasher + Default +> Decodable for HashMap { + fn decode(d: &mut D) -> HashMap { + 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 + Hash + TotalEq, + S, + H: Hasher +> Encodable for HashSet { + 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 + Hash + TotalEq, + S, + H: Hasher + Default +> Decodable for HashSet { + fn decode(d: &mut D) -> HashSet { + 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 +> Encodable for TrieMap { + 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 +> Decodable for TrieMap { + fn decode(d: &mut D) -> TrieMap { + 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 Encodable 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 Decodable 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 + }) + } +} + diff --git a/src/libserialize/ebml.rs b/src/libserialize/ebml.rs index 2b416f263c2..cc2385665a2 100644 --- a/src/libserialize/ebml.rs +++ b/src/libserialize/ebml.rs @@ -10,12 +10,9 @@ #[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 = Result; // 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 { 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 { use std::mem::from_be32; if data.len() - start < 4 { @@ -166,10 +184,10 @@ pub mod reader { 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 mod reader { 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> { + 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> { 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 mod reader { 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 mod reader { 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 mod reader { } 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> { 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 @@ pub mod reader { 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(&mut self, exp_tag: EbmlEncoderTag, - f: |&mut Decoder<'doc>| -> T) -> T { - let d = self.next_doc(exp_tag); + f: |&mut Decoder<'doc>| -> DecodeResult) -> DecodeResult { + 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 { + 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(&mut self, op: |&mut Decoder<'doc>, Doc| -> R) -> R { - let doc = self.next_doc(EsOpaque); + pub fn read_opaque(&mut self, + op: |&mut Decoder<'doc>, Doc| -> DecodeResult) -> DecodeResult { + 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 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 { Ok(doc_as_u64(try!(self.next_doc(EsU64)))) } + fn read_u32(&mut self) -> DecodeResult { Ok(doc_as_u32(try!(self.next_doc(EsU32)))) } + fn read_u16(&mut self) -> DecodeResult { Ok(doc_as_u16(try!(self.next_doc(EsU16)))) } + fn read_u8 (&mut self) -> DecodeResult { Ok(doc_as_u8 (try!(self.next_doc(EsU8 )))) } + fn read_uint(&mut self) -> DecodeResult { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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(&mut self, name: &str, f: |&mut Decoder<'doc>| -> T) -> T { + fn read_enum(&mut self, + name: &str, + f: |&mut Decoder<'doc>| -> DecodeResult) -> DecodeResult { 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(&mut self, _: &[&str], - f: |&mut Decoder<'doc>, uint| -> T) - -> T { + f: |&mut Decoder<'doc>, uint| -> DecodeResult) + -> DecodeResult { 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(&mut self, idx: uint, - f: |&mut Decoder<'doc>| -> T) -> T { + f: |&mut Decoder<'doc>| -> DecodeResult) -> DecodeResult { debug!("read_enum_variant_arg(idx={})", idx); f(self) } fn read_enum_struct_variant(&mut self, _: &[&str], - f: |&mut Decoder<'doc>, uint| -> T) - -> T { + f: |&mut Decoder<'doc>, uint| -> DecodeResult) + -> DecodeResult { 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(&mut self, name: &str, idx: uint, - f: |&mut Decoder<'doc>| -> T) - -> T { + f: |&mut Decoder<'doc>| -> DecodeResult) + -> DecodeResult { debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx); f(self) } @@ -494,8 +518,8 @@ pub mod reader { fn read_struct(&mut self, name: &str, _: uint, - f: |&mut Decoder<'doc>| -> T) - -> T { + f: |&mut Decoder<'doc>| -> DecodeResult) + -> DecodeResult { debug!("read_struct(name={})", name); f(self) } @@ -503,85 +527,89 @@ pub mod reader { fn read_struct_field(&mut self, name: &str, idx: uint, - f: |&mut Decoder<'doc>| -> T) - -> T { + f: |&mut Decoder<'doc>| -> DecodeResult) + -> DecodeResult { debug!("read_struct_field(name={}, idx={})", name, idx); - self._check_label(name); + try!(self._check_label(name)); f(self) } - fn read_tuple(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T { + fn read_tuple(&mut self, + f: |&mut Decoder<'doc>, uint| -> DecodeResult) -> DecodeResult { debug!("read_tuple()"); self.read_seq(f) } - fn read_tuple_arg(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T) - -> T { + fn read_tuple_arg(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult) + -> DecodeResult { debug!("read_tuple_arg(idx={})", idx); self.read_seq_elt(idx, f) } fn read_tuple_struct(&mut self, name: &str, - f: |&mut Decoder<'doc>, uint| -> T) - -> T { + f: |&mut Decoder<'doc>, uint| -> DecodeResult) + -> DecodeResult { debug!("read_tuple_struct(name={})", name); self.read_tuple(f) } fn read_tuple_struct_arg(&mut self, idx: uint, - f: |&mut Decoder<'doc>| -> T) - -> T { + f: |&mut Decoder<'doc>| -> DecodeResult) + -> DecodeResult { debug!("read_tuple_struct_arg(idx={})", idx); self.read_tuple_arg(idx, f) } - fn read_option(&mut self, f: |&mut Decoder<'doc>, bool| -> T) -> T { + fn read_option(&mut self, + f: |&mut Decoder<'doc>, bool| -> DecodeResult) -> DecodeResult { 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(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T { + fn read_seq(&mut self, + f: |&mut Decoder<'doc>, uint| -> DecodeResult) -> DecodeResult { 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(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T) - -> T { + fn read_seq_elt(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult) + -> DecodeResult { debug!("read_seq_elt(idx={})", idx); self.push_doc(EsVecElt, f) } - fn read_map(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T { + fn read_map(&mut self, + f: |&mut Decoder<'doc>, uint| -> DecodeResult) -> DecodeResult { 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(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T) - -> T { + fn read_map_elt_key(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult) + -> DecodeResult { debug!("read_map_elt_key(idx={})", idx); self.push_doc(EsMapKey, f) } - fn read_map_elt_val(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T) - -> T { + fn read_map_elt_val(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult) + -> DecodeResult { 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: &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 @@ pub mod writer { 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: &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 mod writer { // 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 @@ pub mod writer { // 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| -> 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) {} - - 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); + impl<'a, W: Writer + Seek> serialize::Encoder for Encoder<'a, W> { + fn emit_nil(&mut self) -> EncodeResult { + Ok(()) } - fn emit_int(&mut self, v: int) { - self.wr_tagged_i64(EsInt as uint, v as i64); + fn emit_uint(&mut self, v: uint) -> EncodeResult { + self.wr_tagged_u64(EsUint as uint, v as u64) } - fn emit_i64(&mut self, v: i64) { - self.wr_tagged_i64(EsI64 as uint, v); + fn emit_u64(&mut self, v: u64) -> EncodeResult { + self.wr_tagged_u64(EsU64 as uint, v) } - fn emit_i32(&mut self, v: i32) { - self.wr_tagged_i32(EsI32 as uint, v); + fn emit_u32(&mut self, v: u32) -> EncodeResult { + self.wr_tagged_u32(EsU32 as uint, v) } - fn emit_i16(&mut self, v: i16) { - self.wr_tagged_i16(EsI16 as uint, v); + fn emit_u16(&mut self, v: u16) -> EncodeResult { + self.wr_tagged_u16(EsU16 as uint, v) } - fn emit_i8(&mut self, v: i8) { - self.wr_tagged_i8(EsI8 as uint, v); + fn emit_u8(&mut self, v: u8) -> EncodeResult { + self.wr_tagged_u8(EsU8 as uint, v) } - fn emit_bool(&mut self, v: bool) { + 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) -> EncodeResult { + self.wr_tagged_i64(EsI64 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) -> EncodeResult { + self.wr_tagged_i16(EsI16 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) -> 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 @@ pub mod writer { 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 @@ mod tests { 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 @@ mod tests { 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 @@ mod bench { 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 @@ mod bench { 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 @@ mod bench { 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 @@ mod bench { 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 index 00000000000..1c66960672f --- /dev/null +++ b/src/libserialize/ebml_old.rs @@ -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 or the MIT license +// , 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> { + 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(&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(&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(&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(&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(&mut self, + idx: uint, + f: |&mut Decoder<'doc>| -> T) -> T { + debug!("read_enum_variant_arg(idx={})", idx); + f(self) + } + + fn read_enum_struct_variant(&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(&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(&mut self, + name: &str, + _: uint, + f: |&mut Decoder<'doc>| -> T) + -> T { + debug!("read_struct(name={})", name); + f(self) + } + + fn read_struct_field(&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(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T { + debug!("read_tuple()"); + self.read_seq(f) + } + + fn read_tuple_arg(&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(&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(&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(&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(&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(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T) + -> T { + debug!("read_seq_elt(idx={})", idx); + self.push_doc(EsVecElt, f) + } + + fn read_map(&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(&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(&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) { + 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; + } + }); + } +} + diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index c52cfb1e35d..f2bdef445bd 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -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 @@ 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 { @@ -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 = Result; 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>>(to_encode_object: &T) -> ~[u8] { + pub fn buffer_encode, 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>>(to_encode_object: &T) -> ~str { + pub fn str_encode, 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 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>|) { - 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>|) { + fn emit_enum_variant_arg(&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>|) { - try!(write!(self.wr, r"\{")); - f(self); - try!(write!(self.wr, r"\}")); + fn emit_enum_struct_variant(&mut self, + name: &str, + id: uint, + cnt: uint, + f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult { + self.emit_enum_variant(name, id, cnt, f) } - fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Encoder<'a>|) { + fn emit_enum_struct_variant_field(&mut self, + _: &str, + idx: uint, + f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult { + self.emit_enum_variant_arg(idx, f) + } + + fn emit_struct(&mut self, + _: &str, + _: uint, + f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult { + 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>| -> EncodeResult) -> EncodeResult { + 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>| -> EncodeResult) -> EncodeResult { + self.emit_seq(len, f) + } + 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>| -> EncodeResult) -> EncodeResult { + self.emit_seq(len, f) + } + 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>| -> 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>| -> EncodeResult) -> EncodeResult { + try!(write!(self.wr, "[")); + try!(f(self)); + write!(self.wr, "]") + } + + 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>| -> EncodeResult) -> EncodeResult { + 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>| -> 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 @@ impl<'a> ::Encoder for 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 @@ impl<'a> 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 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 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { 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 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { 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 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { 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 @@ impl<'a> ::Encoder for 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 @@ impl<'a> ::Encoder for 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 Encodable for Json { - fn encode(&self, e: &mut E) { +impl> Encodable 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 @@ impl Encodable for Json { 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 @@ impl> Parser { } impl> Parser { - pub fn parse(&mut self) -> Result { + pub fn parse(&mut self) -> DecodeResult { match self.parse_value() { Ok(value) => { // Skip trailing whitespaces. @@ -927,11 +959,11 @@ impl> Parser { self.ch == Some(c) } - fn error(&self, msg: ~str) -> Result { - Err(Error { line: self.line, col: self.col, msg: msg }) + fn error(&self, msg: ~str) -> DecodeResult { + Err(ParseError(msg, self.line, self.col)) } - fn parse_value(&mut self) -> Result { + fn parse_value(&mut self) -> DecodeResult { self.parse_whitespace(); if self.eof() { return self.error(~"EOF while parsing value"); } @@ -960,7 +992,7 @@ impl> Parser { self.ch_is('\r') { self.bump(); } } - fn parse_ident(&mut self, ident: &str, value: Json) -> Result { + fn parse_ident(&mut self, ident: &str, value: Json) -> DecodeResult { if ident.chars().all(|c| Some(c) == self.next_char()) { self.bump(); Ok(value) @@ -969,7 +1001,7 @@ impl> Parser { } } - fn parse_number(&mut self) -> Result { + fn parse_number(&mut self) -> DecodeResult { let mut neg = 1.0; if self.ch_is('-') { @@ -999,7 +1031,7 @@ impl> Parser { Ok(Number(neg * res)) } - fn parse_integer(&mut self) -> Result { + fn parse_integer(&mut self) -> DecodeResult { let mut res = 0.0; match self.ch_or_null() { @@ -1030,7 +1062,7 @@ impl> Parser { Ok(res) } - fn parse_decimal(&mut self, res: f64) -> Result { + fn parse_decimal(&mut self, res: f64) -> DecodeResult { self.bump(); // Make sure a digit follows the decimal place. @@ -1056,7 +1088,7 @@ impl> Parser { Ok(res) } - fn parse_exponent(&mut self, mut res: f64) -> Result { + fn parse_exponent(&mut self, mut res: f64) -> DecodeResult { self.bump(); let mut exp = 0u; @@ -1096,7 +1128,7 @@ impl> Parser { 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 @@ impl> Parser { } } - fn parse_list(&mut self) -> Result { + fn parse_list(&mut self) -> DecodeResult { self.bump(); self.parse_whitespace(); @@ -1193,7 +1225,7 @@ impl> Parser { }; } - fn parse_object(&mut self) -> Result { + fn parse_object(&mut self) -> DecodeResult { self.bump(); self.parse_whitespace(); @@ -1245,21 +1277,21 @@ impl> Parser { } /// Decodes a json value from an `&mut io::Reader` -pub fn from_reader(rdr: &mut io::Reader) -> Result { +pub fn from_reader(rdr: &mut io::Reader) -> DecodeResult { 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 { +pub fn from_str(s: &str) -> DecodeResult { let mut parser = Parser::new(s.chars()); parser.parse() } @@ -1279,110 +1311,103 @@ impl 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) -> () { +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 for Decoder { + fn read_nil(&mut self) -> DecodeResult<()> { debug!("read_nil"); - match self.stack.pop().unwrap() { - Null => (), - value => self.expected("null", &value) - } + 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 { Ok(try!(self.read_f64()) as u64) } + fn read_u32(&mut self) -> DecodeResult { Ok(try!(self.read_f64()) as u32) } + fn read_u16(&mut self) -> DecodeResult { Ok(try!(self.read_f64()) as u16) } + fn read_u8 (&mut self) -> DecodeResult { Ok(try!(self.read_f64()) as u8) } + fn read_uint(&mut self) -> DecodeResult { 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 { Ok(try!(self.read_f64()) as i64) } + fn read_i32(&mut self) -> DecodeResult { Ok(try!(self.read_f64()) as i32) } + fn read_i16(&mut self) -> DecodeResult { Ok(try!(self.read_f64()) as i16) } + fn read_i8 (&mut self) -> DecodeResult { Ok(try!(self.read_f64()) as i8) } + fn read_int(&mut self) -> DecodeResult { Ok(try!(self.read_f64()) as int) } - fn read_bool(&mut self) -> bool { + fn read_bool(&mut self) -> DecodeResult { 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 { 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 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 { Ok(try!(self.read_f64()) as f32) } - fn read_char(&mut self) -> char { - let s = self.read_str(); + fn read_char(&mut self) -> DecodeResult { + 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(&mut self, name: &str, f: |&mut Decoder| -> T) -> T { + fn read_enum(&mut self, + name: &str, + f: |&mut Decoder| -> DecodeResult) -> DecodeResult { debug!("read_enum({})", name); f(self) } fn read_enum_variant(&mut self, names: &[&str], - f: |&mut Decoder, uint| -> T) - -> T { + f: |&mut Decoder, uint| -> DecodeResult) + -> DecodeResult { 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 @@ impl ::Decoder for Decoder { 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(&mut self, idx: uint, f: |&mut Decoder| -> T) - -> T { + fn read_enum_variant_arg(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult) + -> DecodeResult { debug!("read_enum_variant_arg(idx={})", idx); f(self) } fn read_enum_struct_variant(&mut self, names: &[&str], - f: |&mut Decoder, uint| -> T) - -> T { + f: |&mut Decoder, uint| -> DecodeResult) + -> DecodeResult { debug!("read_enum_struct_variant(names={:?})", names); self.read_enum_variant(names, f) } @@ -1428,8 +1447,8 @@ impl ::Decoder for Decoder { fn read_enum_struct_variant_field(&mut self, name: &str, idx: uint, - f: |&mut Decoder| -> T) - -> T { + f: |&mut Decoder| -> DecodeResult) + -> DecodeResult { debug!("read_enum_struct_variant_field(name={}, idx={})", name, idx); self.read_enum_variant_arg(idx, f) } @@ -1437,113 +1456,104 @@ impl ::Decoder for Decoder { fn read_struct(&mut self, name: &str, len: uint, - f: |&mut Decoder| -> T) - -> T { + f: |&mut Decoder| -> DecodeResult) + -> DecodeResult { 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(&mut self, name: &str, idx: uint, - f: |&mut Decoder| -> T) - -> T { + f: |&mut Decoder| -> DecodeResult) + -> DecodeResult { 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(&mut self, f: |&mut Decoder, uint| -> T) -> T { + fn read_tuple(&mut self, f: |&mut Decoder, uint| -> DecodeResult) -> DecodeResult { debug!("read_tuple()"); self.read_seq(f) } - fn read_tuple_arg(&mut self, idx: uint, f: |&mut Decoder| -> T) -> T { + fn read_tuple_arg(&mut self, + idx: uint, + f: |&mut Decoder| -> DecodeResult) -> DecodeResult { debug!("read_tuple_arg(idx={})", idx); self.read_seq_elt(idx, f) } fn read_tuple_struct(&mut self, name: &str, - f: |&mut Decoder, uint| -> T) - -> T { + f: |&mut Decoder, uint| -> DecodeResult) + -> DecodeResult { debug!("read_tuple_struct(name={})", name); self.read_tuple(f) } fn read_tuple_struct_arg(&mut self, idx: uint, - f: |&mut Decoder| -> T) - -> T { + f: |&mut Decoder| -> DecodeResult) + -> DecodeResult { debug!("read_tuple_struct_arg(idx={})", idx); self.read_tuple_arg(idx, f) } - fn read_option(&mut self, f: |&mut Decoder, bool| -> T) -> T { - match self.stack.pop().unwrap() { + fn read_option(&mut self, f: |&mut Decoder, bool| -> DecodeResult) -> DecodeResult { + match self.pop() { Null => f(self, false), value => { self.stack.push(value); f(self, true) } } } - fn read_seq(&mut self, f: |&mut Decoder, uint| -> T) -> T { + fn read_seq(&mut self, f: |&mut Decoder, uint| -> DecodeResult) -> DecodeResult { 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(&mut self, idx: uint, f: |&mut Decoder| -> T) -> T { + fn read_seq_elt(&mut self, + idx: uint, + f: |&mut Decoder| -> DecodeResult) -> DecodeResult { debug!("read_seq_elt(idx={})", idx); f(self) } - fn read_map(&mut self, f: |&mut Decoder, uint| -> T) -> T { + fn read_map(&mut self, f: |&mut Decoder, uint| -> DecodeResult) -> DecodeResult { 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(&mut self, idx: uint, f: |&mut Decoder| -> T) - -> T { + fn read_map_elt_key(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult) + -> DecodeResult { debug!("read_map_elt_key(idx={})", idx); f(self) } - fn read_map_elt_val(&mut self, idx: uint, f: |&mut Decoder| -> T) - -> T { + fn read_map_elt_val(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult) + -> DecodeResult { debug!("read_map_elt_val(idx={})", idx); f(self) } @@ -1735,17 +1745,12 @@ impl fmt::Show for Json { } } -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 @@ mod tests { 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 @@ mod tests { 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 @@ mod tests { 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 @@ mod tests { 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 @@ mod tests { #[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 @@ mod tests { #[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 @@ mod tests { #[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 @@ mod tests { #[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 @@ mod tests { #[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 @@ mod tests { ] }"; 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 @@ mod tests { #[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 @@ mod tests { 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 @@ mod tests { #[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 @@ mod tests { A(f64), B(~str) } - fn check_err>(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>(to_parse: &'static str, expected: Error) { + let res: DecodeResult = 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::("[]", "object but found list"); + check_err::("[]", ExpectedError(~"Object", ~"[]")); check_err::("{\"x\": true, \"y\": true, \"z\": \"\", \"w\": []}", - "number but found boolean"); + ExpectedError(~"Number", ~"true")); check_err::("{\"x\": 1, \"y\": [], \"z\": \"\", \"w\": []}", - "boolean but found list"); + ExpectedError(~"Boolean", ~"[]")); check_err::("{\"x\": 1, \"y\": true, \"z\": {}, \"w\": []}", - "string but found object"); + ExpectedError(~"String", ~"{}")); check_err::("{\"x\": 1, \"y\": true, \"z\": \"\", \"w\": null}", - "list but found null"); + ExpectedError(~"List", ~"null")); check_err::("{\"x\": 1, \"y\": true, \"z\": \"\"}", - "'w' field in object"); + MissingFieldError(~"w")); } #[test] fn test_decode_errors_enum() { check_err::("{}", - "'variant' field in object"); + MissingFieldError(~"variant")); check_err::("{\"variant\": 1}", - "string but found number"); + ExpectedError(~"String", ~"1")); check_err::("{\"variant\": \"A\"}", - "'fields' field in object"); + MissingFieldError(~"fields")); check_err::("{\"variant\": \"A\", \"fields\": null}", - "list but found null"); + ExpectedError(~"List", ~"null")); check_err::("{\"variant\": \"C\", \"fields\": []}", - "unknown variant name"); + UnknownVariantError(~"C")); } #[test] @@ -2561,7 +2525,7 @@ mod tests { 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 @@ mod tests { 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 @@ mod tests { Ok(o) => o }; let mut decoder = Decoder::new(json_obj); - let _hm: HashMap = Decodable::decode(&mut decoder); + let _hm: HashMap = Decodable::decode(&mut decoder).unwrap(); } } diff --git a/src/libserialize/json_old.rs b/src/libserialize/json_old.rs new file mode 100644 index 00000000000..cc4c86599fa --- /dev/null +++ b/src/libserialize/json_old.rs @@ -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 or the MIT license +// , 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>>(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>>(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 Encodable 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 { + 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 { + 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 { + priv rdr: T, + priv ch: Option, + priv line: uint, + priv col: uint, +} + +impl> Parser { + /// Decode a json value from an Iterator + pub fn new(rdr: T) -> Parser { + let mut p = Parser { + rdr: rdr, + ch: Some('\x00'), + line: 1, + col: 0, + }; + p.bump(); + p + } +} + +impl> Parser { + pub fn parse(&mut self) -> Result { + 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> Parser { + 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 { + self.bump(); + self.ch + } + fn ch_is(&self, c: char) -> bool { + self.ch == Some(c) + } + + fn error(&self, msg: ~str) -> Result { + Err(Error { line: self.line, col: self.col, msg: msg }) + } + + fn parse_value(&mut self) -> Result { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 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(&mut self, name: &str, f: |&mut Decoder| -> T) -> T { + debug!("read_enum({})", name); + f(self) + } + + fn read_enum_variant(&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(&mut self, idx: uint, f: |&mut Decoder| -> T) + -> T { + debug!("read_enum_variant_arg(idx={})", idx); + f(self) + } + + fn read_enum_struct_variant(&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(&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(&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(&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(&mut self, f: |&mut Decoder, uint| -> T) -> T { + debug!("read_tuple()"); + self.read_seq(f) + } + + fn read_tuple_arg(&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(&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(&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(&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(&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(&mut self, idx: uint, f: |&mut Decoder| -> T) -> T { + debug!("read_seq_elt(idx={})", idx); + f(self) + } + + fn read_map(&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(&mut self, idx: uint, f: |&mut Decoder| -> T) + -> T { + debug!("read_map_elt_key(idx={})", idx); + f(self) + } + + fn read_map_elt_val(&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 ToJson for (A, B) { + fn to_json(&self) -> Json { + match *self { + (ref a, ref b) => { + List(~[a.to_json(), b.to_json()]) + } + } + } +} + +impl 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 ToJson for ~[A] { + fn to_json(&self) -> Json { List(self.map(|elt| elt.to_json())) } +} + +impl 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 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 ToJson for Option { + 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>(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::("[]", "object but found list"); + check_err::("{\"x\": true, \"y\": true, \"z\": \"\", \"w\": []}", + "number but found boolean"); + check_err::("{\"x\": 1, \"y\": [], \"z\": \"\", \"w\": []}", + "boolean but found list"); + check_err::("{\"x\": 1, \"y\": true, \"z\": {}, \"w\": []}", + "string but found object"); + check_err::("{\"x\": 1, \"y\": true, \"z\": \"\", \"w\": null}", + "list but found null"); + check_err::("{\"x\": 1, \"y\": true, \"z\": \"\"}", + "'w' field in object"); + } + #[test] + fn test_decode_errors_enum() { + check_err::("{}", + "'variant' field in object"); + check_err::("{\"variant\": 1}", + "string but found number"); + check_err::("{\"variant\": \"A\"}", + "'fields' field in object"); + check_err::("{\"variant\": \"A\", \"fields\": null}", + "list but found null"); + check_err::("{\"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 = 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 = 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 = Decodable::decode(&mut decoder); + } +} + diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 8a5829da9d6..86e03aae673 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -34,10 +34,31 @@ extern crate collections; 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; diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index a65443653cc..6cda8d9ffb5 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -18,444 +18,465 @@ use std::path; use std::rc::Rc; use std::slice; -pub trait Encoder { +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); + 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 { // 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; + fn read_u64(&mut self) -> Result; + fn read_u32(&mut self) -> Result; + fn read_u16(&mut self) -> Result; + fn read_u8(&mut self) -> Result; + fn read_int(&mut self) -> Result; + fn read_i64(&mut self) -> Result; + fn read_i32(&mut self) -> Result; + fn read_i16(&mut self) -> Result; + fn read_i8(&mut self) -> Result; + fn read_bool(&mut self) -> Result; + fn read_f64(&mut self) -> Result; + fn read_f32(&mut self) -> Result; + fn read_char(&mut self) -> Result; + fn read_str(&mut self) -> Result<~str, E>; // Compound types: - fn read_enum(&mut self, name: &str, f: |&mut Self| -> T) -> T; + fn read_enum(&mut self, name: &str, f: |&mut Self| -> Result) -> Result; fn read_enum_variant(&mut self, names: &[&str], - f: |&mut Self, uint| -> T) - -> T; + f: |&mut Self, uint| -> Result) + -> Result; fn read_enum_variant_arg(&mut self, a_idx: uint, - f: |&mut Self| -> T) - -> T; + f: |&mut Self| -> Result) + -> Result; fn read_enum_struct_variant(&mut self, names: &[&str], - f: |&mut Self, uint| -> T) - -> T; + f: |&mut Self, uint| -> Result) + -> Result; fn read_enum_struct_variant_field(&mut self, &f_name: &str, f_idx: uint, - f: |&mut Self| -> T) - -> T; + f: |&mut Self| -> Result) + -> Result; - fn read_struct(&mut self, s_name: &str, len: uint, f: |&mut Self| -> T) - -> T; + fn read_struct(&mut self, s_name: &str, len: uint, f: |&mut Self| -> Result) + -> Result; fn read_struct_field(&mut self, f_name: &str, f_idx: uint, - f: |&mut Self| -> T) - -> T; + f: |&mut Self| -> Result) + -> Result; - fn read_tuple(&mut self, f: |&mut Self, uint| -> T) -> T; - fn read_tuple_arg(&mut self, a_idx: uint, f: |&mut Self| -> T) -> T; + fn read_tuple(&mut self, f: |&mut Self, uint| -> Result) -> Result; + fn read_tuple_arg(&mut self, a_idx: uint, f: |&mut Self| -> Result) -> Result; fn read_tuple_struct(&mut self, s_name: &str, - f: |&mut Self, uint| -> T) - -> T; + f: |&mut Self, uint| -> Result) + -> Result; fn read_tuple_struct_arg(&mut self, a_idx: uint, - f: |&mut Self| -> T) - -> T; + f: |&mut Self| -> Result) + -> Result; // Specialized types: - fn read_option(&mut self, f: |&mut Self, bool| -> T) -> T; + fn read_option(&mut self, f: |&mut Self, bool| -> Result) -> Result; - fn read_seq(&mut self, f: |&mut Self, uint| -> T) -> T; - fn read_seq_elt(&mut self, idx: uint, f: |&mut Self| -> T) -> T; + fn read_seq(&mut self, f: |&mut Self, uint| -> Result) -> Result; + fn read_seq_elt(&mut self, idx: uint, f: |&mut Self| -> Result) -> Result; - fn read_map(&mut self, f: |&mut Self, uint| -> T) -> T; - fn read_map_elt_key(&mut self, idx: uint, f: |&mut Self| -> T) -> T; - fn read_map_elt_val(&mut self, idx: uint, f: |&mut Self| -> T) -> T; + fn read_map(&mut self, f: |&mut Self, uint| -> Result) -> Result; + fn read_map_elt_key(&mut self, idx: uint, f: |&mut Self| -> Result) -> Result; + fn read_map_elt_val(&mut self, idx: uint, f: |&mut Self| -> Result) -> Result; } -pub trait Encodable { - fn encode(&self, s: &mut S); +pub trait Encodable, E> { + fn encode(&self, s: &mut S) -> Result<(), E>; } -pub trait Decodable { - fn decode(d: &mut D) -> Self; +pub trait Decodable, E> { + fn decode(d: &mut D) -> Result; } -impl Encodable for uint { - fn encode(&self, s: &mut S) { +macro_rules! try ( ($e:expr) => ( + match $e { Ok(v) => v, Err(e) => return Err(e) } +)) + +impl> Encodable for uint { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_uint(*self) } } -impl Decodable for uint { - fn decode(d: &mut D) -> uint { +impl> Decodable for uint { + fn decode(d: &mut D) -> Result { d.read_uint() } } -impl Encodable for u8 { - fn encode(&self, s: &mut S) { +impl> Encodable for u8 { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_u8(*self) } } -impl Decodable for u8 { - fn decode(d: &mut D) -> u8 { +impl> Decodable for u8 { + fn decode(d: &mut D) -> Result { d.read_u8() } } -impl Encodable for u16 { - fn encode(&self, s: &mut S) { +impl> Encodable for u16 { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_u16(*self) } } -impl Decodable for u16 { - fn decode(d: &mut D) -> u16 { +impl> Decodable for u16 { + fn decode(d: &mut D) -> Result { d.read_u16() } } -impl Encodable for u32 { - fn encode(&self, s: &mut S) { +impl> Encodable for u32 { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_u32(*self) } } -impl Decodable for u32 { - fn decode(d: &mut D) -> u32 { +impl> Decodable for u32 { + fn decode(d: &mut D) -> Result { d.read_u32() } } -impl Encodable for u64 { - fn encode(&self, s: &mut S) { +impl> Encodable for u64 { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_u64(*self) } } -impl Decodable for u64 { - fn decode(d: &mut D) -> u64 { +impl> Decodable for u64 { + fn decode(d: &mut D) -> Result { d.read_u64() } } -impl Encodable for int { - fn encode(&self, s: &mut S) { +impl> Encodable for int { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_int(*self) } } -impl Decodable for int { - fn decode(d: &mut D) -> int { +impl> Decodable for int { + fn decode(d: &mut D) -> Result { d.read_int() } } -impl Encodable for i8 { - fn encode(&self, s: &mut S) { +impl> Encodable for i8 { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_i8(*self) } } -impl Decodable for i8 { - fn decode(d: &mut D) -> i8 { +impl> Decodable for i8 { + fn decode(d: &mut D) -> Result { d.read_i8() } } -impl Encodable for i16 { - fn encode(&self, s: &mut S) { +impl> Encodable for i16 { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_i16(*self) } } -impl Decodable for i16 { - fn decode(d: &mut D) -> i16 { +impl> Decodable for i16 { + fn decode(d: &mut D) -> Result { d.read_i16() } } -impl Encodable for i32 { - fn encode(&self, s: &mut S) { +impl> Encodable for i32 { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_i32(*self) } } -impl Decodable for i32 { - fn decode(d: &mut D) -> i32 { +impl> Decodable for i32 { + fn decode(d: &mut D) -> Result { d.read_i32() } } -impl Encodable for i64 { - fn encode(&self, s: &mut S) { +impl> Encodable for i64 { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_i64(*self) } } -impl Decodable for i64 { - fn decode(d: &mut D) -> i64 { +impl> Decodable for i64 { + fn decode(d: &mut D) -> Result { d.read_i64() } } -impl<'a, S:Encoder> Encodable for &'a str { - fn encode(&self, s: &mut S) { +impl<'a, E, S:Encoder> Encodable for &'a str { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_str(*self) } } -impl Encodable for ~str { - fn encode(&self, s: &mut S) { +impl> Encodable for ~str { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_str(*self) } } -impl Decodable for ~str { - fn decode(d: &mut D) -> ~str { +impl> Decodable for ~str { + fn decode(d: &mut D) -> Result<~str, E> { d.read_str() } } -impl Encodable for f32 { - fn encode(&self, s: &mut S) { +impl> Encodable for f32 { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_f32(*self) } } -impl Decodable for f32 { - fn decode(d: &mut D) -> f32 { +impl> Decodable for f32 { + fn decode(d: &mut D) -> Result { d.read_f32() } } -impl Encodable for f64 { - fn encode(&self, s: &mut S) { +impl> Encodable for f64 { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_f64(*self) } } -impl Decodable for f64 { - fn decode(d: &mut D) -> f64 { +impl> Decodable for f64 { + fn decode(d: &mut D) -> Result { d.read_f64() } } -impl Encodable for bool { - fn encode(&self, s: &mut S) { +impl> Encodable for bool { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_bool(*self) } } -impl Decodable for bool { - fn decode(d: &mut D) -> bool { +impl> Decodable for bool { + fn decode(d: &mut D) -> Result { d.read_bool() } } -impl Encodable for char { - fn encode(&self, s: &mut S) { +impl> Encodable for char { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_char(*self) } } -impl Decodable for char { - fn decode(d: &mut D) -> char { +impl> Decodable for char { + fn decode(d: &mut D) -> Result { d.read_char() } } -impl Encodable for () { - fn encode(&self, s: &mut S) { +impl> Encodable for () { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_nil() } } -impl Decodable for () { - fn decode(d: &mut D) -> () { +impl> Decodable for () { + fn decode(d: &mut D) -> Result<(), E> { d.read_nil() } } -impl<'a, S:Encoder,T:Encodable> Encodable for &'a T { - fn encode(&self, s: &mut S) { +impl<'a, E, S:Encoder,T:Encodable> Encodable for &'a T { + fn encode(&self, s: &mut S) -> Result<(), E> { (**self).encode(s) } } -impl> Encodable for ~T { - fn encode(&self, s: &mut S) { +impl,T:Encodable> Encodable for ~T { + fn encode(&self, s: &mut S) -> Result<(), E> { (**self).encode(s) } } -impl> Decodable for ~T { - fn decode(d: &mut D) -> ~T { - ~Decodable::decode(d) +impl,T:Decodable> Decodable for ~T { + fn decode(d: &mut D) -> Result<~T, E> { + Ok(~try!(Decodable::decode(d))) } } -impl> Encodable for @T { - fn encode(&self, s: &mut S) { +impl,T:Encodable> Encodable for @T { + fn encode(&self, s: &mut S) -> Result<(), E> { (**self).encode(s) } } -impl> Encodable for Rc { +impl,T:Encodable> Encodable for Rc { #[inline] - fn encode(&self, s: &mut S) { + fn encode(&self, s: &mut S) -> Result<(), E> { (**self).encode(s) } } -impl> Decodable for Rc { +impl,T:Decodable> Decodable for Rc { #[inline] - fn decode(d: &mut D) -> Rc { - Rc::new(Decodable::decode(d)) + fn decode(d: &mut D) -> Result, E> { + Ok(Rc::new(try!(Decodable::decode(d)))) } } -impl + 'static> Decodable for @T { - fn decode(d: &mut D) -> @T { - @Decodable::decode(d) +impl,T:Decodable + 'static> Decodable for @T { + fn decode(d: &mut D) -> Result<@T, E> { + Ok(@try!(Decodable::decode(d))) } } -impl<'a, S:Encoder,T:Encodable> Encodable for &'a [T] { - fn encode(&self, s: &mut S) { +impl<'a, E, S:Encoder,T:Encodable> Encodable 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> Encodable for ~[T] { - fn encode(&self, s: &mut S) { +impl,T:Encodable> Encodable 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> Decodable for ~[T] { - fn decode(d: &mut D) -> ~[T] { +impl,T:Decodable> Decodable 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> Encodable for Vec { - fn encode(&self, s: &mut S) { +impl,T:Encodable> Encodable for Vec { + 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> Decodable for Vec { - fn decode(d: &mut D) -> Vec { +impl,T:Decodable> Decodable for Vec { + fn decode(d: &mut D) -> Result, 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> Encodable for Option { - fn encode(&self, s: &mut S) { +impl,T:Encodable> Encodable for Option { + fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_option(|s| { match *self { None => s.emit_option_none(), @@ -465,13 +486,13 @@ impl> Encodable for Option { } } -impl> Decodable for Option { - fn decode(d: &mut D) -> Option { +impl,T:Decodable> Decodable for Option { + fn decode(d: &mut D) -> Result, 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),*> Decodable for ($($name,)*) { + impl,$($name:Decodable),*> Decodable 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),*> Encodable for ($($name,)*) { + impl,$($name:Encodable),*> Encodable 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 @@ macro_rules! tuple ( tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } -impl Encodable for path::posix::Path { - fn encode(&self, e: &mut E) { +impl> Encodable for path::posix::Path { + fn encode(&self, e: &mut S) -> Result<(), E> { self.as_vec().encode(e) } } -impl Decodable for path::posix::Path { - fn decode(d: &mut D) -> path::posix::Path { - let bytes: ~[u8] = Decodable::decode(d); - path::posix::Path::new(bytes) +impl> Decodable for path::posix::Path { + fn decode(d: &mut D) -> Result { + let bytes: ~[u8] = try!(Decodable::decode(d)); + Ok(path::posix::Path::new(bytes)) } } -impl Encodable for path::windows::Path { - fn encode(&self, e: &mut E) { +impl> Encodable for path::windows::Path { + fn encode(&self, e: &mut S) -> Result<(), E> { self.as_vec().encode(e) } } -impl Decodable for path::windows::Path { - fn decode(d: &mut D) -> path::windows::Path { - let bytes: ~[u8] = Decodable::decode(d); - path::windows::Path::new(bytes) +impl> Decodable for path::windows::Path { + fn decode(d: &mut D) -> Result { + let bytes: ~[u8] = try!(Decodable::decode(d)); + Ok(path::windows::Path::new(bytes)) } } @@ -546,32 +568,37 @@ impl Decodable for path::windows::Path { // // In some cases, these should eventually be coded as traits. -pub trait EncoderHelpers { - fn emit_from_vec(&mut self, v: &[T], f: |&mut Self, v: &T|); +pub trait EncoderHelpers { + fn emit_from_vec(&mut self, + v: &[T], + f: |&mut Self, v: &T| -> Result<(), E>) -> Result<(), E>; } -impl EncoderHelpers for S { - fn emit_from_vec(&mut self, v: &[T], f: |&mut S, &T|) { +impl> EncoderHelpers for S { + fn emit_from_vec(&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(&mut self, f: |&mut Self| -> T) -> ~[T]; +pub trait DecoderHelpers { + fn read_to_vec(&mut self, f: |&mut Self| -> Result) -> Result<~[T], E>; } -impl DecoderHelpers for D { - fn read_to_vec(&mut self, f: |&mut D| -> T) -> ~[T] { +impl> DecoderHelpers for D { + fn read_to_vec(&mut self, f: |&mut D| -> Result) -> 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 index 00000000000..4043cbe65fe --- /dev/null +++ b/src/libserialize/serialize_old.rs @@ -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 or the MIT license +// , 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(&mut self, name: &str, f: |&mut Self| -> T) -> T; + + fn read_enum_variant(&mut self, + names: &[&str], + f: |&mut Self, uint| -> T) + -> T; + fn read_enum_variant_arg(&mut self, + a_idx: uint, + f: |&mut Self| -> T) + -> T; + + fn read_enum_struct_variant(&mut self, + names: &[&str], + f: |&mut Self, uint| -> T) + -> T; + fn read_enum_struct_variant_field(&mut self, + &f_name: &str, + f_idx: uint, + f: |&mut Self| -> T) + -> T; + + fn read_struct(&mut self, s_name: &str, len: uint, f: |&mut Self| -> T) + -> T; + fn read_struct_field(&mut self, + f_name: &str, + f_idx: uint, + f: |&mut Self| -> T) + -> T; + + fn read_tuple(&mut self, f: |&mut Self, uint| -> T) -> T; + fn read_tuple_arg(&mut self, a_idx: uint, f: |&mut Self| -> T) -> T; + + fn read_tuple_struct(&mut self, + s_name: &str, + f: |&mut Self, uint| -> T) + -> T; + fn read_tuple_struct_arg(&mut self, + a_idx: uint, + f: |&mut Self| -> T) + -> T; + + // Specialized types: + fn read_option(&mut self, f: |&mut Self, bool| -> T) -> T; + + fn read_seq(&mut self, f: |&mut Self, uint| -> T) -> T; + fn read_seq_elt(&mut self, idx: uint, f: |&mut Self| -> T) -> T; + + fn read_map(&mut self, f: |&mut Self, uint| -> T) -> T; + fn read_map_elt_key(&mut self, idx: uint, f: |&mut Self| -> T) -> T; + fn read_map_elt_val(&mut self, idx: uint, f: |&mut Self| -> T) -> T; +} + +pub trait Encodable { + fn encode(&self, s: &mut S); +} + +pub trait Decodable { + fn decode(d: &mut D) -> Self; +} + +impl Encodable for uint { + fn encode(&self, s: &mut S) { + s.emit_uint(*self) + } +} + +impl Decodable for uint { + fn decode(d: &mut D) -> uint { + d.read_uint() + } +} + +impl Encodable for u8 { + fn encode(&self, s: &mut S) { + s.emit_u8(*self) + } +} + +impl Decodable for u8 { + fn decode(d: &mut D) -> u8 { + d.read_u8() + } +} + +impl Encodable for u16 { + fn encode(&self, s: &mut S) { + s.emit_u16(*self) + } +} + +impl Decodable for u16 { + fn decode(d: &mut D) -> u16 { + d.read_u16() + } +} + +impl Encodable for u32 { + fn encode(&self, s: &mut S) { + s.emit_u32(*self) + } +} + +impl Decodable for u32 { + fn decode(d: &mut D) -> u32 { + d.read_u32() + } +} + +impl Encodable for u64 { + fn encode(&self, s: &mut S) { + s.emit_u64(*self) + } +} + +impl Decodable for u64 { + fn decode(d: &mut D) -> u64 { + d.read_u64() + } +} + +impl Encodable for int { + fn encode(&self, s: &mut S) { + s.emit_int(*self) + } +} + +impl Decodable for int { + fn decode(d: &mut D) -> int { + d.read_int() + } +} + +impl Encodable for i8 { + fn encode(&self, s: &mut S) { + s.emit_i8(*self) + } +} + +impl Decodable for i8 { + fn decode(d: &mut D) -> i8 { + d.read_i8() + } +} + +impl Encodable for i16 { + fn encode(&self, s: &mut S) { + s.emit_i16(*self) + } +} + +impl Decodable for i16 { + fn decode(d: &mut D) -> i16 { + d.read_i16() + } +} + +impl Encodable for i32 { + fn encode(&self, s: &mut S) { + s.emit_i32(*self) + } +} + +impl Decodable for i32 { + fn decode(d: &mut D) -> i32 { + d.read_i32() + } +} + +impl Encodable for i64 { + fn encode(&self, s: &mut S) { + s.emit_i64(*self) + } +} + +impl Decodable for i64 { + fn decode(d: &mut D) -> i64 { + d.read_i64() + } +} + +impl<'a, S:Encoder> Encodable for &'a str { + fn encode(&self, s: &mut S) { + s.emit_str(*self) + } +} + +impl Encodable for ~str { + fn encode(&self, s: &mut S) { + s.emit_str(*self) + } +} + +impl Decodable for ~str { + fn decode(d: &mut D) -> ~str { + d.read_str() + } +} + +impl Encodable for f32 { + fn encode(&self, s: &mut S) { + s.emit_f32(*self) + } +} + +impl Decodable for f32 { + fn decode(d: &mut D) -> f32 { + d.read_f32() + } +} + +impl Encodable for f64 { + fn encode(&self, s: &mut S) { + s.emit_f64(*self) + } +} + +impl Decodable for f64 { + fn decode(d: &mut D) -> f64 { + d.read_f64() + } +} + +impl Encodable for bool { + fn encode(&self, s: &mut S) { + s.emit_bool(*self) + } +} + +impl Decodable for bool { + fn decode(d: &mut D) -> bool { + d.read_bool() + } +} + +impl Encodable for char { + fn encode(&self, s: &mut S) { + s.emit_char(*self) + } +} + +impl Decodable for char { + fn decode(d: &mut D) -> char { + d.read_char() + } +} + +impl Encodable for () { + fn encode(&self, s: &mut S) { + s.emit_nil() + } +} + +impl Decodable for () { + fn decode(d: &mut D) -> () { + d.read_nil() + } +} + +impl<'a, S:Encoder,T:Encodable> Encodable for &'a T { + fn encode(&self, s: &mut S) { + (**self).encode(s) + } +} + +impl> Encodable for ~T { + fn encode(&self, s: &mut S) { + (**self).encode(s) + } +} + +impl> Decodable for ~T { + fn decode(d: &mut D) -> ~T { + ~Decodable::decode(d) + } +} + +impl> Encodable for @T { + fn encode(&self, s: &mut S) { + (**self).encode(s) + } +} + +impl> Encodable for Rc { + #[inline] + fn encode(&self, s: &mut S) { + (**self).encode(s) + } +} + +impl> Decodable for Rc { + #[inline] + fn decode(d: &mut D) -> Rc { + Rc::new(Decodable::decode(d)) + } +} + +impl + 'static> Decodable for @T { + fn decode(d: &mut D) -> @T { + @Decodable::decode(d) + } +} + +impl<'a, S:Encoder,T:Encodable> Encodable 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> Encodable 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> Decodable 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> Encodable for Vec { + 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> Decodable for Vec { + fn decode(d: &mut D) -> Vec { + d.read_seq(|d, len| { + Vec::from_fn(len, |i| { + d.read_seq_elt(i, |d| Decodable::decode(d)) + }) + }) + } +} + +impl> Encodable for Option { + 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> Decodable for Option { + fn decode(d: &mut D) -> Option { + d.read_option(|d, b| { + if b { + Some(Decodable::decode(d)) + } else { + None + } + }) + } +} + +impl,T1:Encodable> Encodable 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,T1:Decodable> Decodable 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, + T1: Encodable, + T2: Encodable +> Encodable 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, + T1: Decodable, + T2: Decodable +> Decodable 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, + T1: Encodable, + T2: Encodable, + T3: Encodable +> Encodable 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, + T1: Decodable, + T2: Decodable, + T3: Decodable +> Decodable 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, + T1: Encodable, + T2: Encodable, + T3: Encodable, + T4: Encodable +> Encodable 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, + T1: Decodable, + T2: Decodable, + T3: Decodable, + T4: Decodable +> Decodable 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 Encodable for path::posix::Path { + fn encode(&self, e: &mut E) { + self.as_vec().encode(e) + } +} + +impl Decodable for path::posix::Path { + fn decode(d: &mut D) -> path::posix::Path { + let bytes: ~[u8] = Decodable::decode(d); + path::posix::Path::new(bytes) + } +} + +impl Encodable for path::windows::Path { + fn encode(&self, e: &mut E) { + self.as_vec().encode(e) + } +} + +impl Decodable 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(&mut self, v: &[T], f: |&mut Self, v: &T|); +} + +impl EncoderHelpers for S { + fn emit_from_vec(&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(&mut self, f: |&mut Self| -> T) -> ~[T]; +} + +impl DecoderHelpers for D { + fn read_to_vec(&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)) + }) + }) + } +} + diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a7d458df0cf..a44fbce421b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -98,18 +98,35 @@ pub type Name = u32; /// A mark represents a unique id associated with a macro expansion pub type Mrk = u32; +// FIXME: remove stage0 Encodables after snapshot +#[cfg(stage0)] impl Encodable for Ident { fn encode(&self, s: &mut S) { s.emit_str(token::get_ident(*self).get()); } } +#[cfg(stage0)] impl Decodable for Ident { fn decode(d: &mut D) -> Ident { str_to_ident(d.read_str()) } } +#[cfg(not(stage0))] +impl, E> Encodable for Ident { + fn encode(&self, s: &mut S) -> Result<(), E> { + s.emit_str(token::get_ident(*self).get()) + } +} + +#[cfg(not(stage0))] +impl, E> Decodable for Ident { + fn decode(d: &mut D) -> Result { + Ok(str_to_ident(try!(d.read_str()))) + } +} + /// Function name (not all functions have names) pub type FnIdent = Option; @@ -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 @@ mod test { // doesn't matter which encoder we use.... let _f = &e as &serialize::Encodable; } + + #[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; + } } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 4a9e53c63e7..f3ff7f97ee2 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -110,6 +110,8 @@ impl Eq for Span { impl TotalEq for Span {} +// FIXME: remove stage0 Encodables/Decodables after snapshot +#[cfg(stage0)] impl Encodable for Span { /* Note #1972 -- spans are encoded but not decoded */ fn encode(&self, s: &mut S) { @@ -117,12 +119,28 @@ impl Encodable for Span { } } +#[cfg(stage0)] impl Decodable for Span { fn decode(_d: &mut D) -> Span { DUMMY_SP } } +#[cfg(not(stage0))] +impl, E> Encodable 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, E> Decodable for Span { + fn decode(_d: &mut D) -> Result { + Ok(DUMMY_SP) + } +} + pub fn spanned(lo: BytePos, hi: BytePos, t: T) -> Spanned { respan(mk_sp(lo, hi), t) } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index bdb16f176c0..1c2c63cd919 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -142,6 +142,10 @@ pub trait AstBuilder { 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 @@ impl<'a> AstBuilder for ExtCtxt<'a> { "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 } diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 4c9a58c46f7..579de82c8db 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -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, diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 2fa6ec6888b..90ea8701562 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -82,7 +82,7 @@ would yield functions like: ``` */ -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, diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs index 57051e78667..c4ce3c5cb55 100644 --- a/src/libsyntax/owned_slice.rs +++ b/src/libsyntax/owned_slice.rs @@ -131,14 +131,34 @@ impl FromIterator for OwnedSlice { } } +// FIXME: remove stage0 Encodables/Decodables after snapshot +#[cfg(stage0)] impl> Encodable for OwnedSlice { fn encode(&self, s: &mut S) { self.as_slice().encode(s) } } +#[cfg(stage0)] impl> Decodable for OwnedSlice { fn decode(d: &mut D) -> OwnedSlice { OwnedSlice::from_vec(Decodable::decode(d)) } } + +#[cfg(not(stage0))] +impl, T: Encodable, E> Encodable for OwnedSlice { + fn encode(&self, s: &mut S) -> Result<(), E> { + self.as_slice().encode(s) + } +} + +#[cfg(not(stage0))] +impl, T: Decodable, E> Decodable for OwnedSlice { + fn decode(d: &mut D) -> Result, E> { + Ok(OwnedSlice::from_vec(match Decodable::decode(d) { + Ok(t) => t, + Err(e) => return Err(e) + })) + } +} diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index eb6b462fb94..2df93deea14 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -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>>(val: &E) -> ~str { let mut writer = MemWriter::new(); let mut encoder = json::Encoder::new(&mut writer as &mut io::Writer); @@ -296,6 +297,14 @@ mod test { str::from_utf8_owned(writer.unwrap()).unwrap() } + #[cfg(not(stage0))] + fn to_json_str<'a, E: Encodable, 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} diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 15525912955..7bb920bdf56 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -602,18 +602,35 @@ impl<'a> Equiv<&'a str> for InternedString { } } +// FIXME: remove stage0 Encodables/Decodables after snapshot +#[cfg(stage0)] impl Decodable for InternedString { fn decode(d: &mut D) -> InternedString { get_name(get_ident_interner().intern(d.read_str())) } } +#[cfg(stage0)] impl Encodable for InternedString { fn encode(&self, e: &mut E) { e.emit_str(self.string.as_slice()) } } +#[cfg(not(stage0))] +impl, E> Decodable for InternedString { + fn decode(d: &mut D) -> Result { + Ok(get_name(get_ident_interner().intern(try!(d.read_str())))) + } +} + +#[cfg(not(stage0))] +impl, E> Encodable 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 { diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 039b118b327..751dc58450f 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -46,7 +46,7 @@ use stats::Stats; 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 @@ impl ToJson for Metric { } } +// 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 @@ impl 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. diff --git a/src/libuuid/lib.rs b/src/libuuid/lib.rs index d31b0f43a09..0065c90c91a 100644 --- a/src/libuuid/lib.rs +++ b/src/libuuid/lib.rs @@ -490,13 +490,16 @@ impl Eq for Uuid { impl TotalEq for Uuid {} // FIXME #9845: Test these more thoroughly +// FIXME: remove stage0 Encodable/Decodable after snapshot +#[cfg(stage0)] impl Encodable 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 Decodable for Uuid { /// Decode a UUID from a string fn decode(d: &mut T) -> Uuid { @@ -504,6 +507,22 @@ impl Decodable for Uuid { } } +#[cfg(not(stage0))] +impl, E> Encodable 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, E> Decodable for Uuid { + /// Decode a UUID from a string + fn decode(d: &mut T) -> Result { + 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 + } + + #[cfg(not(stage0))] + fn unwrap_(t: Result) -> T { + t.unwrap() + } + #[test] fn test_nil() { let nil = Uuid::nil(); @@ -797,9 +827,9 @@ mod test { 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); } diff --git a/src/libworkcache/lib.rs b/src/libworkcache/lib.rs index 3e513472027..a049279c5c4 100644 --- a/src/libworkcache/lib.rs +++ b/src/libworkcache/lib.rs @@ -203,7 +203,7 @@ impl Database { 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>>(t: &T) -> ~str { +fn json_encode<'a, T:Encodable, 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>(s: &str) -> T { +fn json_decode>(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 @@ impl<'a> Prep<'a> { } pub fn exec<'a, T:Send + - Encodable> + - Decodable>( + Encodable, io::IoError> + + Decodable>( &'a self, blk: proc:Send(&mut Exec) -> T) -> T { self.exec_work(blk).unwrap() } fn exec_work<'a, T:Send + - Encodable> + - Decodable>( // FIXME(#5121) + Encodable, io::IoError> + + Decodable>( // FIXME(#5121) &'a self, blk: proc:Send(&mut Exec) -> T) -> Work<'a, T> { let mut bo = Some(blk); @@ -443,8 +443,8 @@ impl<'a> Prep<'a> { } impl<'a, T:Send + - Encodable> + - Decodable> + Encodable, io::IoError> + + Decodable> Work<'a, T> { // FIXME(#5121) pub fn from_value(elt: T) -> Work<'a, T> { diff --git a/src/test/run-pass/issue-4016.rs b/src/test/run-pass/issue-4016.rs index 4b9a2353862..7f72850aaaf 100644 --- a/src/test/run-pass/issue-4016.rs +++ b/src/test/run-pass/issue-4016.rs @@ -15,12 +15,12 @@ extern crate serialize; use serialize::{json, Decodable}; -trait JD : Decodable { } +trait JD : Decodable { } fn exec() { 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!() } diff --git a/src/test/run-pass/issue-4036.rs b/src/test/run-pass/issue-4036.rs index 1033b953305..72efd252512 100644 --- a/src/test/run-pass/issue-4036.rs +++ b/src/test/run-pass/issue-4036.rs @@ -20,5 +20,5 @@ use serialize::{json, Decodable}; pub fn main() { let json = json::from_str("[1]").unwrap(); let mut decoder = json::Decoder::new(json); - let _x: Vec = Decodable::decode(&mut decoder); + let _x: Vec = Decodable::decode(&mut decoder).unwrap(); }