All of Decoder and Encoder's methods now return a Result.
Encodable.encode() and Decodable.decode() return a Result as well.
fixes #12292
}
}
+// FIXME: remove unwrap_ after snapshot
+#[cfg(stage0)]
+fn unwrap_<T>(t: T) -> T {
+ t
+}
+
+#[cfg(not(stage0))]
+fn unwrap_<T, E>(r: Result<T, E>) -> T {
+ r.unwrap()
+}
+
+
pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
-> ast::Crate {
let krate = time(sess.time_passes(), "parsing", (), |_| {
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() {
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)
pub type Cmd = @crate_metadata;
+// FIXME: remove unwrap_ after a snapshot
+#[cfg(stage0)]
+fn unwrap_<T>(t: T) -> T {
+ t
+}
+
+#[cfg(not(stage0))]
+fn unwrap_<T, E>(r: Result<T, E>) -> T {
+ r.unwrap()
+}
+
// A function that takes a def_id relative to the crate being searched and
// returns a def_id relative to the compilation environment, i.e. if we hit a
// def_id for an item defined in another crate, somebody needs to figure out
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;
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
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,
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> {
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));
}
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) {
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);
}
// 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();
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) {
}
}
-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);
}
}
-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));
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(),
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());
}
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,
}
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,
}
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);
}
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);
}
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) {
}
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();
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 {
}
fn encode_enum_variant_info(ecx: &EncodeContext,
- ebml_w: &mut writer::Encoder,
+ ebml_w: &mut Encoder,
id: NodeId,
variants: &[P<Variant>],
index: @RefCell<Vec<entry<i64>> >,
}
}
-fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut writer::Encoder,
+fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut Encoder,
mut path: PI) {
ebml_w.start_tag(tag_path);
ebml_w.wr_tagged_u32(tag_path_len, path.clone().len() as u32);
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) {
}
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) {
}
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) {
}
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) {
}
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);
}
fn encode_info_for_mod(ecx: &EncodeContext,
- ebml_w: &mut writer::Encoder,
+ ebml_w: &mut Encoder,
md: &Mod,
id: NodeId,
path: PathElems,
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',
});
}
-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',
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.
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 ]); }
}
}
-fn encode_method_sort(ebml_w: &mut writer::Encoder, sort: char) {
+fn encode_method_sort(ebml_w: &mut Encoder, sort: char) {
ebml_w.start_tag(tag_item_trait_method_sort);
ebml_w.writer.write(&[ sort as u8 ]);
ebml_w.end_tag();
}
-fn encode_provided_source(ebml_w: &mut writer::Encoder,
+fn encode_provided_source(ebml_w: &mut Encoder,
source_opt: Option<DefId>) {
for source in source_opt.iter() {
ebml_w.start_tag(tag_item_method_provided_source);
/* Returns an index of items in this class */
fn encode_info_for_struct(ecx: &EncodeContext,
- ebml_w: &mut writer::Encoder,
+ ebml_w: &mut Encoder,
fields: &[StructField],
global_index: @RefCell<Vec<entry<i64>> >)
-> Vec<entry<i64>> {
}
fn encode_info_for_struct_ctor(ecx: &EncodeContext,
- ebml_w: &mut writer::Encoder,
+ ebml_w: &mut Encoder,
name: ast::Ident,
ctor_id: NodeId,
index: @RefCell<Vec<entry<i64>> >,
}
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);
}
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,
// 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 => {}
// 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 => {}
}
fn encode_info_for_item(ecx: &EncodeContext,
- ebml_w: &mut writer::Encoder,
+ ebml_w: &mut Encoder,
item: &Item,
index: @RefCell<Vec<entry<i64>> >,
path: PathElems,
vis: ast::Visibility) {
let tcx = ecx.tcx;
- fn add_to_index(item: &Item, ebml_w: &writer::Encoder,
+ fn add_to_index(item: &Item, ebml_w: &Encoder,
index: @RefCell<Vec<entry<i64>> >) {
index.borrow_mut().push(entry {
val: item.id as i64,
}
fn encode_info_for_foreign_item(ecx: &EncodeContext,
- ebml_w: &mut writer::Encoder,
+ ebml_w: &mut Encoder,
nitem: &ForeignItem,
index: @RefCell<Vec<entry<i64>> >,
path: PathElems,
fn my_visit_expr(_e: &Expr) { }
fn my_visit_item(i: &Item,
- ebml_w: &mut writer::Encoder,
+ ebml_w: &mut Encoder,
ecx_ptr: *int,
index: @RefCell<Vec<entry<i64>> >) {
let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
}
fn my_visit_foreign_item(ni: &ForeignItem,
- ebml_w: &mut writer::Encoder,
+ ebml_w: &mut Encoder,
ecx_ptr:*int,
index: @RefCell<Vec<entry<i64>> >) {
// See above
}
struct EncodeVisitor<'a,'b> {
- ebml_w_for_visit_item: &'a mut writer::Encoder<'b>,
+ ebml_w_for_visit_item: &'a mut Encoder<'b>,
ecx_ptr:*int,
index: @RefCell<Vec<entry<i64>> >,
}
}
fn encode_info_for_items(ecx: &EncodeContext,
- ebml_w: &mut writer::Encoder,
+ ebml_w: &mut Encoder,
krate: &Crate)
-> Vec<entry<i64>> {
let index = @RefCell::new(Vec::new());
}
fn encode_index<T:'static>(
- ebml_w: &mut writer::Encoder,
+ ebml_w: &mut Encoder,
buckets: Vec<@Vec<entry<T>> > ,
write_fn: |&mut MemWriter, &T|) {
ebml_w.start_tag(tag_index);
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);
}
}
-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);
attrs
}
-fn encode_crate_deps(ebml_w: &mut writer::Encoder, cstore: &cstore::CStore) {
+fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
// Pull the cnums and name,vers,hash out of cstore
let mut deps = Vec::new();
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() {
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()
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);
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> {
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 {
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> {
/// * 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);
{
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() {
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);
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();
// 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;
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;
fn tr_intern(&self, xcx: &ExtendedDecodeContext) -> ast::DefId;
}
+// FIXME: remove this Encoder type after snapshot
+#[cfg(stage0)]
+pub type Encoder<'a> = writer::Encoder<'a>;
+
+#[cfg(not(stage0))]
+pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
+
+// FIXME: remove unwrap_ and wrap_ after snapshot
+#[cfg(stage0)]
+fn unwrap_<T>(t: T) -> T {
+ t
+}
+
+#[cfg(not(stage0))]
+fn unwrap_<T, E>(r: Result<T, E>) -> T {
+ r.unwrap()
+}
+
+#[cfg(stage0)]
+fn wrap_<T>(t: T) -> T {
+ t
+}
+
+#[cfg(not(stage0))]
+fn wrap_<T, E>(t: T) -> Result<T, E> {
+ Ok(t)
+}
+
+
+
// ______________________________________________________________________
// Top-level methods.
pub fn encode_inlined_item(ecx: &e::EncodeContext,
- ebml_w: &mut writer::Encoder,
+ ebml_w: &mut Encoder,
ii: e::InlinedItemRef,
maps: &Maps) {
let id = match ii {
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")
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,
fn emit_def_id(&mut self, did: ast::DefId);
}
+#[cfg(stage0)]
impl<S:serialize::Encoder> def_id_encoder_helpers for S {
fn emit_def_id(&mut self, did: ast::DefId) {
did.encode(self)
}
}
+#[cfg(not(stage0))]
+impl<S:serialize::Encoder<E>, E> def_id_encoder_helpers for S {
+ fn emit_def_id(&mut self, did: ast::DefId) {
+ unwrap_(did.encode(self))
+ }
+}
+
trait def_id_decoder_helpers {
fn read_def_id(&mut self, xcx: &ExtendedDecodeContext) -> ast::DefId;
fn read_def_id_noxcx(&mut self,
cdata: @cstore::crate_metadata) -> ast::DefId;
}
+#[cfg(stage0)]
impl<D:serialize::Decoder> def_id_decoder_helpers for D {
fn read_def_id(&mut self, xcx: &ExtendedDecodeContext) -> ast::DefId {
- let did: ast::DefId = Decodable::decode(self);
+ let did: ast::DefId = unwrap_(Decodable::decode(self));
did.tr(xcx)
}
fn read_def_id_noxcx(&mut self,
cdata: @cstore::crate_metadata) -> ast::DefId {
- let did: ast::DefId = Decodable::decode(self);
+ let did: ast::DefId = unwrap_(Decodable::decode(self));
+ decoder::translate_def_id(cdata, did)
+ }
+}
+
+#[cfg(not(stage0))]
+impl<D:serialize::Decoder<E>, E> def_id_decoder_helpers for D {
+ fn read_def_id(&mut self, xcx: &ExtendedDecodeContext) -> ast::DefId {
+ let did: ast::DefId = unwrap_(Decodable::decode(self));
+ did.tr(xcx)
+ }
+
+ fn read_def_id_noxcx(&mut self,
+ cdata: @cstore::crate_metadata) -> ast::DefId {
+ let did: ast::DefId = unwrap_(Decodable::decode(self));
decoder::translate_def_id(cdata, did)
}
}
// 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();
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> {
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)
}
// ______________________________________________________________________
// 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 {
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)
}
}
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)
}
}
}
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))
+ }))
+ }))
+ }))
}
}
// 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 {
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()
}
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()
}
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")
- }
+ })
})
- })
+ }))
}
}
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,
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) {
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) => {
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)))
+ })
}
}
});
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,
}
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 {
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;
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)));
})
}
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))
+ });
})
})
}
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)
+ });
})
})
}
impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
fn read_ty_noxcx(&mut self,
tcx: &ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t {
- self.read_opaque(|_, doc| {
- tydecode::parse_ty_data(
+ unwrap_(self.read_opaque(|_, doc| {
+ wrap_(tydecode::parse_ty_data(
doc.data,
cdata.cnum,
doc.start,
tcx,
- |_, id| decoder::translate_def_id(cdata, id))
- })
+ |_, id| decoder::translate_def_id(cdata, id)))
+ }))
}
fn read_tys_noxcx(&mut self,
tcx: &ty::ctxt,
cdata: @cstore::crate_metadata) -> Vec<ty::t> {
- self.read_to_vec(|this| this.read_ty_noxcx(tcx, cdata) )
+ unwrap_(self.read_to_vec(|this| wrap_(this.read_ty_noxcx(tcx, cdata)) ))
.move_iter()
.collect()
}
// 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(
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 = ~"";
}
fn read_tys(&mut self, xcx: &ExtendedDecodeContext) -> Vec<ty::t> {
- self.read_to_vec(|this| this.read_ty(xcx)).move_iter().collect()
+ unwrap_(self.read_to_vec(|this| wrap_(this.read_ty(xcx)))).move_iter().collect()
}
fn read_type_param_def(&mut self, xcx: &ExtendedDecodeContext)
-> ty::TypeParameterDef {
- self.read_opaque(|this, doc| {
- tydecode::parse_type_param_def_data(
+ unwrap_(self.read_opaque(|this, doc| {
+ wrap_(tydecode::parse_type_param_def_data(
doc.data,
doc.start,
xcx.dcx.cdata.cnum,
xcx.dcx.tcx,
- |s, a| this.convert_def_id(xcx, s, a))
- })
+ |s, a| this.convert_def_id(xcx, s, a)))
+ }))
}
fn read_ty_param_bounds_and_ty(&mut self, xcx: &ExtendedDecodeContext)
-> ty::ty_param_bounds_and_ty {
- self.read_struct("ty_param_bounds_and_ty", 2, |this| {
- ty::ty_param_bounds_and_ty {
- generics: this.read_struct_field("generics", 0, |this| {
+ unwrap_(self.read_struct("ty_param_bounds_and_ty", 2, |this| {
+ wrap_(ty::ty_param_bounds_and_ty {
+ generics: unwrap_(this.read_struct_field("generics", 0, |this| {
this.read_struct("Generics", 2, |this| {
- ty::Generics {
+ wrap_(ty::Generics {
type_param_defs:
- this.read_struct_field("type_param_defs",
+ unwrap_(this.read_struct_field("type_param_defs",
0,
|this| {
- Rc::new(this.read_to_vec(|this|
- this.read_type_param_def(xcx))
+ wrap_(Rc::new(unwrap_(this.read_to_vec(|this|
+ wrap_(this.read_type_param_def(xcx))))
.move_iter()
- .collect())
- }),
+ .collect()))
+ })),
region_param_defs:
- this.read_struct_field("region_param_defs",
+ unwrap_(this.read_struct_field("region_param_defs",
1,
|this| {
Decodable::decode(this)
- })
- }
+ }))
+ })
})
- }),
- ty: this.read_struct_field("ty", 1, |this| {
- this.read_ty(xcx)
- })
- }
- })
+ })),
+ ty: unwrap_(this.read_struct_field("ty", 1, |this| {
+ wrap_(this.read_ty(xcx))
+ }))
+ })
+ }))
}
fn read_substs(&mut self, xcx: &ExtendedDecodeContext) -> ty::substs {
- self.read_opaque(|this, doc| {
- tydecode::parse_substs_data(doc.data,
+ unwrap_(self.read_opaque(|this, doc| {
+ wrap_(tydecode::parse_substs_data(doc.data,
xcx.dcx.cdata.cnum,
doc.start,
xcx.dcx.tcx,
- |s, a| this.convert_def_id(xcx, s, a))
- })
+ |s, a| this.convert_def_id(xcx, s, a)))
+ }))
}
fn read_auto_adjustment(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoAdjustment {
- self.read_enum("AutoAdjustment", |this| {
+ unwrap_(self.read_enum("AutoAdjustment", |this| {
let variants = ["AutoAddEnv", "AutoDerefRef", "AutoObject"];
this.read_enum_variant(variants, |this, i| {
- match i {
+ wrap_(match i {
0 => {
let region: ty::Region =
- this.read_enum_variant_arg(0, |this| Decodable::decode(this));
+ unwrap_(this.read_enum_variant_arg(0, |this| Decodable::decode(this)));
let sigil: ast::Sigil =
- this.read_enum_variant_arg(1, |this| Decodable::decode(this));
+ unwrap_(this.read_enum_variant_arg(1, |this| Decodable::decode(this)));
ty:: AutoAddEnv(region.tr(xcx), sigil)
}
1 => {
let auto_deref_ref: ty::AutoDerefRef =
- this.read_enum_variant_arg(0, |this| Decodable::decode(this));
+ unwrap_(this.read_enum_variant_arg(0, |this| Decodable::decode(this)));
ty::AutoDerefRef(auto_deref_ref.tr(xcx))
}
2 => {
let sigil: ast::Sigil =
- this.read_enum_variant_arg(0, |this| Decodable::decode(this));
+ unwrap_(this.read_enum_variant_arg(0, |this| Decodable::decode(this)));
let region: Option<ty::Region> =
- this.read_enum_variant_arg(1, |this| Decodable::decode(this));
+ unwrap_(this.read_enum_variant_arg(1, |this| Decodable::decode(this)));
let m: ast::Mutability =
- this.read_enum_variant_arg(2, |this| Decodable::decode(this));
+ unwrap_(this.read_enum_variant_arg(2, |this| Decodable::decode(this)));
let b: ty::BuiltinBounds =
- this.read_enum_variant_arg(3, |this| Decodable::decode(this));
+ unwrap_(this.read_enum_variant_arg(3, |this| Decodable::decode(this)));
let def_id: ast::DefId =
- this.read_enum_variant_arg(4, |this| Decodable::decode(this));
- let substs = this.read_enum_variant_arg(5, |this| this.read_substs(xcx));
+ unwrap_(this.read_enum_variant_arg(4, |this| Decodable::decode(this)));
+ let substs = unwrap_(
+ this.read_enum_variant_arg(5, |this| wrap_(this.read_substs(xcx))));
let region = match region {
Some(r) => Some(r.tr(xcx)),
ty::AutoObject(sigil, region, m, b, def_id.tr(xcx), substs)
}
_ => fail!("bad enum variant for ty::AutoAdjustment")
- }
+ })
})
- })
+ }))
}
fn convert_def_id(&mut self,
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 => {
}
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));
// 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();
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)]
return pm.run_plugins(krate);
}
+// FIXME: remove unwrap_ after snapshot
+#[cfg(stage0)]
+fn unwrap_<T>(t: T) -> T {
+ t
+}
+
+#[cfg(not(stage0))]
+fn unwrap_<T, E>(r: Result<T, E>) -> T {
+ r.unwrap()
+}
+
/// This input format purely deserializes the json output file. No passes are
/// run over the deserialized output.
fn json_input(input: &str) -> Result<Output, ~str> {
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"),
};
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()
};
use collections::enum_set::{EnumSet, CLike};
impl<
- S: Encoder,
- T: Encodable<S>
-> Encodable<S> for DList<T> {
- fn encode(&self, s: &mut S) {
+ E,
+ S: Encoder<E>,
+ T: Encodable<S, E>
+> Encodable<S, E> for DList<T> {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
- s.emit_seq_elt(i, |s| e.encode(s));
+ try!(s.emit_seq_elt(i, |s| e.encode(s)));
}
+ Ok(())
})
}
}
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for DList<T> {
- fn decode(d: &mut D) -> DList<T> {
- let mut list = DList::new();
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for DList<T> {
+ fn decode(d: &mut D) -> Result<DList<T>, E> {
d.read_seq(|d, len| {
+ let mut list = DList::new();
for i in range(0u, len) {
- list.push_back(d.read_seq_elt(i, |d| Decodable::decode(d)));
+ list.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
- });
- list
+ Ok(list)
+ })
}
}
impl<
- S: Encoder,
- T: Encodable<S>
-> Encodable<S> for RingBuf<T> {
- fn encode(&self, s: &mut S) {
+ E,
+ S: Encoder<E>,
+ T: Encodable<S, E>
+> Encodable<S, E> for RingBuf<T> {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
- s.emit_seq_elt(i, |s| e.encode(s));
+ try!(s.emit_seq_elt(i, |s| e.encode(s)));
}
+ Ok(())
})
}
}
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for RingBuf<T> {
- fn decode(d: &mut D) -> RingBuf<T> {
- let mut deque = RingBuf::new();
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for RingBuf<T> {
+ fn decode(d: &mut D) -> Result<RingBuf<T>, E> {
d.read_seq(|d, len| {
+ let mut deque: RingBuf<T> = RingBuf::new();
for i in range(0u, len) {
- deque.push_back(d.read_seq_elt(i, |d| Decodable::decode(d)));
+ deque.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
- });
- deque
+ Ok(deque)
+ })
}
}
impl<
- E: Encoder,
- K: Encodable<E> + Eq + TotalOrd,
- V: Encodable<E> + Eq
-> Encodable<E> for TreeMap<K, V> {
- fn encode(&self, e: &mut E) {
+ E,
+ S: Encoder<E>,
+ K: Encodable<S, E> + Eq + TotalOrd,
+ V: Encodable<S, E> + Eq
+> Encodable<S, E> for TreeMap<K, V> {
+ fn encode(&self, e: &mut S) -> Result<(), E> {
e.emit_map(self.len(), |e| {
let mut i = 0;
for (key, val) in self.iter() {
- e.emit_map_elt_key(i, |e| key.encode(e));
- e.emit_map_elt_val(i, |e| val.encode(e));
+ try!(e.emit_map_elt_key(i, |e| key.encode(e)));
+ try!(e.emit_map_elt_val(i, |e| val.encode(e)));
i += 1;
}
+ Ok(())
})
}
}
impl<
- D: Decoder,
- K: Decodable<D> + Eq + TotalOrd,
- V: Decodable<D> + Eq
-> Decodable<D> for TreeMap<K, V> {
- fn decode(d: &mut D) -> TreeMap<K, V> {
+ E,
+ D: Decoder<E>,
+ K: Decodable<D, E> + Eq + TotalOrd,
+ V: Decodable<D, E> + Eq
+> Decodable<D, E> for TreeMap<K, V> {
+ fn decode(d: &mut D) -> Result<TreeMap<K, V>, E> {
d.read_map(|d, len| {
let mut map = TreeMap::new();
for i in range(0u, len) {
- let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
- let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
+ let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
+ let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
map.insert(key, val);
}
- map
+ Ok(map)
})
}
}
impl<
- S: Encoder,
- T: Encodable<S> + Eq + TotalOrd
-> Encodable<S> for TreeSet<T> {
- fn encode(&self, s: &mut S) {
+ E,
+ S: Encoder<E>,
+ T: Encodable<S, E> + Eq + TotalOrd
+> Encodable<S, E> for TreeSet<T> {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_seq(self.len(), |s| {
let mut i = 0;
for e in self.iter() {
- s.emit_seq_elt(i, |s| e.encode(s));
+ try!(s.emit_seq_elt(i, |s| e.encode(s)));
i += 1;
}
+ Ok(())
})
}
}
impl<
- D: Decoder,
- T: Decodable<D> + Eq + TotalOrd
-> Decodable<D> for TreeSet<T> {
- fn decode(d: &mut D) -> TreeSet<T> {
+ E,
+ D: Decoder<E>,
+ T: Decodable<D, E> + Eq + TotalOrd
+> Decodable<D, E> for TreeSet<T> {
+ fn decode(d: &mut D) -> Result<TreeSet<T>, E> {
d.read_seq(|d, len| {
let mut set = TreeSet::new();
for i in range(0u, len) {
- set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
+ set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
- set
+ Ok(set)
})
}
}
impl<
- S: Encoder,
- T: Encodable<S> + CLike
-> Encodable<S> for EnumSet<T> {
- fn encode(&self, s: &mut S) {
+ E,
+ S: Encoder<E>,
+ T: Encodable<S, E> + CLike
+> Encodable<S, E> for EnumSet<T> {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
let mut bits = 0;
for item in self.iter() {
bits |= item.to_uint();
}
- s.emit_uint(bits);
+ s.emit_uint(bits)
}
}
impl<
- D: Decoder,
- T: Decodable<D> + CLike
-> Decodable<D> for EnumSet<T> {
- fn decode(d: &mut D) -> EnumSet<T> {
- let bits = d.read_uint();
+ E,
+ D: Decoder<E>,
+ T: Decodable<D, E> + CLike
+> Decodable<D, E> for EnumSet<T> {
+ fn decode(d: &mut D) -> Result<EnumSet<T>, E> {
+ let bits = try!(d.read_uint());
let mut set = EnumSet::empty();
for bit in range(0, uint::BITS) {
if bits & (1 << bit) != 0 {
set.add(CLike::from_uint(1 << bit));
}
}
- set
+ Ok(set)
}
}
impl<
- E: Encoder,
- K: Encodable<E> + Hash<S> + TotalEq,
- V: Encodable<E>,
- S,
- H: Hasher<S>
-> Encodable<E> for HashMap<K, V, H> {
- fn encode(&self, e: &mut E) {
+ E,
+ S: Encoder<E>,
+ K: Encodable<S, E> + Hash<X> + TotalEq,
+ V: Encodable<S, E>,
+ X,
+ H: Hasher<X>
+> Encodable<S, E> for HashMap<K, V, H> {
+ fn encode(&self, e: &mut S) -> Result<(), E> {
e.emit_map(self.len(), |e| {
let mut i = 0;
for (key, val) in self.iter() {
- e.emit_map_elt_key(i, |e| key.encode(e));
- e.emit_map_elt_val(i, |e| val.encode(e));
+ try!(e.emit_map_elt_key(i, |e| key.encode(e)));
+ try!(e.emit_map_elt_val(i, |e| val.encode(e)));
i += 1;
}
+ Ok(())
})
}
}
impl<
- D: Decoder,
- K: Decodable<D> + Hash<S> + TotalEq,
- V: Decodable<D>,
+ E,
+ D: Decoder<E>,
+ K: Decodable<D, E> + Hash<S> + TotalEq,
+ V: Decodable<D, E>,
S,
H: Hasher<S> + Default
-> Decodable<D> for HashMap<K, V, H> {
- fn decode(d: &mut D) -> HashMap<K, V, H> {
+> Decodable<D, E> for HashMap<K, V, H> {
+ fn decode(d: &mut D) -> Result<HashMap<K, V, H>, E> {
d.read_map(|d, len| {
let hasher = Default::default();
let mut map = HashMap::with_capacity_and_hasher(len, hasher);
for i in range(0u, len) {
- let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
- let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
+ let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
+ let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
map.insert(key, val);
}
- map
+ Ok(map)
})
}
}
impl<
- E: Encoder,
- T: Encodable<E> + Hash<S> + TotalEq,
- S,
- H: Hasher<S>
-> Encodable<E> for HashSet<T, H> {
- fn encode(&self, s: &mut E) {
+ E,
+ S: Encoder<E>,
+ T: Encodable<S, E> + Hash<X> + TotalEq,
+ X,
+ H: Hasher<X>
+> Encodable<S, E> for HashSet<T, H> {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_seq(self.len(), |s| {
let mut i = 0;
for e in self.iter() {
- s.emit_seq_elt(i, |s| e.encode(s));
+ try!(s.emit_seq_elt(i, |s| e.encode(s)));
i += 1;
}
+ Ok(())
})
}
}
impl<
- D: Decoder,
- T: Decodable<D> + Hash<S> + TotalEq,
+ E,
+ D: Decoder<E>,
+ T: Decodable<D, E> + Hash<S> + TotalEq,
S,
H: Hasher<S> + Default
-> Decodable<D> for HashSet<T, H> {
- fn decode(d: &mut D) -> HashSet<T, H> {
+> Decodable<D, E> for HashSet<T, H> {
+ fn decode(d: &mut D) -> Result<HashSet<T, H>, E> {
d.read_seq(|d, len| {
let mut set = HashSet::with_capacity_and_hasher(len, Default::default());
for i in range(0u, len) {
- set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
+ set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
- set
+ Ok(set)
})
}
}
impl<
- E: Encoder,
- V: Encodable<E>
-> Encodable<E> for TrieMap<V> {
- fn encode(&self, e: &mut E) {
+ E,
+ S: Encoder<E>,
+ V: Encodable<S, E>
+> Encodable<S, E> for TrieMap<V> {
+ fn encode(&self, e: &mut S) -> Result<(), E> {
e.emit_map(self.len(), |e| {
for (i, (key, val)) in self.iter().enumerate() {
- e.emit_map_elt_key(i, |e| key.encode(e));
- e.emit_map_elt_val(i, |e| val.encode(e));
+ try!(e.emit_map_elt_key(i, |e| key.encode(e)));
+ try!(e.emit_map_elt_val(i, |e| val.encode(e)));
}
- });
+ Ok(())
+ })
}
}
impl<
- D: Decoder,
- V: Decodable<D>
-> Decodable<D> for TrieMap<V> {
- fn decode(d: &mut D) -> TrieMap<V> {
+ E,
+ D: Decoder<E>,
+ V: Decodable<D, E>
+> Decodable<D, E> for TrieMap<V> {
+ fn decode(d: &mut D) -> Result<TrieMap<V>, E> {
d.read_map(|d, len| {
let mut map = TrieMap::new();
for i in range(0u, len) {
- let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
- let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
+ let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
+ let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
map.insert(key, val);
}
- map
+ Ok(map)
})
}
}
-impl<S: Encoder> Encodable<S> for TrieSet {
- fn encode(&self, s: &mut S) {
+impl<E, S: Encoder<E>> Encodable<S, E> for TrieSet {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
- s.emit_seq_elt(i, |s| e.encode(s));
+ try!(s.emit_seq_elt(i, |s| e.encode(s)));
}
+ Ok(())
})
}
}
-impl<D: Decoder> Decodable<D> for TrieSet {
- fn decode(d: &mut D) -> TrieSet {
+impl<E, D: Decoder<E>> Decodable<D, E> for TrieSet {
+ fn decode(d: &mut D) -> Result<TrieSet, E> {
d.read_seq(|d, len| {
let mut set = TrieSet::new();
for i in range(0u, len) {
- set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
+ set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
- set
+ Ok(set)
})
}
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Implementations of serialization for structures found in libcollections
+
+use std::uint;
+use std::default::Default;
+use std::hash::{Hash, Hasher};
+
+use {Decodable, Encodable, Decoder, Encoder};
+use collections::{DList, RingBuf, TreeMap, TreeSet, Deque, HashMap, HashSet,
+ TrieMap, TrieSet};
+use collections::enum_set::{EnumSet, CLike};
+
+impl<
+ S: Encoder,
+ T: Encodable<S>
+> Encodable<S> for DList<T> {
+ fn encode(&self, s: &mut S) {
+ s.emit_seq(self.len(), |s| {
+ for (i, e) in self.iter().enumerate() {
+ s.emit_seq_elt(i, |s| e.encode(s));
+ }
+ })
+ }
+}
+
+impl<D:Decoder,T:Decodable<D>> Decodable<D> for DList<T> {
+ fn decode(d: &mut D) -> DList<T> {
+ let mut list = DList::new();
+ d.read_seq(|d, len| {
+ for i in range(0u, len) {
+ list.push_back(d.read_seq_elt(i, |d| Decodable::decode(d)));
+ }
+ });
+ list
+ }
+}
+
+impl<
+ S: Encoder,
+ T: Encodable<S>
+> Encodable<S> for RingBuf<T> {
+ fn encode(&self, s: &mut S) {
+ s.emit_seq(self.len(), |s| {
+ for (i, e) in self.iter().enumerate() {
+ s.emit_seq_elt(i, |s| e.encode(s));
+ }
+ })
+ }
+}
+
+impl<D:Decoder,T:Decodable<D>> Decodable<D> for RingBuf<T> {
+ fn decode(d: &mut D) -> RingBuf<T> {
+ let mut deque = RingBuf::new();
+ d.read_seq(|d, len| {
+ for i in range(0u, len) {
+ deque.push_back(d.read_seq_elt(i, |d| Decodable::decode(d)));
+ }
+ });
+ deque
+ }
+}
+
+impl<
+ E: Encoder,
+ K: Encodable<E> + Eq + TotalOrd,
+ V: Encodable<E> + Eq
+> Encodable<E> for TreeMap<K, V> {
+ fn encode(&self, e: &mut E) {
+ e.emit_map(self.len(), |e| {
+ let mut i = 0;
+ for (key, val) in self.iter() {
+ e.emit_map_elt_key(i, |e| key.encode(e));
+ e.emit_map_elt_val(i, |e| val.encode(e));
+ i += 1;
+ }
+ })
+ }
+}
+
+impl<
+ D: Decoder,
+ K: Decodable<D> + Eq + TotalOrd,
+ V: Decodable<D> + Eq
+> Decodable<D> for TreeMap<K, V> {
+ fn decode(d: &mut D) -> TreeMap<K, V> {
+ d.read_map(|d, len| {
+ let mut map = TreeMap::new();
+ for i in range(0u, len) {
+ let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
+ let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
+ map.insert(key, val);
+ }
+ map
+ })
+ }
+}
+
+impl<
+ S: Encoder,
+ T: Encodable<S> + Eq + TotalOrd
+> Encodable<S> for TreeSet<T> {
+ fn encode(&self, s: &mut S) {
+ s.emit_seq(self.len(), |s| {
+ let mut i = 0;
+ for e in self.iter() {
+ s.emit_seq_elt(i, |s| e.encode(s));
+ i += 1;
+ }
+ })
+ }
+}
+
+impl<
+ D: Decoder,
+ T: Decodable<D> + Eq + TotalOrd
+> Decodable<D> for TreeSet<T> {
+ fn decode(d: &mut D) -> TreeSet<T> {
+ d.read_seq(|d, len| {
+ let mut set = TreeSet::new();
+ for i in range(0u, len) {
+ set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
+ }
+ set
+ })
+ }
+}
+
+impl<
+ S: Encoder,
+ T: Encodable<S> + CLike
+> Encodable<S> for EnumSet<T> {
+ fn encode(&self, s: &mut S) {
+ let mut bits = 0;
+ for item in self.iter() {
+ bits |= item.to_uint();
+ }
+ s.emit_uint(bits);
+ }
+}
+
+impl<
+ D: Decoder,
+ T: Decodable<D> + CLike
+> Decodable<D> for EnumSet<T> {
+ fn decode(d: &mut D) -> EnumSet<T> {
+ let bits = d.read_uint();
+ let mut set = EnumSet::empty();
+ for bit in range(0, uint::BITS) {
+ if bits & (1 << bit) != 0 {
+ set.add(CLike::from_uint(1 << bit));
+ }
+ }
+ set
+ }
+}
+
+impl<
+ E: Encoder,
+ K: Encodable<E> + Hash<S> + TotalEq,
+ V: Encodable<E>,
+ S,
+ H: Hasher<S>
+> Encodable<E> for HashMap<K, V, H> {
+ fn encode(&self, e: &mut E) {
+ e.emit_map(self.len(), |e| {
+ let mut i = 0;
+ for (key, val) in self.iter() {
+ e.emit_map_elt_key(i, |e| key.encode(e));
+ e.emit_map_elt_val(i, |e| val.encode(e));
+ i += 1;
+ }
+ })
+ }
+}
+
+impl<
+ D: Decoder,
+ K: Decodable<D> + Hash<S> + TotalEq,
+ V: Decodable<D>,
+ S,
+ H: Hasher<S> + Default
+> Decodable<D> for HashMap<K, V, H> {
+ fn decode(d: &mut D) -> HashMap<K, V, H> {
+ d.read_map(|d, len| {
+ let hasher = Default::default();
+ let mut map = HashMap::with_capacity_and_hasher(len, hasher);
+ for i in range(0u, len) {
+ let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
+ let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
+ map.insert(key, val);
+ }
+ map
+ })
+ }
+}
+
+impl<
+ E: Encoder,
+ T: Encodable<E> + Hash<S> + TotalEq,
+ S,
+ H: Hasher<S>
+> Encodable<E> for HashSet<T, H> {
+ fn encode(&self, s: &mut E) {
+ s.emit_seq(self.len(), |s| {
+ let mut i = 0;
+ for e in self.iter() {
+ s.emit_seq_elt(i, |s| e.encode(s));
+ i += 1;
+ }
+ })
+ }
+}
+
+impl<
+ D: Decoder,
+ T: Decodable<D> + Hash<S> + TotalEq,
+ S,
+ H: Hasher<S> + Default
+> Decodable<D> for HashSet<T, H> {
+ fn decode(d: &mut D) -> HashSet<T, H> {
+ d.read_seq(|d, len| {
+ let mut set = HashSet::with_capacity_and_hasher(len, Default::default());
+ for i in range(0u, len) {
+ set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
+ }
+ set
+ })
+ }
+}
+
+impl<
+ E: Encoder,
+ V: Encodable<E>
+> Encodable<E> for TrieMap<V> {
+ fn encode(&self, e: &mut E) {
+ e.emit_map(self.len(), |e| {
+ for (i, (key, val)) in self.iter().enumerate() {
+ e.emit_map_elt_key(i, |e| key.encode(e));
+ e.emit_map_elt_val(i, |e| val.encode(e));
+ }
+ });
+ }
+}
+
+impl<
+ D: Decoder,
+ V: Decodable<D>
+> Decodable<D> for TrieMap<V> {
+ fn decode(d: &mut D) -> TrieMap<V> {
+ d.read_map(|d, len| {
+ let mut map = TrieMap::new();
+ for i in range(0u, len) {
+ let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
+ let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
+ map.insert(key, val);
+ }
+ map
+ })
+ }
+}
+
+impl<S: Encoder> Encodable<S> for TrieSet {
+ fn encode(&self, s: &mut S) {
+ s.emit_seq(self.len(), |s| {
+ for (i, e) in self.iter().enumerate() {
+ s.emit_seq_elt(i, |s| e.encode(s));
+ }
+ })
+ }
+}
+
+impl<D: Decoder> Decodable<D> for TrieSet {
+ fn decode(d: &mut D) -> TrieSet {
+ d.read_seq(|d, len| {
+ let mut set = TrieSet::new();
+ for i in range(0u, len) {
+ set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
+ }
+ set
+ })
+ }
+}
+
#[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
EsLabel, // Used only when debugging
}
+
+#[deriving(Show)]
+pub enum Error {
+ IntTooBig(uint),
+ Expected(~str),
+ IoError(io::IoError)
+}
// --------------------------------------
pub mod reader {
use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey,
EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8,
EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint,
- EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc };
+ EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc, Error, IntTooBig,
+ Expected };
+ pub type DecodeResult<T> = Result<T, Error>;
// ebml reading
+ macro_rules! try_or(
+ ($e:expr, $r:expr) => (
+ match $e {
+ Ok(e) => e,
+ Err(e) => {
+ debug!("ignored error: {}", e);
+ return $r
+ }
+ }
+ )
+ )
+
pub struct Res {
val: uint,
next: uint
}
#[inline(never)]
- fn vuint_at_slow(data: &[u8], start: uint) -> Res {
+ fn vuint_at_slow(data: &[u8], start: uint) -> DecodeResult<Res> {
let a = data[start];
if a & 0x80u8 != 0u8 {
- return Res {val: (a & 0x7fu8) as uint, next: start + 1u};
+ return Ok(Res {val: (a & 0x7fu8) as uint, next: start + 1u});
}
if a & 0x40u8 != 0u8 {
- return Res {val: ((a & 0x3fu8) as uint) << 8u |
+ return Ok(Res {val: ((a & 0x3fu8) as uint) << 8u |
(data[start + 1u] as uint),
- next: start + 2u};
+ next: start + 2u});
}
if a & 0x20u8 != 0u8 {
- return Res {val: ((a & 0x1fu8) as uint) << 16u |
+ return Ok(Res {val: ((a & 0x1fu8) as uint) << 16u |
(data[start + 1u] as uint) << 8u |
(data[start + 2u] as uint),
- next: start + 3u};
+ next: start + 3u});
}
if a & 0x10u8 != 0u8 {
- return Res {val: ((a & 0x0fu8) as uint) << 24u |
+ return Ok(Res {val: ((a & 0x0fu8) as uint) << 24u |
(data[start + 1u] as uint) << 16u |
(data[start + 2u] as uint) << 8u |
(data[start + 3u] as uint),
- next: start + 4u};
+ next: start + 4u});
}
- fail!("vint too big");
+ Err(IntTooBig(a as uint))
}
- pub fn vuint_at(data: &[u8], start: uint) -> Res {
+ pub fn vuint_at(data: &[u8], start: uint) -> DecodeResult<Res> {
use std::mem::from_be32;
if data.len() - start < 4 {
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)
- }
+ })
}
}
Doc { data: data, start: 0u, end: data.len() }
}
- pub fn doc_at<'a>(data: &'a [u8], start: uint) -> TaggedDoc<'a> {
- let elt_tag = vuint_at(data, start);
- let elt_size = vuint_at(data, elt_tag.next);
+ pub fn doc_at<'a>(data: &'a [u8], start: uint) -> DecodeResult<TaggedDoc<'a>> {
+ let elt_tag = try!(vuint_at(data, start));
+ let elt_size = try!(vuint_at(data, elt_tag.next));
let end = elt_size.next + elt_size.val;
- TaggedDoc {
+ Ok(TaggedDoc {
tag: elt_tag.val,
doc: Doc { data: data, start: elt_size.next, end: end }
- }
+ })
}
pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: uint) -> Option<Doc<'a>> {
let mut pos = d.start;
while pos < d.end {
- let elt_tag = vuint_at(d.data, pos);
- let elt_size = vuint_at(d.data, elt_tag.next);
+ let elt_tag = try_or!(vuint_at(d.data, pos), None);
+ let elt_size = try_or!(vuint_at(d.data, elt_tag.next), None);
pos = elt_size.next + elt_size.val;
if elt_tag.val == tg {
return Some(Doc { data: d.data, start: elt_size.next,
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) {
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,
}
impl<'doc> Decoder<'doc> {
- fn _check_label(&mut self, lbl: &str) {
+ fn _check_label(&mut self, lbl: &str) -> DecodeResult<()> {
if self.pos < self.parent.end {
let TaggedDoc { tag: r_tag, doc: r_doc } =
- doc_at(self.parent.data, self.pos);
+ try!(doc_at(self.parent.data, self.pos));
if r_tag == (EsLabel as uint) {
self.pos = r_doc.end;
let str = r_doc.as_str_slice();
if lbl != str {
- fail!("Expected label {} but found {}", lbl, str);
+ return Err(Expected(format!("Expected label {} but found {}", lbl, str)));
}
}
}
+ Ok(())
}
- fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> Doc<'doc> {
+ fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<Doc<'doc>> {
debug!(". next_doc(exp_tag={:?})", exp_tag);
if self.pos >= self.parent.end {
- fail!("no more documents in current node!");
+ return Err(Expected(format!("no more documents in current node!")));
}
let TaggedDoc { tag: r_tag, doc: r_doc } =
- doc_at(self.parent.data, self.pos);
+ try!(doc_at(self.parent.data, self.pos));
debug!("self.parent={}-{} self.pos={} r_tag={} r_doc={}-{}",
self.parent.start,
self.parent.end,
r_doc.start,
r_doc.end);
if r_tag != (exp_tag as uint) {
- fail!("expected EBML doc with tag {:?} but found tag {:?}",
- exp_tag, r_tag);
+ return Err(Expected(format!("expected EBML doc with tag {:?} but found tag {:?}",
+ exp_tag, r_tag)));
}
if r_doc.end > self.parent.end {
- fail!("invalid EBML, child extends to {:#x}, parent to {:#x}",
- r_doc.end, self.parent.end);
+ return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to {:#x}",
+ r_doc.end, self.parent.end)));
}
self.pos = r_doc.end;
- r_doc
+ Ok(r_doc)
}
fn push_doc<T>(&mut self, exp_tag: EbmlEncoderTag,
- f: |&mut Decoder<'doc>| -> T) -> T {
- let d = self.next_doc(exp_tag);
+ f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
+ let d = try!(self.next_doc(exp_tag));
let old_parent = self.parent;
let old_pos = self.pos;
self.parent = d;
self.pos = d.start;
- let r = f(self);
+ let r = try!(f(self));
self.parent = old_parent;
self.pos = old_pos;
- r
+ Ok(r)
}
- fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> uint {
- let r = doc_as_u32(self.next_doc(exp_tag));
+ fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<uint> {
+ let r = doc_as_u32(try!(self.next_doc(exp_tag)));
debug!("_next_uint exp_tag={:?} result={}", exp_tag, r);
- r as uint
+ Ok(r as uint)
}
- pub fn read_opaque<R>(&mut self, op: |&mut Decoder<'doc>, Doc| -> R) -> R {
- let doc = self.next_doc(EsOpaque);
+ pub fn read_opaque<R>(&mut self,
+ op: |&mut Decoder<'doc>, Doc| -> DecodeResult<R>) -> DecodeResult<R> {
+ let doc = try!(self.next_doc(EsOpaque));
let (old_parent, old_pos) = (self.parent, self.pos);
self.parent = doc;
self.pos = doc.start;
- let result = op(self, doc);
+ let result = try!(op(self, doc));
self.parent = old_parent;
self.pos = old_pos;
- result
+ Ok(result)
}
}
- impl<'doc> serialize::Decoder for Decoder<'doc> {
- fn read_nil(&mut self) -> () { () }
+ impl<'doc> serialize::Decoder<Error> for Decoder<'doc> {
+ fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) }
- fn read_u64(&mut self) -> u64 { doc_as_u64(self.next_doc(EsU64)) }
- fn read_u32(&mut self) -> u32 { doc_as_u32(self.next_doc(EsU32)) }
- fn read_u16(&mut self) -> u16 { doc_as_u16(self.next_doc(EsU16)) }
- fn read_u8 (&mut self) -> u8 { doc_as_u8 (self.next_doc(EsU8 )) }
- fn read_uint(&mut self) -> uint {
- let v = doc_as_u64(self.next_doc(EsUint));
+ fn read_u64(&mut self) -> DecodeResult<u64> { Ok(doc_as_u64(try!(self.next_doc(EsU64)))) }
+ fn read_u32(&mut self) -> DecodeResult<u32> { Ok(doc_as_u32(try!(self.next_doc(EsU32)))) }
+ fn read_u16(&mut self) -> DecodeResult<u16> { Ok(doc_as_u16(try!(self.next_doc(EsU16)))) }
+ fn read_u8 (&mut self) -> DecodeResult<u8 > { Ok(doc_as_u8 (try!(self.next_doc(EsU8 )))) }
+ fn read_uint(&mut self) -> DecodeResult<uint> {
+ let v = doc_as_u64(try!(self.next_doc(EsUint)));
if v > (::std::uint::MAX as u64) {
- fail!("uint {} too large for this architecture", v);
+ Err(IntTooBig(v as uint))
+ } else {
+ Ok(v as uint)
}
- v as uint
}
- fn read_i64(&mut self) -> i64 {
- doc_as_u64(self.next_doc(EsI64)) as i64
+ fn read_i64(&mut self) -> DecodeResult<i64> {
+ Ok(doc_as_u64(try!(self.next_doc(EsI64))) as i64)
}
- fn read_i32(&mut self) -> i32 {
- doc_as_u32(self.next_doc(EsI32)) as i32
+ fn read_i32(&mut self) -> DecodeResult<i32> {
+ Ok(doc_as_u32(try!(self.next_doc(EsI32))) as i32)
}
- fn read_i16(&mut self) -> i16 {
- doc_as_u16(self.next_doc(EsI16)) as i16
+ fn read_i16(&mut self) -> DecodeResult<i16> {
+ Ok(doc_as_u16(try!(self.next_doc(EsI16))) as i16)
}
- fn read_i8 (&mut self) -> i8 {
- doc_as_u8(self.next_doc(EsI8 )) as i8
+ fn read_i8 (&mut self) -> DecodeResult<i8> {
+ Ok(doc_as_u8(try!(self.next_doc(EsI8 ))) as i8)
}
- fn read_int(&mut self) -> int {
- let v = doc_as_u64(self.next_doc(EsInt)) as i64;
+ fn read_int(&mut self) -> DecodeResult<int> {
+ let v = doc_as_u64(try!(self.next_doc(EsInt))) as i64;
if v > (int::MAX as i64) || v < (int::MIN as i64) {
debug!("FIXME \\#6122: Removing this makes this function miscompile");
- fail!("int {} out of range for this architecture", v);
+ Err(IntTooBig(v as uint))
+ } else {
+ Ok(v as int)
}
- v as int
}
- fn read_bool(&mut self) -> bool {
- doc_as_u8(self.next_doc(EsBool)) != 0
+ fn read_bool(&mut self) -> DecodeResult<bool> {
+ Ok(doc_as_u8(try!(self.next_doc(EsBool))) != 0)
}
- fn read_f64(&mut self) -> f64 {
- let bits = doc_as_u64(self.next_doc(EsF64));
- unsafe { transmute(bits) }
+ fn read_f64(&mut self) -> DecodeResult<f64> {
+ let bits = doc_as_u64(try!(self.next_doc(EsF64)));
+ Ok(unsafe { transmute(bits) })
}
- fn read_f32(&mut self) -> f32 {
- let bits = doc_as_u32(self.next_doc(EsF32));
- unsafe { transmute(bits) }
+ fn read_f32(&mut self) -> DecodeResult<f32> {
+ let bits = doc_as_u32(try!(self.next_doc(EsF32)));
+ Ok(unsafe { transmute(bits) })
}
- fn read_char(&mut self) -> char {
- char::from_u32(doc_as_u32(self.next_doc(EsChar))).unwrap()
+ fn read_char(&mut self) -> DecodeResult<char> {
+ Ok(char::from_u32(doc_as_u32(try!(self.next_doc(EsChar)))).unwrap())
}
- fn read_str(&mut self) -> ~str {
- self.next_doc(EsStr).as_str()
+ fn read_str(&mut self) -> DecodeResult<~str> {
+ Ok(try!(self.next_doc(EsStr)).as_str())
}
// Compound types:
- fn read_enum<T>(&mut self, name: &str, f: |&mut Decoder<'doc>| -> T) -> T {
+ fn read_enum<T>(&mut self,
+ name: &str,
+ f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
debug!("read_enum({})", name);
- self._check_label(name);
+ try!(self._check_label(name));
- let doc = self.next_doc(EsEnum);
+ let doc = try!(self.next_doc(EsEnum));
let (old_parent, old_pos) = (self.parent, self.pos);
self.parent = doc;
self.pos = self.parent.start;
- let result = f(self);
+ let result = try!(f(self));
self.parent = old_parent;
self.pos = old_pos;
- result
+ Ok(result)
}
fn read_enum_variant<T>(&mut self,
_: &[&str],
- f: |&mut Decoder<'doc>, uint| -> T)
- -> T {
+ f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_enum_variant()");
- let idx = self._next_uint(EsEnumVid);
+ let idx = try!(self._next_uint(EsEnumVid));
debug!(" idx={}", idx);
- let doc = self.next_doc(EsEnumBody);
+ let doc = try!(self.next_doc(EsEnumBody));
let (old_parent, old_pos) = (self.parent, self.pos);
self.parent = doc;
self.pos = self.parent.start;
- let result = f(self, idx);
+ let result = try!(f(self, idx));
self.parent = old_parent;
self.pos = old_pos;
- result
+ Ok(result)
}
fn read_enum_variant_arg<T>(&mut self,
idx: uint,
- f: |&mut Decoder<'doc>| -> T) -> T {
+ f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
debug!("read_enum_variant_arg(idx={})", idx);
f(self)
}
fn read_enum_struct_variant<T>(&mut self,
_: &[&str],
- f: |&mut Decoder<'doc>, uint| -> T)
- -> T {
+ f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_enum_struct_variant()");
- let idx = self._next_uint(EsEnumVid);
+ let idx = try!(self._next_uint(EsEnumVid));
debug!(" idx={}", idx);
- let doc = self.next_doc(EsEnumBody);
+ let doc = try!(self.next_doc(EsEnumBody));
let (old_parent, old_pos) = (self.parent, self.pos);
self.parent = doc;
self.pos = self.parent.start;
- let result = f(self, idx);
+ let result = try!(f(self, idx));
self.parent = old_parent;
self.pos = old_pos;
- result
+ Ok(result)
}
fn read_enum_struct_variant_field<T>(&mut self,
name: &str,
idx: uint,
- f: |&mut Decoder<'doc>| -> T)
- -> T {
+ f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
f(self)
}
fn read_struct<T>(&mut self,
name: &str,
_: uint,
- f: |&mut Decoder<'doc>| -> T)
- -> T {
+ f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_struct(name={})", name);
f(self)
}
fn read_struct_field<T>(&mut self,
name: &str,
idx: uint,
- f: |&mut Decoder<'doc>| -> T)
- -> T {
+ f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_struct_field(name={}, idx={})", name, idx);
- self._check_label(name);
+ try!(self._check_label(name));
f(self)
}
- fn read_tuple<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T {
+ fn read_tuple<T>(&mut self,
+ f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
debug!("read_tuple()");
self.read_seq(f)
}
- fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
- -> T {
+ fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_tuple_arg(idx={})", idx);
self.read_seq_elt(idx, f)
}
fn read_tuple_struct<T>(&mut self,
name: &str,
- f: |&mut Decoder<'doc>, uint| -> T)
- -> T {
+ f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_tuple_struct(name={})", name);
self.read_tuple(f)
}
fn read_tuple_struct_arg<T>(&mut self,
idx: uint,
- f: |&mut Decoder<'doc>| -> T)
- -> T {
+ f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_tuple_struct_arg(idx={})", idx);
self.read_tuple_arg(idx, f)
}
- fn read_option<T>(&mut self, f: |&mut Decoder<'doc>, bool| -> T) -> T {
+ fn read_option<T>(&mut self,
+ f: |&mut Decoder<'doc>, bool| -> DecodeResult<T>) -> DecodeResult<T> {
debug!("read_option()");
self.read_enum("Option", |this| {
this.read_enum_variant(["None", "Some"], |this, idx| {
match idx {
0 => f(this, false),
1 => f(this, true),
- _ => fail!(),
+ _ => Err(Expected(format!("Expected None or Some"))),
}
})
})
}
- fn read_seq<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T {
+ fn read_seq<T>(&mut self,
+ f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
debug!("read_seq()");
self.push_doc(EsVec, |d| {
- let len = d._next_uint(EsVecLen);
+ let len = try!(d._next_uint(EsVecLen));
debug!(" len={}", len);
f(d, len)
})
}
- fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
- -> T {
+ fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_seq_elt(idx={})", idx);
self.push_doc(EsVecElt, f)
}
- fn read_map<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T {
+ fn read_map<T>(&mut self,
+ f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
debug!("read_map()");
self.push_doc(EsMap, |d| {
- let len = d._next_uint(EsMapLen);
+ let len = try!(d._next_uint(EsMapLen));
debug!(" len={}", len);
f(d, len)
})
}
- fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
- -> T {
+ fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_map_elt_key(idx={})", idx);
self.push_doc(EsMapKey, f)
}
- fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
- -> T {
+ fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_map_elt_val(idx={})", idx);
self.push_doc(EsMapVal, f)
}
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,
use serialize;
+
+ pub type EncodeResult = io::IoResult<()>;
+
// ebml writing
- pub struct Encoder<'a> {
- // FIXME(#5665): this should take a trait object. Note that if you
- // delete this comment you should consider removing the
- // unwrap()'s below of the results of the calls to
- // write(). We're guaranteed that writing into a MemWriter
- // won't fail, but this is not true for all I/O streams in
- // general.
- writer: &'a mut MemWriter,
+ pub struct Encoder<'a, W> {
+ writer: &'a mut W,
priv size_positions: ~[uint],
- last_error: io::IoResult<()>,
}
- fn write_sized_vuint(w: &mut MemWriter, n: uint, size: uint) {
+ fn write_sized_vuint<W: Writer>(w: &mut W, n: uint, size: uint) -> EncodeResult {
match size {
1u => w.write(&[0x80u8 | (n as u8)]),
2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]),
n as u8]),
4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8,
(n >> 8_u) as u8, n as u8]),
- _ => fail!("vint to write too big: {}", n)
- }.unwrap()
+ _ => Err(io::IoError {
+ kind: io::OtherIoError,
+ desc: "int too big",
+ detail: Some(format!("{}", n))
+ })
+ }
}
- fn write_vuint(w: &mut MemWriter, n: uint) {
- if n < 0x7f_u { write_sized_vuint(w, n, 1u); return; }
- if n < 0x4000_u { write_sized_vuint(w, n, 2u); return; }
- if n < 0x200000_u { write_sized_vuint(w, n, 3u); return; }
- if n < 0x10000000_u { write_sized_vuint(w, n, 4u); return; }
- fail!("vint to write too big: {}", n);
+ fn write_vuint<W: Writer>(w: &mut W, n: uint) -> EncodeResult {
+ if n < 0x7f_u { return write_sized_vuint(w, n, 1u); }
+ if n < 0x4000_u { return write_sized_vuint(w, n, 2u); }
+ if n < 0x200000_u { return write_sized_vuint(w, n, 3u); }
+ if n < 0x10000000_u { return write_sized_vuint(w, n, 4u); }
+ Err(io::IoError {
+ kind: io::OtherIoError,
+ desc: "int too big",
+ detail: Some(format!("{}", n))
+ })
}
- pub fn Encoder<'a>(w: &'a mut MemWriter) -> Encoder<'a> {
+ pub fn Encoder<'a, W: Writer + Seek>(w: &'a mut W) -> Encoder<'a, W> {
let size_positions: ~[uint] = ~[];
Encoder {
writer: w,
size_positions: size_positions,
- last_error: Ok(()),
}
}
// FIXME (#2741): Provide a function to write the standard ebml header.
- impl<'a> Encoder<'a> {
+ impl<'a, W: Writer + Seek> Encoder<'a, W> {
/// FIXME(pcwalton): Workaround for badness in trans. DO NOT USE ME.
- pub unsafe fn unsafe_clone(&self) -> Encoder<'a> {
+ pub unsafe fn unsafe_clone(&self) -> Encoder<'a, W> {
Encoder {
writer: cast::transmute_copy(&self.writer),
size_positions: self.size_positions.clone(),
- last_error: Ok(()),
}
}
- pub fn start_tag(&mut self, tag_id: uint) {
+ pub fn start_tag(&mut self, tag_id: uint) -> EncodeResult {
debug!("Start tag {}", tag_id);
// Write the enum ID:
- write_vuint(self.writer, tag_id);
+ try!(write_vuint(self.writer, tag_id));
// Write a placeholder four-byte size.
self.size_positions.push(try!(self.writer.tell()) as uint);
let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8];
- try!(self.writer.write(zeroes));
+ self.writer.write(zeroes)
}
- pub fn end_tag(&mut self) {
+ pub fn end_tag(&mut self) -> EncodeResult {
let last_size_pos = self.size_positions.pop().unwrap();
let cur_pos = try!(self.writer.tell());
try!(self.writer.seek(last_size_pos as i64, io::SeekSet));
let size = cur_pos as uint - last_size_pos - 4;
- write_sized_vuint(self.writer, size, 4u);
- try!(self.writer.seek(cur_pos as i64, io::SeekSet));
+ try!(write_sized_vuint(self.writer, size, 4u));
+ let r = try!(self.writer.seek(cur_pos as i64, io::SeekSet));
debug!("End tag (size = {})", size);
+ Ok(r)
}
- pub fn wr_tag(&mut self, tag_id: uint, blk: ||) {
- self.start_tag(tag_id);
- blk();
- self.end_tag();
+ pub fn wr_tag(&mut self, tag_id: uint, blk: || -> EncodeResult) -> EncodeResult {
+ try!(self.start_tag(tag_id));
+ try!(blk());
+ self.end_tag()
}
- pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) {
- write_vuint(self.writer, tag_id);
- write_vuint(self.writer, b.len());
- self.writer.write(b).unwrap();
+ pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) -> EncodeResult {
+ try!(write_vuint(self.writer, tag_id));
+ try!(write_vuint(self.writer, b.len()));
+ self.writer.write(b)
}
- pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) {
+ pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) -> EncodeResult {
u64_to_be_bytes(v, 8u, |v| {
- self.wr_tagged_bytes(tag_id, v);
+ self.wr_tagged_bytes(tag_id, v)
})
}
- pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) {
+ pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) -> EncodeResult{
u64_to_be_bytes(v as u64, 4u, |v| {
- self.wr_tagged_bytes(tag_id, v);
+ self.wr_tagged_bytes(tag_id, v)
})
}
- pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) {
+ pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) -> EncodeResult {
u64_to_be_bytes(v as u64, 2u, |v| {
- self.wr_tagged_bytes(tag_id, v);
+ self.wr_tagged_bytes(tag_id, v)
})
}
- pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) {
- self.wr_tagged_bytes(tag_id, &[v]);
+ pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) -> EncodeResult {
+ self.wr_tagged_bytes(tag_id, &[v])
}
- pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) {
+ pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) -> EncodeResult {
u64_to_be_bytes(v as u64, 8u, |v| {
- self.wr_tagged_bytes(tag_id, v);
+ self.wr_tagged_bytes(tag_id, v)
})
}
- pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) {
+ pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) -> EncodeResult {
u64_to_be_bytes(v as u64, 4u, |v| {
- self.wr_tagged_bytes(tag_id, v);
+ self.wr_tagged_bytes(tag_id, v)
})
}
- pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) {
+ pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) -> EncodeResult {
u64_to_be_bytes(v as u64, 2u, |v| {
- self.wr_tagged_bytes(tag_id, v);
+ self.wr_tagged_bytes(tag_id, v)
})
}
- pub fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) {
- self.wr_tagged_bytes(tag_id, &[v as u8]);
+ pub fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) -> EncodeResult {
+ self.wr_tagged_bytes(tag_id, &[v as u8])
}
- pub fn wr_tagged_str(&mut self, tag_id: uint, v: &str) {
- self.wr_tagged_bytes(tag_id, v.as_bytes());
+ pub fn wr_tagged_str(&mut self, tag_id: uint, v: &str) -> EncodeResult {
+ self.wr_tagged_bytes(tag_id, v.as_bytes())
}
- pub fn wr_bytes(&mut self, b: &[u8]) {
+ pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult {
debug!("Write {} bytes", b.len());
- self.writer.write(b).unwrap();
+ self.writer.write(b)
}
- pub fn wr_str(&mut self, s: &str) {
+ pub fn wr_str(&mut self, s: &str) -> EncodeResult {
debug!("Write str: {}", s);
- self.writer.write(s.as_bytes()).unwrap();
+ self.writer.write(s.as_bytes())
}
}
// 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
// labels and then they will be checked by decoder to
// try and check failures more quickly.
if DEBUG { self.wr_tagged_str(EsLabel as uint, label) }
+ else { Ok(()) }
}
- pub fn emit_opaque(&mut self, f: |&mut Encoder|) {
- self.start_tag(EsOpaque as uint);
- f(self);
- self.end_tag();
+ pub fn emit_opaque(&mut self, f: |&mut Encoder<W>| -> EncodeResult) -> EncodeResult {
+ try!(self.start_tag(EsOpaque as uint));
+ try!(f(self));
+ self.end_tag()
}
}
- impl<'a> serialize::Encoder for Encoder<'a> {
- fn emit_nil(&mut self) {}
+ impl<'a, W: Writer + Seek> serialize::Encoder<io::IoError> for Encoder<'a, W> {
+ fn emit_nil(&mut self) -> EncodeResult {
+ Ok(())
+ }
- fn emit_uint(&mut self, v: uint) {
- self.wr_tagged_u64(EsUint as uint, v as u64);
+ fn emit_uint(&mut self, v: uint) -> EncodeResult {
+ self.wr_tagged_u64(EsUint as uint, v as u64)
}
- fn emit_u64(&mut self, v: u64) {
- self.wr_tagged_u64(EsU64 as uint, v);
+ fn emit_u64(&mut self, v: u64) -> EncodeResult {
+ self.wr_tagged_u64(EsU64 as uint, v)
}
- fn emit_u32(&mut self, v: u32) {
- self.wr_tagged_u32(EsU32 as uint, v);
+ fn emit_u32(&mut self, v: u32) -> EncodeResult {
+ self.wr_tagged_u32(EsU32 as uint, v)
}
- fn emit_u16(&mut self, v: u16) {
- self.wr_tagged_u16(EsU16 as uint, v);
+ fn emit_u16(&mut self, v: u16) -> EncodeResult {
+ self.wr_tagged_u16(EsU16 as uint, v)
}
- fn emit_u8(&mut self, v: u8) {
- self.wr_tagged_u8(EsU8 as uint, v);
+ fn emit_u8(&mut self, v: u8) -> EncodeResult {
+ self.wr_tagged_u8(EsU8 as uint, v)
}
- fn emit_int(&mut self, v: int) {
- self.wr_tagged_i64(EsInt as uint, v as i64);
+ fn emit_int(&mut self, v: int) -> EncodeResult {
+ self.wr_tagged_i64(EsInt as uint, v as i64)
}
- fn emit_i64(&mut self, v: i64) {
- self.wr_tagged_i64(EsI64 as uint, v);
+ fn emit_i64(&mut self, v: i64) -> EncodeResult {
+ self.wr_tagged_i64(EsI64 as uint, v)
}
- fn emit_i32(&mut self, v: i32) {
- self.wr_tagged_i32(EsI32 as uint, v);
+ fn emit_i32(&mut self, v: i32) -> EncodeResult {
+ self.wr_tagged_i32(EsI32 as uint, v)
}
- fn emit_i16(&mut self, v: i16) {
- self.wr_tagged_i16(EsI16 as uint, v);
+ fn emit_i16(&mut self, v: i16) -> EncodeResult {
+ self.wr_tagged_i16(EsI16 as uint, v)
}
- fn emit_i8(&mut self, v: i8) {
- self.wr_tagged_i8(EsI8 as uint, v);
+ fn emit_i8(&mut self, v: i8) -> EncodeResult {
+ self.wr_tagged_i8(EsI8 as uint, v)
}
- fn emit_bool(&mut self, v: bool) {
+ fn emit_bool(&mut self, v: bool) -> EncodeResult {
self.wr_tagged_u8(EsBool as uint, v as u8)
}
- fn emit_f64(&mut self, v: f64) {
+ fn emit_f64(&mut self, v: f64) -> EncodeResult {
let bits = unsafe { cast::transmute(v) };
- self.wr_tagged_u64(EsF64 as uint, bits);
+ self.wr_tagged_u64(EsF64 as uint, bits)
}
- fn emit_f32(&mut self, v: f32) {
+ fn emit_f32(&mut self, v: f32) -> EncodeResult {
let bits = unsafe { cast::transmute(v) };
- self.wr_tagged_u32(EsF32 as uint, bits);
+ self.wr_tagged_u32(EsF32 as uint, bits)
}
- fn emit_char(&mut self, v: char) {
- self.wr_tagged_u32(EsChar as uint, v as u32);
+ fn emit_char(&mut self, v: char) -> EncodeResult {
+ self.wr_tagged_u32(EsChar as uint, v as u32)
}
- fn emit_str(&mut self, v: &str) {
+ fn emit_str(&mut self, v: &str) -> EncodeResult {
self.wr_tagged_str(EsStr as uint, v)
}
- fn emit_enum(&mut self, name: &str, f: |&mut Encoder<'a>|) {
- self._emit_label(name);
- self.start_tag(EsEnum as uint);
- f(self);
- self.end_tag();
+ fn emit_enum(&mut self,
+ name: &str,
+ f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
+ try!(self._emit_label(name));
+ try!(self.start_tag(EsEnum as uint));
+ try!(f(self));
+ self.end_tag()
}
fn emit_enum_variant(&mut self,
_: &str,
v_id: uint,
_: uint,
- f: |&mut Encoder<'a>|) {
- self._emit_tagged_uint(EsEnumVid, v_id);
- self.start_tag(EsEnumBody as uint);
- f(self);
- self.end_tag();
+ f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
+ try!(self._emit_tagged_uint(EsEnumVid, v_id));
+ try!(self.start_tag(EsEnumBody as uint));
+ try!(f(self));
+ self.end_tag()
}
- fn emit_enum_variant_arg(&mut self, _: uint, f: |&mut Encoder<'a>|) {
+ fn emit_enum_variant_arg(&mut self,
+ _: uint,
+ f: |&mut Encoder<'a, W>| -> EncodeResult) -> EncodeResult {
f(self)
}
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()
}
}
}
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);
}
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);
}
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;
}
});
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;
}
});
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;
}
});
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;
}
});
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[allow(missing_doc)];
+
+use std::str;
+
+macro_rules! try( ($e:expr) => (
+ match $e { Ok(e) => e, Err(e) => { self.last_error = Err(e); return } }
+) )
+
+// Simple Extensible Binary Markup Language (ebml) reader and writer on a
+// cursor model. See the specification here:
+// http://www.matroska.org/technical/specs/rfc/index.html
+
+// Common data structures
+#[deriving(Clone)]
+pub struct Doc<'a> {
+ data: &'a [u8],
+ start: uint,
+ end: uint,
+}
+
+impl<'doc> Doc<'doc> {
+ pub fn get<'a>(&'a self, tag: uint) -> Doc<'a> {
+ reader::get_doc(*self, tag)
+ }
+
+ pub fn as_str_slice<'a>(&'a self) -> &'a str {
+ str::from_utf8(self.data.slice(self.start, self.end)).unwrap()
+ }
+
+ pub fn as_str(&self) -> ~str {
+ self.as_str_slice().to_owned()
+ }
+}
+
+pub struct TaggedDoc<'a> {
+ priv tag: uint,
+ doc: Doc<'a>,
+}
+
+pub enum EbmlEncoderTag {
+ EsUint, // 0
+ EsU64, // 1
+ EsU32, // 2
+ EsU16, // 3
+ EsU8, // 4
+ EsInt, // 5
+ EsI64, // 6
+ EsI32, // 7
+ EsI16, // 8
+ EsI8, // 9
+ EsBool, // 10
+ EsChar, // 11
+ EsStr, // 12
+ EsF64, // 13
+ EsF32, // 14
+ EsFloat, // 15
+ EsEnum, // 16
+ EsEnumVid, // 17
+ EsEnumBody, // 18
+ EsVec, // 19
+ EsVecLen, // 20
+ EsVecElt, // 21
+ EsMap, // 22
+ EsMapLen, // 23
+ EsMapKey, // 24
+ EsMapVal, // 25
+
+ EsOpaque,
+
+ EsLabel, // Used only when debugging
+}
+// --------------------------------------
+
+pub mod reader {
+ use std::char;
+
+ use std::cast::transmute;
+ use std::int;
+ use std::option::{None, Option, Some};
+ use std::io::extensions::u64_from_be_bytes;
+
+ use serialize;
+
+ use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey,
+ EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8,
+ EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint,
+ EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc };
+
+ // ebml reading
+
+ pub struct Res {
+ val: uint,
+ next: uint
+ }
+
+ #[inline(never)]
+ fn vuint_at_slow(data: &[u8], start: uint) -> Res {
+ let a = data[start];
+ if a & 0x80u8 != 0u8 {
+ return Res {val: (a & 0x7fu8) as uint, next: start + 1u};
+ }
+ if a & 0x40u8 != 0u8 {
+ return Res {val: ((a & 0x3fu8) as uint) << 8u |
+ (data[start + 1u] as uint),
+ next: start + 2u};
+ }
+ if a & 0x20u8 != 0u8 {
+ return Res {val: ((a & 0x1fu8) as uint) << 16u |
+ (data[start + 1u] as uint) << 8u |
+ (data[start + 2u] as uint),
+ next: start + 3u};
+ }
+ if a & 0x10u8 != 0u8 {
+ return Res {val: ((a & 0x0fu8) as uint) << 24u |
+ (data[start + 1u] as uint) << 16u |
+ (data[start + 2u] as uint) << 8u |
+ (data[start + 3u] as uint),
+ next: start + 4u};
+ }
+ fail!("vint too big");
+ }
+
+ pub fn vuint_at(data: &[u8], start: uint) -> Res {
+ use std::mem::from_be32;
+
+ if data.len() - start < 4 {
+ return vuint_at_slow(data, start);
+ }
+
+ // Lookup table for parsing EBML Element IDs as per http://ebml.sourceforge.net/specs/
+ // The Element IDs are parsed by reading a big endian u32 positioned at data[start].
+ // Using the four most significant bits of the u32 we lookup in the table below how the
+ // element ID should be derived from it.
+ //
+ // The table stores tuples (shift, mask) where shift is the number the u32 should be right
+ // shifted with and mask is the value the right shifted value should be masked with.
+ // If for example the most significant bit is set this means it's a class A ID and the u32
+ // should be right shifted with 24 and masked with 0x7f. Therefore we store (24, 0x7f) at
+ // index 0x8 - 0xF (four bit numbers where the most significant bit is set).
+ //
+ // By storing the number of shifts and masks in a table instead of checking in order if
+ // the most significant bit is set, the second most significant bit is set etc. we can
+ // replace up to three "and+branch" with a single table lookup which gives us a measured
+ // speedup of around 2x on x86_64.
+ static SHIFT_MASK_TABLE: [(u32, u32), ..16] = [
+ (0, 0x0), (0, 0x0fffffff),
+ (8, 0x1fffff), (8, 0x1fffff),
+ (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff),
+ (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f),
+ (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f)
+ ];
+
+ unsafe {
+ let ptr = data.as_ptr().offset(start as int) as *i32;
+ let val = from_be32(*ptr) as u32;
+
+ let i = (val >> 28u) as uint;
+ let (shift, mask) = SHIFT_MASK_TABLE[i];
+ Res {
+ val: ((val >> shift) & mask) as uint,
+ next: start + (((32 - shift) >> 3) as uint)
+ }
+ }
+ }
+
+ pub fn Doc<'a>(data: &'a [u8]) -> Doc<'a> {
+ Doc { data: data, start: 0u, end: data.len() }
+ }
+
+ pub fn doc_at<'a>(data: &'a [u8], start: uint) -> TaggedDoc<'a> {
+ let elt_tag = vuint_at(data, start);
+ let elt_size = vuint_at(data, elt_tag.next);
+ let end = elt_size.next + elt_size.val;
+ TaggedDoc {
+ tag: elt_tag.val,
+ doc: Doc { data: data, start: elt_size.next, end: end }
+ }
+ }
+
+ pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: uint) -> Option<Doc<'a>> {
+ let mut pos = d.start;
+ while pos < d.end {
+ let elt_tag = vuint_at(d.data, pos);
+ let elt_size = vuint_at(d.data, elt_tag.next);
+ pos = elt_size.next + elt_size.val;
+ if elt_tag.val == tg {
+ return Some(Doc { data: d.data, start: elt_size.next,
+ end: pos });
+ }
+ }
+ None
+ }
+
+ pub fn get_doc<'a>(d: Doc<'a>, tg: uint) -> Doc<'a> {
+ match maybe_get_doc(d, tg) {
+ Some(d) => d,
+ None => {
+ error!("failed to find block with tag {}", tg);
+ fail!();
+ }
+ }
+ }
+
+ pub fn docs<'a>(d: Doc<'a>, it: |uint, Doc<'a>| -> bool) -> bool {
+ let mut pos = d.start;
+ while pos < d.end {
+ let elt_tag = vuint_at(d.data, pos);
+ let elt_size = vuint_at(d.data, elt_tag.next);
+ pos = elt_size.next + elt_size.val;
+ let doc = Doc { data: d.data, start: elt_size.next, end: pos };
+ if !it(elt_tag.val, doc) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ pub fn tagged_docs<'a>(d: Doc<'a>, tg: uint, it: |Doc<'a>| -> bool) -> bool {
+ let mut pos = d.start;
+ while pos < d.end {
+ let elt_tag = vuint_at(d.data, pos);
+ let elt_size = vuint_at(d.data, elt_tag.next);
+ pos = elt_size.next + elt_size.val;
+ if elt_tag.val == tg {
+ let doc = Doc { data: d.data, start: elt_size.next,
+ end: pos };
+ if !it(doc) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ pub fn with_doc_data<'a, T>(d: Doc<'a>, f: |x: &'a [u8]| -> T) -> T {
+ f(d.data.slice(d.start, d.end))
+ }
+
+
+ pub fn doc_as_u8(d: Doc) -> u8 {
+ assert_eq!(d.end, d.start + 1u);
+ d.data[d.start]
+ }
+
+ pub fn doc_as_u16(d: Doc) -> u16 {
+ assert_eq!(d.end, d.start + 2u);
+ u64_from_be_bytes(d.data, d.start, 2u) as u16
+ }
+
+ pub fn doc_as_u32(d: Doc) -> u32 {
+ assert_eq!(d.end, d.start + 4u);
+ u64_from_be_bytes(d.data, d.start, 4u) as u32
+ }
+
+ pub fn doc_as_u64(d: Doc) -> u64 {
+ assert_eq!(d.end, d.start + 8u);
+ u64_from_be_bytes(d.data, d.start, 8u)
+ }
+
+ pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
+ pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 }
+ pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 }
+ pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 }
+
+ pub struct Decoder<'a> {
+ priv parent: Doc<'a>,
+ priv pos: uint,
+ }
+
+ pub fn Decoder<'a>(d: Doc<'a>) -> Decoder<'a> {
+ Decoder {
+ parent: d,
+ pos: d.start
+ }
+ }
+
+ impl<'doc> Decoder<'doc> {
+ fn _check_label(&mut self, lbl: &str) {
+ if self.pos < self.parent.end {
+ let TaggedDoc { tag: r_tag, doc: r_doc } =
+ doc_at(self.parent.data, self.pos);
+
+ if r_tag == (EsLabel as uint) {
+ self.pos = r_doc.end;
+ let str = r_doc.as_str_slice();
+ if lbl != str {
+ fail!("Expected label {} but found {}", lbl, str);
+ }
+ }
+ }
+ }
+
+ fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> Doc<'doc> {
+ debug!(". next_doc(exp_tag={:?})", exp_tag);
+ if self.pos >= self.parent.end {
+ fail!("no more documents in current node!");
+ }
+ let TaggedDoc { tag: r_tag, doc: r_doc } =
+ doc_at(self.parent.data, self.pos);
+ debug!("self.parent={}-{} self.pos={} r_tag={} r_doc={}-{}",
+ self.parent.start,
+ self.parent.end,
+ self.pos,
+ r_tag,
+ r_doc.start,
+ r_doc.end);
+ if r_tag != (exp_tag as uint) {
+ fail!("expected EBML doc with tag {:?} but found tag {:?}",
+ exp_tag, r_tag);
+ }
+ if r_doc.end > self.parent.end {
+ fail!("invalid EBML, child extends to {:#x}, parent to {:#x}",
+ r_doc.end, self.parent.end);
+ }
+ self.pos = r_doc.end;
+ r_doc
+ }
+
+ fn push_doc<T>(&mut self, exp_tag: EbmlEncoderTag,
+ f: |&mut Decoder<'doc>| -> T) -> T {
+ let d = self.next_doc(exp_tag);
+ let old_parent = self.parent;
+ let old_pos = self.pos;
+ self.parent = d;
+ self.pos = d.start;
+ let r = f(self);
+ self.parent = old_parent;
+ self.pos = old_pos;
+ r
+ }
+
+ fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> uint {
+ let r = doc_as_u32(self.next_doc(exp_tag));
+ debug!("_next_uint exp_tag={:?} result={}", exp_tag, r);
+ r as uint
+ }
+
+ pub fn read_opaque<R>(&mut self, op: |&mut Decoder<'doc>, Doc| -> R) -> R {
+ let doc = self.next_doc(EsOpaque);
+
+ let (old_parent, old_pos) = (self.parent, self.pos);
+ self.parent = doc;
+ self.pos = doc.start;
+
+ let result = op(self, doc);
+
+ self.parent = old_parent;
+ self.pos = old_pos;
+ result
+ }
+ }
+
+ impl<'doc> serialize::Decoder for Decoder<'doc> {
+ fn read_nil(&mut self) -> () { () }
+
+ fn read_u64(&mut self) -> u64 { doc_as_u64(self.next_doc(EsU64)) }
+ fn read_u32(&mut self) -> u32 { doc_as_u32(self.next_doc(EsU32)) }
+ fn read_u16(&mut self) -> u16 { doc_as_u16(self.next_doc(EsU16)) }
+ fn read_u8 (&mut self) -> u8 { doc_as_u8 (self.next_doc(EsU8 )) }
+ fn read_uint(&mut self) -> uint {
+ let v = doc_as_u64(self.next_doc(EsUint));
+ if v > (::std::uint::MAX as u64) {
+ fail!("uint {} too large for this architecture", v);
+ }
+ v as uint
+ }
+
+ fn read_i64(&mut self) -> i64 {
+ doc_as_u64(self.next_doc(EsI64)) as i64
+ }
+ fn read_i32(&mut self) -> i32 {
+ doc_as_u32(self.next_doc(EsI32)) as i32
+ }
+ fn read_i16(&mut self) -> i16 {
+ doc_as_u16(self.next_doc(EsI16)) as i16
+ }
+ fn read_i8 (&mut self) -> i8 {
+ doc_as_u8(self.next_doc(EsI8 )) as i8
+ }
+ fn read_int(&mut self) -> int {
+ let v = doc_as_u64(self.next_doc(EsInt)) as i64;
+ if v > (int::MAX as i64) || v < (int::MIN as i64) {
+ debug!("FIXME \\#6122: Removing this makes this function miscompile");
+ fail!("int {} out of range for this architecture", v);
+ }
+ v as int
+ }
+
+ fn read_bool(&mut self) -> bool {
+ doc_as_u8(self.next_doc(EsBool)) != 0
+ }
+
+ fn read_f64(&mut self) -> f64 {
+ let bits = doc_as_u64(self.next_doc(EsF64));
+ unsafe { transmute(bits) }
+ }
+ fn read_f32(&mut self) -> f32 {
+ let bits = doc_as_u32(self.next_doc(EsF32));
+ unsafe { transmute(bits) }
+ }
+ fn read_char(&mut self) -> char {
+ char::from_u32(doc_as_u32(self.next_doc(EsChar))).unwrap()
+ }
+ fn read_str(&mut self) -> ~str {
+ self.next_doc(EsStr).as_str()
+ }
+
+ // Compound types:
+ fn read_enum<T>(&mut self, name: &str, f: |&mut Decoder<'doc>| -> T) -> T {
+ debug!("read_enum({})", name);
+ self._check_label(name);
+
+ let doc = self.next_doc(EsEnum);
+
+ let (old_parent, old_pos) = (self.parent, self.pos);
+ self.parent = doc;
+ self.pos = self.parent.start;
+
+ let result = f(self);
+
+ self.parent = old_parent;
+ self.pos = old_pos;
+ result
+ }
+
+ fn read_enum_variant<T>(&mut self,
+ _: &[&str],
+ f: |&mut Decoder<'doc>, uint| -> T)
+ -> T {
+ debug!("read_enum_variant()");
+ let idx = self._next_uint(EsEnumVid);
+ debug!(" idx={}", idx);
+
+ let doc = self.next_doc(EsEnumBody);
+
+ let (old_parent, old_pos) = (self.parent, self.pos);
+ self.parent = doc;
+ self.pos = self.parent.start;
+
+ let result = f(self, idx);
+
+ self.parent = old_parent;
+ self.pos = old_pos;
+ result
+ }
+
+ fn read_enum_variant_arg<T>(&mut self,
+ idx: uint,
+ f: |&mut Decoder<'doc>| -> T) -> T {
+ debug!("read_enum_variant_arg(idx={})", idx);
+ f(self)
+ }
+
+ fn read_enum_struct_variant<T>(&mut self,
+ _: &[&str],
+ f: |&mut Decoder<'doc>, uint| -> T)
+ -> T {
+ debug!("read_enum_struct_variant()");
+ let idx = self._next_uint(EsEnumVid);
+ debug!(" idx={}", idx);
+
+ let doc = self.next_doc(EsEnumBody);
+
+ let (old_parent, old_pos) = (self.parent, self.pos);
+ self.parent = doc;
+ self.pos = self.parent.start;
+
+ let result = f(self, idx);
+
+ self.parent = old_parent;
+ self.pos = old_pos;
+ result
+ }
+
+ fn read_enum_struct_variant_field<T>(&mut self,
+ name: &str,
+ idx: uint,
+ f: |&mut Decoder<'doc>| -> T)
+ -> T {
+ debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
+ f(self)
+ }
+
+ fn read_struct<T>(&mut self,
+ name: &str,
+ _: uint,
+ f: |&mut Decoder<'doc>| -> T)
+ -> T {
+ debug!("read_struct(name={})", name);
+ f(self)
+ }
+
+ fn read_struct_field<T>(&mut self,
+ name: &str,
+ idx: uint,
+ f: |&mut Decoder<'doc>| -> T)
+ -> T {
+ debug!("read_struct_field(name={}, idx={})", name, idx);
+ self._check_label(name);
+ f(self)
+ }
+
+ fn read_tuple<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T {
+ debug!("read_tuple()");
+ self.read_seq(f)
+ }
+
+ fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
+ -> T {
+ debug!("read_tuple_arg(idx={})", idx);
+ self.read_seq_elt(idx, f)
+ }
+
+ fn read_tuple_struct<T>(&mut self,
+ name: &str,
+ f: |&mut Decoder<'doc>, uint| -> T)
+ -> T {
+ debug!("read_tuple_struct(name={})", name);
+ self.read_tuple(f)
+ }
+
+ fn read_tuple_struct_arg<T>(&mut self,
+ idx: uint,
+ f: |&mut Decoder<'doc>| -> T)
+ -> T {
+ debug!("read_tuple_struct_arg(idx={})", idx);
+ self.read_tuple_arg(idx, f)
+ }
+
+ fn read_option<T>(&mut self, f: |&mut Decoder<'doc>, bool| -> T) -> T {
+ debug!("read_option()");
+ self.read_enum("Option", |this| {
+ this.read_enum_variant(["None", "Some"], |this, idx| {
+ match idx {
+ 0 => f(this, false),
+ 1 => f(this, true),
+ _ => fail!(),
+ }
+ })
+ })
+ }
+
+ fn read_seq<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T {
+ debug!("read_seq()");
+ self.push_doc(EsVec, |d| {
+ let len = d._next_uint(EsVecLen);
+ debug!(" len={}", len);
+ f(d, len)
+ })
+ }
+
+ fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
+ -> T {
+ debug!("read_seq_elt(idx={})", idx);
+ self.push_doc(EsVecElt, f)
+ }
+
+ fn read_map<T>(&mut self, f: |&mut Decoder<'doc>, uint| -> T) -> T {
+ debug!("read_map()");
+ self.push_doc(EsMap, |d| {
+ let len = d._next_uint(EsMapLen);
+ debug!(" len={}", len);
+ f(d, len)
+ })
+ }
+
+ fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
+ -> T {
+ debug!("read_map_elt_key(idx={})", idx);
+ self.push_doc(EsMapKey, f)
+ }
+
+ fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> T)
+ -> T {
+ debug!("read_map_elt_val(idx={})", idx);
+ self.push_doc(EsMapVal, f)
+ }
+ }
+}
+
+pub mod writer {
+ use std::cast;
+ use std::clone::Clone;
+ use std::io;
+ use std::io::{Writer, Seek};
+ use std::io::MemWriter;
+ use std::io::extensions::u64_to_be_bytes;
+
+ use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey,
+ EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8,
+ EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint,
+ EsOpaque, EsLabel, EbmlEncoderTag };
+
+ use serialize;
+
+ // ebml writing
+ pub struct Encoder<'a> {
+ // FIXME(#5665): this should take a trait object. Note that if you
+ // delete this comment you should consider removing the
+ // unwrap()'s below of the results of the calls to
+ // write(). We're guaranteed that writing into a MemWriter
+ // won't fail, but this is not true for all I/O streams in
+ // general.
+ writer: &'a mut MemWriter,
+ priv size_positions: ~[uint],
+ last_error: io::IoResult<()>,
+ }
+
+ fn write_sized_vuint(w: &mut MemWriter, n: uint, size: uint) {
+ match size {
+ 1u => w.write(&[0x80u8 | (n as u8)]),
+ 2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]),
+ 3u => w.write(&[0x20u8 | ((n >> 16_u) as u8), (n >> 8_u) as u8,
+ n as u8]),
+ 4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8,
+ (n >> 8_u) as u8, n as u8]),
+ _ => fail!("vint to write too big: {}", n)
+ }.unwrap()
+ }
+
+ fn write_vuint(w: &mut MemWriter, n: uint) {
+ if n < 0x7f_u { write_sized_vuint(w, n, 1u); return; }
+ if n < 0x4000_u { write_sized_vuint(w, n, 2u); return; }
+ if n < 0x200000_u { write_sized_vuint(w, n, 3u); return; }
+ if n < 0x10000000_u { write_sized_vuint(w, n, 4u); return; }
+ fail!("vint to write too big: {}", n);
+ }
+
+ pub fn Encoder<'a>(w: &'a mut MemWriter) -> Encoder<'a> {
+ let size_positions: ~[uint] = ~[];
+ Encoder {
+ writer: w,
+ size_positions: size_positions,
+ last_error: Ok(()),
+ }
+ }
+
+ // FIXME (#2741): Provide a function to write the standard ebml header.
+ impl<'a> Encoder<'a> {
+ /// FIXME(pcwalton): Workaround for badness in trans. DO NOT USE ME.
+ pub unsafe fn unsafe_clone(&self) -> Encoder<'a> {
+ Encoder {
+ writer: cast::transmute_copy(&self.writer),
+ size_positions: self.size_positions.clone(),
+ last_error: Ok(()),
+ }
+ }
+
+ pub fn start_tag(&mut self, tag_id: uint) {
+ debug!("Start tag {}", tag_id);
+
+ // Write the enum ID:
+ write_vuint(self.writer, tag_id);
+
+ // Write a placeholder four-byte size.
+ self.size_positions.push(try!(self.writer.tell()) as uint);
+ let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8];
+ try!(self.writer.write(zeroes));
+ }
+
+ pub fn end_tag(&mut self) {
+ let last_size_pos = self.size_positions.pop().unwrap();
+ let cur_pos = try!(self.writer.tell());
+ try!(self.writer.seek(last_size_pos as i64, io::SeekSet));
+ let size = cur_pos as uint - last_size_pos - 4;
+ write_sized_vuint(self.writer, size, 4u);
+ try!(self.writer.seek(cur_pos as i64, io::SeekSet));
+
+ debug!("End tag (size = {})", size);
+ }
+
+ pub fn wr_tag(&mut self, tag_id: uint, blk: ||) {
+ self.start_tag(tag_id);
+ blk();
+ self.end_tag();
+ }
+
+ pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) {
+ write_vuint(self.writer, tag_id);
+ write_vuint(self.writer, b.len());
+ self.writer.write(b).unwrap();
+ }
+
+ pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) {
+ u64_to_be_bytes(v, 8u, |v| {
+ self.wr_tagged_bytes(tag_id, v);
+ })
+ }
+
+ pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) {
+ u64_to_be_bytes(v as u64, 4u, |v| {
+ self.wr_tagged_bytes(tag_id, v);
+ })
+ }
+
+ pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) {
+ u64_to_be_bytes(v as u64, 2u, |v| {
+ self.wr_tagged_bytes(tag_id, v);
+ })
+ }
+
+ pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) {
+ self.wr_tagged_bytes(tag_id, &[v]);
+ }
+
+ pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) {
+ u64_to_be_bytes(v as u64, 8u, |v| {
+ self.wr_tagged_bytes(tag_id, v);
+ })
+ }
+
+ pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) {
+ u64_to_be_bytes(v as u64, 4u, |v| {
+ self.wr_tagged_bytes(tag_id, v);
+ })
+ }
+
+ pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) {
+ u64_to_be_bytes(v as u64, 2u, |v| {
+ self.wr_tagged_bytes(tag_id, v);
+ })
+ }
+
+ pub fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) {
+ self.wr_tagged_bytes(tag_id, &[v as u8]);
+ }
+
+ pub fn wr_tagged_str(&mut self, tag_id: uint, v: &str) {
+ self.wr_tagged_bytes(tag_id, v.as_bytes());
+ }
+
+ pub fn wr_bytes(&mut self, b: &[u8]) {
+ debug!("Write {} bytes", b.len());
+ self.writer.write(b).unwrap();
+ }
+
+ pub fn wr_str(&mut self, s: &str) {
+ debug!("Write str: {}", s);
+ self.writer.write(s.as_bytes()).unwrap();
+ }
+ }
+
+ // FIXME (#2743): optionally perform "relaxations" on end_tag to more
+ // efficiently encode sizes; this is a fixed point iteration
+
+ // Set to true to generate more debugging in EBML code.
+ // Totally lame approach.
+ static DEBUG: bool = true;
+
+ impl<'a> Encoder<'a> {
+ // used internally to emit things like the vector length and so on
+ fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) {
+ assert!(v <= 0xFFFF_FFFF_u);
+ self.wr_tagged_u32(t as uint, v as u32);
+ }
+
+ fn _emit_label(&mut self, label: &str) {
+ // There are various strings that we have access to, such as
+ // the name of a record field, which do not actually appear in
+ // the encoded EBML (normally). This is just for
+ // efficiency. When debugging, though, we can emit such
+ // labels and then they will be checked by decoder to
+ // try and check failures more quickly.
+ if DEBUG { self.wr_tagged_str(EsLabel as uint, label) }
+ }
+
+ pub fn emit_opaque(&mut self, f: |&mut Encoder|) {
+ self.start_tag(EsOpaque as uint);
+ f(self);
+ self.end_tag();
+ }
+ }
+
+ impl<'a> serialize::Encoder for Encoder<'a> {
+ fn emit_nil(&mut self) {}
+
+ fn emit_uint(&mut self, v: uint) {
+ self.wr_tagged_u64(EsUint as uint, v as u64);
+ }
+ fn emit_u64(&mut self, v: u64) {
+ self.wr_tagged_u64(EsU64 as uint, v);
+ }
+ fn emit_u32(&mut self, v: u32) {
+ self.wr_tagged_u32(EsU32 as uint, v);
+ }
+ fn emit_u16(&mut self, v: u16) {
+ self.wr_tagged_u16(EsU16 as uint, v);
+ }
+ fn emit_u8(&mut self, v: u8) {
+ self.wr_tagged_u8(EsU8 as uint, v);
+ }
+
+ fn emit_int(&mut self, v: int) {
+ self.wr_tagged_i64(EsInt as uint, v as i64);
+ }
+ fn emit_i64(&mut self, v: i64) {
+ self.wr_tagged_i64(EsI64 as uint, v);
+ }
+ fn emit_i32(&mut self, v: i32) {
+ self.wr_tagged_i32(EsI32 as uint, v);
+ }
+ fn emit_i16(&mut self, v: i16) {
+ self.wr_tagged_i16(EsI16 as uint, v);
+ }
+ fn emit_i8(&mut self, v: i8) {
+ self.wr_tagged_i8(EsI8 as uint, v);
+ }
+
+ fn emit_bool(&mut self, v: bool) {
+ self.wr_tagged_u8(EsBool as uint, v as u8)
+ }
+
+ fn emit_f64(&mut self, v: f64) {
+ let bits = unsafe { cast::transmute(v) };
+ self.wr_tagged_u64(EsF64 as uint, bits);
+ }
+ fn emit_f32(&mut self, v: f32) {
+ let bits = unsafe { cast::transmute(v) };
+ self.wr_tagged_u32(EsF32 as uint, bits);
+ }
+ fn emit_char(&mut self, v: char) {
+ self.wr_tagged_u32(EsChar as uint, v as u32);
+ }
+
+ fn emit_str(&mut self, v: &str) {
+ self.wr_tagged_str(EsStr as uint, v)
+ }
+
+ fn emit_enum(&mut self, name: &str, f: |&mut Encoder<'a>|) {
+ self._emit_label(name);
+ self.start_tag(EsEnum as uint);
+ f(self);
+ self.end_tag();
+ }
+
+ fn emit_enum_variant(&mut self,
+ _: &str,
+ v_id: uint,
+ _: uint,
+ f: |&mut Encoder<'a>|) {
+ self._emit_tagged_uint(EsEnumVid, v_id);
+ self.start_tag(EsEnumBody as uint);
+ f(self);
+ self.end_tag();
+ }
+
+ fn emit_enum_variant_arg(&mut self, _: uint, f: |&mut Encoder<'a>|) {
+ f(self)
+ }
+
+ fn emit_enum_struct_variant(&mut self,
+ v_name: &str,
+ v_id: uint,
+ cnt: uint,
+ f: |&mut Encoder<'a>|) {
+ self.emit_enum_variant(v_name, v_id, cnt, f)
+ }
+
+ fn emit_enum_struct_variant_field(&mut self,
+ _: &str,
+ idx: uint,
+ f: |&mut Encoder<'a>|) {
+ self.emit_enum_variant_arg(idx, f)
+ }
+
+ fn emit_struct(&mut self,
+ _: &str,
+ _len: uint,
+ f: |&mut Encoder<'a>|) {
+ f(self)
+ }
+
+ fn emit_struct_field(&mut self,
+ name: &str,
+ _: uint,
+ f: |&mut Encoder<'a>|) {
+ self._emit_label(name);
+ f(self)
+ }
+
+ fn emit_tuple(&mut self, len: uint, f: |&mut Encoder<'a>|) {
+ self.emit_seq(len, f)
+ }
+ fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+ self.emit_seq_elt(idx, f)
+ }
+
+ fn emit_tuple_struct(&mut self,
+ _: &str,
+ len: uint,
+ f: |&mut Encoder<'a>|) {
+ self.emit_seq(len, f)
+ }
+ fn emit_tuple_struct_arg(&mut self,
+ idx: uint,
+ f: |&mut Encoder<'a>|) {
+ self.emit_seq_elt(idx, f)
+ }
+
+ fn emit_option(&mut self, f: |&mut Encoder<'a>|) {
+ self.emit_enum("Option", f);
+ }
+ fn emit_option_none(&mut self) {
+ self.emit_enum_variant("None", 0, 0, |_| ())
+ }
+ fn emit_option_some(&mut self, f: |&mut Encoder<'a>|) {
+ self.emit_enum_variant("Some", 1, 1, f)
+ }
+
+ fn emit_seq(&mut self, len: uint, f: |&mut Encoder<'a>|) {
+ self.start_tag(EsVec as uint);
+ self._emit_tagged_uint(EsVecLen, len);
+ f(self);
+ self.end_tag();
+ }
+
+ fn emit_seq_elt(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
+ self.start_tag(EsVecElt as uint);
+ f(self);
+ self.end_tag();
+ }
+
+ fn emit_map(&mut self, len: uint, f: |&mut Encoder<'a>|) {
+ self.start_tag(EsMap as uint);
+ self._emit_tagged_uint(EsMapLen, len);
+ f(self);
+ self.end_tag();
+ }
+
+ fn emit_map_elt_key(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
+ self.start_tag(EsMapKey as uint);
+ f(self);
+ self.end_tag();
+ }
+
+ fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
+ self.start_tag(EsMapVal as uint);
+ f(self);
+ self.end_tag();
+ }
+ }
+}
+
+// ___________________________________________________________________________
+// Testing
+
+#[cfg(test)]
+mod tests {
+ use ebml::reader;
+ use ebml::writer;
+ use {Encodable, Decodable};
+
+ use std::io::MemWriter;
+ use std::option::{None, Option, Some};
+
+ #[test]
+ fn test_vuint_at() {
+ let data = [
+ 0x80,
+ 0xff,
+ 0x40, 0x00,
+ 0x7f, 0xff,
+ 0x20, 0x00, 0x00,
+ 0x3f, 0xff, 0xff,
+ 0x10, 0x00, 0x00, 0x00,
+ 0x1f, 0xff, 0xff, 0xff
+ ];
+
+ let mut res: reader::Res;
+
+ // Class A
+ res = reader::vuint_at(data, 0);
+ assert_eq!(res.val, 0);
+ assert_eq!(res.next, 1);
+ res = reader::vuint_at(data, res.next);
+ assert_eq!(res.val, (1 << 7) - 1);
+ assert_eq!(res.next, 2);
+
+ // Class B
+ res = reader::vuint_at(data, res.next);
+ assert_eq!(res.val, 0);
+ assert_eq!(res.next, 4);
+ res = reader::vuint_at(data, res.next);
+ assert_eq!(res.val, (1 << 14) - 1);
+ assert_eq!(res.next, 6);
+
+ // Class C
+ res = reader::vuint_at(data, res.next);
+ assert_eq!(res.val, 0);
+ assert_eq!(res.next, 9);
+ res = reader::vuint_at(data, res.next);
+ assert_eq!(res.val, (1 << 21) - 1);
+ assert_eq!(res.next, 12);
+
+ // Class D
+ res = reader::vuint_at(data, res.next);
+ assert_eq!(res.val, 0);
+ assert_eq!(res.next, 16);
+ res = reader::vuint_at(data, res.next);
+ assert_eq!(res.val, (1 << 28) - 1);
+ assert_eq!(res.next, 20);
+ }
+
+ #[test]
+ fn test_option_int() {
+ fn test_v(v: Option<int>) {
+ debug!("v == {:?}", v);
+ let mut wr = MemWriter::new();
+ {
+ let mut ebml_w = writer::Encoder(&mut wr);
+ v.encode(&mut ebml_w);
+ }
+ let ebml_doc = reader::Doc(wr.get_ref());
+ let mut deser = reader::Decoder(ebml_doc);
+ let v1 = Decodable::decode(&mut deser);
+ debug!("v1 == {:?}", v1);
+ assert_eq!(v, v1);
+ }
+
+ test_v(Some(22));
+ test_v(None);
+ test_v(Some(3));
+ }
+}
+
+#[cfg(test)]
+mod bench {
+ extern crate test;
+ use self::test::BenchHarness;
+ use ebml::reader;
+
+ #[bench]
+ pub fn vuint_at_A_aligned(bh: &mut BenchHarness) {
+ use std::slice;
+ let data = slice::from_fn(4*100, |i| {
+ match i % 2 {
+ 0 => 0x80u8,
+ _ => i as u8,
+ }
+ });
+ let mut sum = 0u;
+ bh.iter(|| {
+ let mut i = 0;
+ while i < data.len() {
+ sum += reader::vuint_at(data, i).val;
+ i += 4;
+ }
+ });
+ }
+
+ #[bench]
+ pub fn vuint_at_A_unaligned(bh: &mut BenchHarness) {
+ use std::slice;
+ let data = slice::from_fn(4*100+1, |i| {
+ match i % 2 {
+ 1 => 0x80u8,
+ _ => i as u8
+ }
+ });
+ let mut sum = 0u;
+ bh.iter(|| {
+ let mut i = 1;
+ while i < data.len() {
+ sum += reader::vuint_at(data, i).val;
+ i += 4;
+ }
+ });
+ }
+
+ #[bench]
+ pub fn vuint_at_D_aligned(bh: &mut BenchHarness) {
+ use std::slice;
+ let data = slice::from_fn(4*100, |i| {
+ match i % 4 {
+ 0 => 0x10u8,
+ 3 => i as u8,
+ _ => 0u8
+ }
+ });
+ let mut sum = 0u;
+ bh.iter(|| {
+ let mut i = 0;
+ while i < data.len() {
+ sum += reader::vuint_at(data, i).val;
+ i += 4;
+ }
+ });
+ }
+
+ #[bench]
+ pub fn vuint_at_D_unaligned(bh: &mut BenchHarness) {
+ use std::slice;
+ let data = slice::from_fn(4*100+1, |i| {
+ match i % 4 {
+ 1 => 0x10u8,
+ 0 => i as u8,
+ _ => 0u8
+ }
+ });
+ let mut sum = 0u;
+ bh.iter(|| {
+ let mut i = 1;
+ while i < data.len() {
+ sum += reader::vuint_at(data, i).val;
+ i += 4;
+ }
+ });
+ }
+}
+
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)
+ };
}
}
```
~"{\"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
}
```
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
}
```
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();
}
```
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 {
pub type List = ~[Json];
pub type Object = TreeMap<~str, Json>;
-#[deriving(Eq)]
-/// If an error occurs while parsing some JSON, this is the structure which is
-/// returned
-pub struct Error {
- /// The line number at which the error occurred
- priv line: uint,
- /// The column number at which the error occurred
- priv col: uint,
- /// A message describing the type of the error
- priv msg: ~str,
+#[deriving(Eq, Show)]
+pub enum Error {
+ /// msg, line, col
+ ParseError(~str, uint, uint),
+ ExpectedError(~str, ~str),
+ MissingFieldError(~str),
+ UnknownVariantError(~str),
+ IoError(io::IoError)
}
-fn io_error_to_error(io: io::IoError) -> Error {
- Error {
- line: 0,
- col: 0,
- msg: format!("io error: {}", io)
- }
-}
+pub type EncodeResult = io::IoResult<()>;
+pub type DecodeResult<T> = Result<T, Error>;
fn escape_str(s: &str) -> ~str {
let mut escaped = ~"\"";
/// A structure for implementing serialization to JSON.
pub struct Encoder<'a> {
priv wr: &'a mut io::Writer,
- priv error: io::IoResult<()>,
}
impl<'a> Encoder<'a> {
/// Creates a new JSON encoder whose output will be written to the writer
/// specified.
pub fn new<'a>(wr: &'a mut io::Writer) -> Encoder<'a> {
- Encoder { wr: wr, error: Ok(()) }
+ Encoder { wr: wr }
}
/// Encode the specified struct into a json [u8]
- pub fn buffer_encode<T:Encodable<Encoder<'a>>>(to_encode_object: &T) -> ~[u8] {
+ pub fn buffer_encode<T:Encodable<Encoder<'a>, io::IoError>>(to_encode_object: &T) -> ~[u8] {
//Serialize the object in a string using a writer
let mut m = MemWriter::new();
{
let mut encoder = Encoder::new(&mut m as &mut io::Writer);
- to_encode_object.encode(&mut encoder);
+ // MemWriter never Errs
+ let _ = to_encode_object.encode(&mut encoder);
}
m.unwrap()
}
/// Encode the specified struct into a json str
- pub fn str_encode<T:Encodable<Encoder<'a>>>(to_encode_object: &T) -> ~str {
+ pub fn str_encode<T:Encodable<Encoder<'a>, io::IoError>>(to_encode_object: &T) -> ~str {
let buff:~[u8] = Encoder::buffer_encode(to_encode_object);
str::from_utf8_owned(buff).unwrap()
}
}
-impl<'a> ::Encoder for Encoder<'a> {
- fn emit_nil(&mut self) { try!(write!(self.wr, "null")) }
+impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
+ fn emit_nil(&mut self) -> EncodeResult { write!(self.wr, "null") }
- fn emit_uint(&mut self, v: uint) { self.emit_f64(v as f64); }
- fn emit_u64(&mut self, v: u64) { self.emit_f64(v as f64); }
- fn emit_u32(&mut self, v: u32) { self.emit_f64(v as f64); }
- fn emit_u16(&mut self, v: u16) { self.emit_f64(v as f64); }
- fn emit_u8(&mut self, v: u8) { self.emit_f64(v as f64); }
+ fn emit_uint(&mut self, v: uint) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_u64(&mut self, v: u64) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_u32(&mut self, v: u32) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_u16(&mut self, v: u16) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_u8(&mut self, v: u8) -> EncodeResult { self.emit_f64(v as f64) }
- fn emit_int(&mut self, v: int) { self.emit_f64(v as f64); }
- fn emit_i64(&mut self, v: i64) { self.emit_f64(v as f64); }
- fn emit_i32(&mut self, v: i32) { self.emit_f64(v as f64); }
- fn emit_i16(&mut self, v: i16) { self.emit_f64(v as f64); }
- fn emit_i8(&mut self, v: i8) { self.emit_f64(v as f64); }
+ fn emit_int(&mut self, v: int) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_i64(&mut self, v: i64) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_i32(&mut self, v: i32) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_i16(&mut self, v: i16) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_i8(&mut self, v: i8) -> EncodeResult { self.emit_f64(v as f64) }
- fn emit_bool(&mut self, v: bool) {
+ fn emit_bool(&mut self, v: bool) -> EncodeResult {
if v {
- try!(write!(self.wr, "true"));
+ write!(self.wr, "true")
} else {
- try!(write!(self.wr, "false"));
+ write!(self.wr, "false")
}
}
- fn emit_f64(&mut self, v: f64) {
- try!(write!(self.wr, "{}", f64::to_str_digits(v, 6u)))
+ fn emit_f64(&mut self, v: f64) -> EncodeResult {
+ write!(self.wr, "{}", f64::to_str_digits(v, 6u))
}
- fn emit_f32(&mut self, v: f32) { self.emit_f64(v as f64); }
+ fn emit_f32(&mut self, v: f32) -> EncodeResult { self.emit_f64(v as f64) }
- fn emit_char(&mut self, v: char) { self.emit_str(str::from_char(v)) }
- fn emit_str(&mut self, v: &str) {
- try!(write!(self.wr, "{}", escape_str(v)))
+ fn emit_char(&mut self, v: char) -> EncodeResult { self.emit_str(str::from_char(v)) }
+ fn emit_str(&mut self, v: &str) -> EncodeResult {
+ write!(self.wr, "{}", escape_str(v))
}
- fn emit_enum(&mut self, _name: &str, f: |&mut Encoder<'a>|) { f(self) }
+ fn emit_enum(&mut self,
+ _name: &str,
+ f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult { f(self) }
fn emit_enum_variant(&mut self,
name: &str,
_id: uint,
cnt: uint,
- f: |&mut Encoder<'a>|) {
+ f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
// enums are encoded as strings or objects
// Bunny => "Bunny"
// Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]}
if cnt == 0 {
- try!(write!(self.wr, "{}", escape_str(name)));
+ write!(self.wr, "{}", escape_str(name))
} else {
try!(write!(self.wr, "\\{\"variant\":"));
try!(write!(self.wr, "{}", escape_str(name)));
try!(write!(self.wr, ",\"fields\":["));
- f(self);
- try!(write!(self.wr, "]\\}"));
+ try!(f(self));
+ write!(self.wr, "]\\}")
}
}
- fn emit_enum_variant_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+ fn emit_enum_variant_arg(&mut self,
+ idx: uint,
+ f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
if idx != 0 {
try!(write!(self.wr, ","));
}
- f(self);
+ f(self)
}
fn emit_enum_struct_variant(&mut self,
name: &str,
id: uint,
cnt: uint,
- f: |&mut Encoder<'a>|) {
+ f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
self.emit_enum_variant(name, id, cnt, f)
}
fn emit_enum_struct_variant_field(&mut self,
_: &str,
idx: uint,
- f: |&mut Encoder<'a>|) {
+ f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
self.emit_enum_variant_arg(idx, f)
}
- fn emit_struct(&mut self, _: &str, _: uint, f: |&mut Encoder<'a>|) {
+ fn emit_struct(&mut self,
+ _: &str,
+ _: uint,
+ f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
try!(write!(self.wr, r"\{"));
- f(self);
- try!(write!(self.wr, r"\}"));
+ try!(f(self));
+ write!(self.wr, r"\}")
}
fn emit_struct_field(&mut self,
name: &str,
idx: uint,
- f: |&mut Encoder<'a>|) {
- if idx != 0 { try!(write!(self.wr, ",")) }
+ f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
+ if idx != 0 { try!(write!(self.wr, ",")); }
try!(write!(self.wr, "{}:", escape_str(name)));
- f(self);
+ f(self)
}
- fn emit_tuple(&mut self, len: uint, f: |&mut Encoder<'a>|) {
+ fn emit_tuple(&mut self, len: uint, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
self.emit_seq(len, f)
}
- fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+ fn emit_tuple_arg(&mut self,
+ idx: uint,
+ f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
self.emit_seq_elt(idx, f)
}
fn emit_tuple_struct(&mut self,
_name: &str,
len: uint,
- f: |&mut Encoder<'a>|) {
+ f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
self.emit_seq(len, f)
}
- fn emit_tuple_struct_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+ fn emit_tuple_struct_arg(&mut self,
+ idx: uint,
+ f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
self.emit_seq_elt(idx, f)
}
- fn emit_option(&mut self, f: |&mut Encoder<'a>|) { f(self); }
- fn emit_option_none(&mut self) { self.emit_nil(); }
- fn emit_option_some(&mut self, f: |&mut Encoder<'a>|) { f(self); }
+ fn emit_option(&mut self, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
+ f(self)
+ }
+ fn emit_option_none(&mut self) -> EncodeResult { self.emit_nil() }
+ fn emit_option_some(&mut self, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
+ f(self)
+ }
- fn emit_seq(&mut self, _len: uint, f: |&mut Encoder<'a>|) {
+ fn emit_seq(&mut self, _len: uint, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
try!(write!(self.wr, "["));
- f(self);
- try!(write!(self.wr, "]"));
+ try!(f(self));
+ write!(self.wr, "]")
}
- fn emit_seq_elt(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+ fn emit_seq_elt(&mut self, idx: uint, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
if idx != 0 {
try!(write!(self.wr, ","));
}
f(self)
}
- fn emit_map(&mut self, _len: uint, f: |&mut Encoder<'a>|) {
+ fn emit_map(&mut self, _len: uint, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
try!(write!(self.wr, r"\{"));
- f(self);
- try!(write!(self.wr, r"\}"));
+ try!(f(self));
+ write!(self.wr, r"\}")
}
- fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+ fn emit_map_elt_key(&mut self,
+ idx: uint,
+ f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
use std::str::from_utf8;
if idx != 0 { try!(write!(self.wr, ",")) }
// ref #12967, make sure to wrap a key in double quotes,
// in the event that its of a type that omits them (eg numbers)
let mut buf = MemWriter::new();
let mut check_encoder = Encoder::new(&mut buf);
- f(&mut check_encoder);
+ try!(f(&mut check_encoder));
let buf = buf.unwrap();
let out = from_utf8(buf).unwrap();
let needs_wrapping = out.char_at(0) != '"' &&
out.char_at_reverse(out.len()) != '"';
if needs_wrapping { try!(write!(self.wr, "\"")); }
- f(self);
+ try!(f(self));
if needs_wrapping { try!(write!(self.wr, "\"")); }
+ Ok(())
}
- fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
+ fn emit_map_elt_val(&mut self,
+ _idx: uint,
+ f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
try!(write!(self.wr, ":"));
f(self)
}
pub struct PrettyEncoder<'a> {
priv wr: &'a mut io::Writer,
priv indent: uint,
- priv error: io::IoResult<()>,
}
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<io::IoError> for PrettyEncoder<'a> {
+ fn emit_nil(&mut self) -> EncodeResult { write!(self.wr, "null") }
- fn emit_uint(&mut self, v: uint) { self.emit_f64(v as f64); }
- fn emit_u64(&mut self, v: u64) { self.emit_f64(v as f64); }
- fn emit_u32(&mut self, v: u32) { self.emit_f64(v as f64); }
- fn emit_u16(&mut self, v: u16) { self.emit_f64(v as f64); }
- fn emit_u8(&mut self, v: u8) { self.emit_f64(v as f64); }
+ fn emit_uint(&mut self, v: uint) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_u64(&mut self, v: u64) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_u32(&mut self, v: u32) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_u16(&mut self, v: u16) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_u8(&mut self, v: u8) -> EncodeResult { self.emit_f64(v as f64) }
- fn emit_int(&mut self, v: int) { self.emit_f64(v as f64); }
- fn emit_i64(&mut self, v: i64) { self.emit_f64(v as f64); }
- fn emit_i32(&mut self, v: i32) { self.emit_f64(v as f64); }
- fn emit_i16(&mut self, v: i16) { self.emit_f64(v as f64); }
- fn emit_i8(&mut self, v: i8) { self.emit_f64(v as f64); }
+ fn emit_int(&mut self, v: int) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_i64(&mut self, v: i64) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_i32(&mut self, v: i32) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_i16(&mut self, v: i16) -> EncodeResult { self.emit_f64(v as f64) }
+ fn emit_i8(&mut self, v: i8) -> EncodeResult { self.emit_f64(v as f64) }
- fn emit_bool(&mut self, v: bool) {
+ fn emit_bool(&mut self, v: bool) -> EncodeResult {
if v {
- try!(write!(self.wr, "true"));
+ write!(self.wr, "true")
} else {
- try!(write!(self.wr, "false"));
+ write!(self.wr, "false")
}
}
- fn emit_f64(&mut self, v: f64) {
- try!(write!(self.wr, "{}", f64::to_str_digits(v, 6u)));
+ fn emit_f64(&mut self, v: f64) -> EncodeResult {
+ write!(self.wr, "{}", f64::to_str_digits(v, 6u))
}
- fn emit_f32(&mut self, v: f32) { self.emit_f64(v as f64); }
+ fn emit_f32(&mut self, v: f32) -> EncodeResult { self.emit_f64(v as f64) }
- fn emit_char(&mut self, v: char) { self.emit_str(str::from_char(v)) }
- fn emit_str(&mut self, v: &str) {
- try!(write!(self.wr, "{}", escape_str(v)));
+ fn emit_char(&mut self, v: char) -> EncodeResult { self.emit_str(str::from_char(v)) }
+ fn emit_str(&mut self, v: &str) -> EncodeResult {
+ write!(self.wr, "{}", escape_str(v))
}
- fn emit_enum(&mut self, _name: &str, f: |&mut PrettyEncoder<'a>|) {
+ fn emit_enum(&mut self,
+ _name: &str,
+ f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
f(self)
}
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"));
}
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)
}
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 {
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"));
// in the event that its of a type that omits them (eg numbers)
let mut buf = MemWriter::new();
let mut check_encoder = PrettyEncoder::new(&mut buf);
- f(&mut check_encoder);
+ try!(f(&mut check_encoder));
let buf = buf.unwrap();
let out = from_utf8(buf).unwrap();
let needs_wrapping = out.char_at(0) != '"' &&
out.char_at_reverse(out.len()) != '"';
if needs_wrapping { try!(write!(self.wr, "\"")); }
- f(self);
+ try!(f(self));
if needs_wrapping { try!(write!(self.wr, "\"")); }
+ Ok(())
}
- fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut PrettyEncoder<'a>|) {
+ fn emit_map_elt_val(&mut self,
+ _idx: uint,
+ f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
try!(write!(self.wr, ": "));
- f(self);
+ f(self)
}
}
-impl<E: ::Encoder> Encodable<E> for Json {
- fn encode(&self, e: &mut E) {
+impl<E: ::Encoder<io::IoError>> Encodable<E, io::IoError> for Json {
+ fn encode(&self, e: &mut E) -> EncodeResult {
match *self {
Number(v) => v.encode(e),
String(ref v) => v.encode(e),
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
}
impl<T: Iterator<char>> Parser<T> {
- pub fn parse(&mut self) -> Result<Json, Error> {
+ pub fn parse(&mut self) -> DecodeResult<Json> {
match self.parse_value() {
Ok(value) => {
// Skip trailing whitespaces.
self.ch == Some(c)
}
- fn error<T>(&self, msg: ~str) -> Result<T, Error> {
- Err(Error { line: self.line, col: self.col, msg: msg })
+ fn error<T>(&self, msg: ~str) -> DecodeResult<T> {
+ Err(ParseError(msg, self.line, self.col))
}
- fn parse_value(&mut self) -> Result<Json, Error> {
+ fn parse_value(&mut self) -> DecodeResult<Json> {
self.parse_whitespace();
if self.eof() { return self.error(~"EOF while parsing value"); }
self.ch_is('\r') { self.bump(); }
}
- fn parse_ident(&mut self, ident: &str, value: Json) -> Result<Json, Error> {
+ fn parse_ident(&mut self, ident: &str, value: Json) -> DecodeResult<Json> {
if ident.chars().all(|c| Some(c) == self.next_char()) {
self.bump();
Ok(value)
}
}
- fn parse_number(&mut self) -> Result<Json, Error> {
+ fn parse_number(&mut self) -> DecodeResult<Json> {
let mut neg = 1.0;
if self.ch_is('-') {
Ok(Number(neg * res))
}
- fn parse_integer(&mut self) -> Result<f64, Error> {
+ fn parse_integer(&mut self) -> DecodeResult<f64> {
let mut res = 0.0;
match self.ch_or_null() {
Ok(res)
}
- fn parse_decimal(&mut self, res: f64) -> Result<f64, Error> {
+ fn parse_decimal(&mut self, res: f64) -> DecodeResult<f64> {
self.bump();
// Make sure a digit follows the decimal place.
Ok(res)
}
- fn parse_exponent(&mut self, mut res: f64) -> Result<f64, Error> {
+ fn parse_exponent(&mut self, mut res: f64) -> DecodeResult<f64> {
self.bump();
let mut exp = 0u;
Ok(res)
}
- fn parse_str(&mut self) -> Result<~str, Error> {
+ fn parse_str(&mut self) -> DecodeResult<~str> {
let mut escape = false;
let mut res = ~"";
}
}
- fn parse_list(&mut self) -> Result<Json, Error> {
+ fn parse_list(&mut self) -> DecodeResult<Json> {
self.bump();
self.parse_whitespace();
};
}
- fn parse_object(&mut self) -> Result<Json, Error> {
+ fn parse_object(&mut self) -> DecodeResult<Json> {
self.bump();
self.parse_whitespace();
}
/// Decodes a json value from an `&mut io::Reader`
-pub fn from_reader(rdr: &mut io::Reader) -> Result<Json, Error> {
+pub fn from_reader(rdr: &mut io::Reader) -> DecodeResult<Json> {
let contents = match rdr.read_to_end() {
Ok(c) => c,
- Err(e) => return Err(io_error_to_error(e))
+ Err(e) => return Err(IoError(e))
};
let s = match str::from_utf8_owned(contents) {
Some(s) => s,
- None => return Err(Error { line: 0, col: 0, msg: ~"contents not utf-8" })
+ None => return Err(ParseError(~"contents not utf-8", 0, 0))
};
let mut parser = Parser::new(s.chars());
parser.parse()
}
/// Decodes a json value from a string
-pub fn from_str(s: &str) -> Result<Json, Error> {
+pub fn from_str(s: &str) -> DecodeResult<Json> {
let mut parser = Parser::new(s.chars());
parser.parse()
}
}
impl Decoder {
- fn err(&self, msg: &str) -> ! {
- fail!("JSON decode error: {}", msg);
- }
- fn missing_field(&self, field: &str, object: ~Object) -> ! {
- self.err(format!("missing required '{}' field in object: {}",
- field, Object(object).to_str()))
- }
- fn expected(&self, expected: &str, found: &Json) -> ! {
- let found_s = match *found {
- Null => "null",
- List(..) => "list",
- Object(..) => "object",
- Number(..) => "number",
- String(..) => "string",
- Boolean(..) => "boolean"
- };
- self.err(format!("expected {expct} but found {fnd}: {val}",
- expct=expected, fnd=found_s, val=found.to_str()))
+ fn pop(&mut self) -> Json {
+ self.stack.pop().unwrap()
}
}
-impl ::Decoder for Decoder {
- fn read_nil(&mut self) -> () {
- debug!("read_nil");
- match self.stack.pop().unwrap() {
- Null => (),
- value => self.expected("null", &value)
+macro_rules! expect(
+ ($e:expr, Null) => ({
+ match $e {
+ Null => Ok(()),
+ other => Err(ExpectedError(~"Null", format!("{}", other)))
+ }
+ });
+ ($e:expr, $t:ident) => ({
+ match $e {
+ $t(v) => Ok(v),
+ other => Err(ExpectedError(stringify!($t).to_owned(), format!("{}", other)))
}
+ })
+)
+
+impl ::Decoder<Error> for Decoder {
+ fn read_nil(&mut self) -> DecodeResult<()> {
+ debug!("read_nil");
+ try!(expect!(self.pop(), Null));
+ Ok(())
}
- fn read_u64(&mut self) -> u64 { self.read_f64() as u64 }
- fn read_u32(&mut self) -> u32 { self.read_f64() as u32 }
- fn read_u16(&mut self) -> u16 { self.read_f64() as u16 }
- fn read_u8 (&mut self) -> u8 { self.read_f64() as u8 }
- fn read_uint(&mut self) -> uint { self.read_f64() as uint }
+ fn read_u64(&mut self) -> DecodeResult<u64 > { Ok(try!(self.read_f64()) as u64) }
+ fn read_u32(&mut self) -> DecodeResult<u32 > { Ok(try!(self.read_f64()) as u32) }
+ fn read_u16(&mut self) -> DecodeResult<u16 > { Ok(try!(self.read_f64()) as u16) }
+ fn read_u8 (&mut self) -> DecodeResult<u8 > { Ok(try!(self.read_f64()) as u8) }
+ fn read_uint(&mut self) -> DecodeResult<uint> { Ok(try!(self.read_f64()) as uint) }
- fn read_i64(&mut self) -> i64 { self.read_f64() as i64 }
- fn read_i32(&mut self) -> i32 { self.read_f64() as i32 }
- fn read_i16(&mut self) -> i16 { self.read_f64() as i16 }
- fn read_i8 (&mut self) -> i8 { self.read_f64() as i8 }
- fn read_int(&mut self) -> int { self.read_f64() as int }
+ fn read_i64(&mut self) -> DecodeResult<i64> { Ok(try!(self.read_f64()) as i64) }
+ fn read_i32(&mut self) -> DecodeResult<i32> { Ok(try!(self.read_f64()) as i32) }
+ fn read_i16(&mut self) -> DecodeResult<i16> { Ok(try!(self.read_f64()) as i16) }
+ fn read_i8 (&mut self) -> DecodeResult<i8 > { Ok(try!(self.read_f64()) as i8) }
+ fn read_int(&mut self) -> DecodeResult<int> { Ok(try!(self.read_f64()) as int) }
- fn read_bool(&mut self) -> bool {
+ fn read_bool(&mut self) -> DecodeResult<bool> {
debug!("read_bool");
- match self.stack.pop().unwrap() {
- Boolean(b) => b,
- value => self.expected("boolean", &value)
- }
+ Ok(try!(expect!(self.pop(), Boolean)))
}
- fn read_f64(&mut self) -> f64 {
+ fn read_f64(&mut self) -> DecodeResult<f64> {
use std::from_str::FromStr;
debug!("read_f64");
- match self.stack.pop().unwrap() {
- Number(f) => f,
+ match self.pop() {
+ Number(f) => Ok(f),
String(s) => {
// re: #12967.. a type w/ numeric keys (ie HashMap<uint, V> etc)
// is going to have a string here, as per JSON spec..
- FromStr::from_str(s).unwrap()
+ Ok(FromStr::from_str(s).unwrap())
},
- value => self.expected("number", &value)
+ value => Err(ExpectedError(~"Number", format!("{}", value)))
}
}
- fn read_f32(&mut self) -> f32 { self.read_f64() as f32 }
+ fn read_f32(&mut self) -> DecodeResult<f32> { Ok(try!(self.read_f64()) as f32) }
- fn read_char(&mut self) -> char {
- let s = self.read_str();
+ fn read_char(&mut self) -> DecodeResult<char> {
+ let s = try!(self.read_str());
{
let mut it = s.chars();
match (it.next(), it.next()) {
// exactly one character
- (Some(c), None) => return c,
+ (Some(c), None) => return Ok(c),
_ => ()
}
}
- self.expected("single character string", &String(s))
+ Err(ExpectedError(~"single character string", format!("{}", s)))
}
- fn read_str(&mut self) -> ~str {
+ fn read_str(&mut self) -> DecodeResult<~str> {
debug!("read_str");
- match self.stack.pop().unwrap() {
- String(s) => s,
- value => self.expected("string", &value)
- }
+ Ok(try!(expect!(self.pop(), String)))
}
- fn read_enum<T>(&mut self, name: &str, f: |&mut Decoder| -> T) -> T {
+ fn read_enum<T>(&mut self,
+ name: &str,
+ f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
debug!("read_enum({})", name);
f(self)
}
fn read_enum_variant<T>(&mut self,
names: &[&str],
- f: |&mut Decoder, uint| -> T)
- -> T {
+ f: |&mut Decoder, uint| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_enum_variant(names={:?})", names);
- let name = match self.stack.pop().unwrap() {
+ let name = match self.pop() {
String(s) => s,
Object(mut o) => {
let n = match o.pop(&~"variant") {
Some(String(s)) => s,
- Some(val) => self.expected("string", &val),
- None => self.missing_field("variant", o)
+ Some(val) => return Err(ExpectedError(~"String", format!("{}", val))),
+ None => return Err(MissingFieldError(~"variant"))
};
match o.pop(&~"fields") {
Some(List(l)) => {
self.stack.push(field.clone());
}
},
- Some(val) => self.expected("list", &val),
- None => {
- // re-insert the variant field so we're
- // printing the "whole" struct in the error
- // message... ick.
- o.insert(~"variant", String(n));
- self.missing_field("fields", o);
- }
+ Some(val) => return Err(ExpectedError(~"List", format!("{}", val))),
+ None => return Err(MissingFieldError(~"fields"))
}
n
}
- json => self.expected("string or object", &json)
+ json => return Err(ExpectedError(~"String or Object", format!("{}", json)))
};
let idx = match names.iter().position(|n| str::eq_slice(*n, name)) {
Some(idx) => idx,
- None => self.err(format!("unknown variant name: {}", name))
+ None => return Err(UnknownVariantError(name))
};
f(self, idx)
}
- fn read_enum_variant_arg<T>(&mut self, idx: uint, f: |&mut Decoder| -> T)
- -> T {
+ fn read_enum_variant_arg<T>(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_enum_variant_arg(idx={})", idx);
f(self)
}
fn read_enum_struct_variant<T>(&mut self,
names: &[&str],
- f: |&mut Decoder, uint| -> T)
- -> T {
+ f: |&mut Decoder, uint| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_enum_struct_variant(names={:?})", names);
self.read_enum_variant(names, f)
}
fn read_enum_struct_variant_field<T>(&mut self,
name: &str,
idx: uint,
- f: |&mut Decoder| -> T)
- -> T {
+ f: |&mut Decoder| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_enum_struct_variant_field(name={}, idx={})", name, idx);
self.read_enum_variant_arg(idx, f)
}
fn read_struct<T>(&mut self,
name: &str,
len: uint,
- f: |&mut Decoder| -> T)
- -> T {
+ f: |&mut Decoder| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_struct(name={}, len={})", name, len);
- let value = f(self);
- self.stack.pop().unwrap();
- value
+ let value = try!(f(self));
+ self.pop();
+ Ok(value)
}
fn read_struct_field<T>(&mut self,
name: &str,
idx: uint,
- f: |&mut Decoder| -> T)
- -> T {
+ f: |&mut Decoder| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_struct_field(name={}, idx={})", name, idx);
- match self.stack.pop().unwrap() {
- Object(mut obj) => {
- let value = match obj.pop(&name.to_owned()) {
- None => self.missing_field(name, obj),
- Some(json) => {
- self.stack.push(json);
- f(self)
- }
- };
- self.stack.push(Object(obj));
- value
+ let mut obj = try!(expect!(self.pop(), Object));
+
+ let value = match obj.pop(&name.to_owned()) {
+ None => return Err(MissingFieldError(name.to_owned())),
+ Some(json) => {
+ self.stack.push(json);
+ try!(f(self))
}
- value => self.expected("object", &value)
- }
+ };
+ self.stack.push(Object(obj));
+ Ok(value)
}
- fn read_tuple<T>(&mut self, f: |&mut Decoder, uint| -> T) -> T {
+ fn read_tuple<T>(&mut self, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
debug!("read_tuple()");
self.read_seq(f)
}
- fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder| -> T) -> T {
+ fn read_tuple_arg<T>(&mut self,
+ idx: uint,
+ f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
debug!("read_tuple_arg(idx={})", idx);
self.read_seq_elt(idx, f)
}
fn read_tuple_struct<T>(&mut self,
name: &str,
- f: |&mut Decoder, uint| -> T)
- -> T {
+ f: |&mut Decoder, uint| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_tuple_struct(name={})", name);
self.read_tuple(f)
}
fn read_tuple_struct_arg<T>(&mut self,
idx: uint,
- f: |&mut Decoder| -> T)
- -> T {
+ f: |&mut Decoder| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_tuple_struct_arg(idx={})", idx);
self.read_tuple_arg(idx, f)
}
- fn read_option<T>(&mut self, f: |&mut Decoder, bool| -> T) -> T {
- match self.stack.pop().unwrap() {
+ fn read_option<T>(&mut self, f: |&mut Decoder, bool| -> DecodeResult<T>) -> DecodeResult<T> {
+ match self.pop() {
Null => f(self, false),
value => { self.stack.push(value); f(self, true) }
}
}
- fn read_seq<T>(&mut self, f: |&mut Decoder, uint| -> T) -> T {
+ fn read_seq<T>(&mut self, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
debug!("read_seq()");
- let len = match self.stack.pop().unwrap() {
- List(list) => {
- let len = list.len();
- for v in list.move_rev_iter() {
- self.stack.push(v);
- }
- len
- }
- value => self.expected("list", &value)
- };
+ let list = try!(expect!(self.pop(), List));
+ let len = list.len();
+ for v in list.move_rev_iter() {
+ self.stack.push(v);
+ }
f(self, len)
}
- fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder| -> T) -> T {
+ fn read_seq_elt<T>(&mut self,
+ idx: uint,
+ f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
debug!("read_seq_elt(idx={})", idx);
f(self)
}
- fn read_map<T>(&mut self, f: |&mut Decoder, uint| -> T) -> T {
+ fn read_map<T>(&mut self, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
debug!("read_map()");
- let len = match self.stack.pop().unwrap() {
- Object(obj) => {
- let len = obj.len();
- for (key, value) in obj.move_iter() {
- self.stack.push(value);
- self.stack.push(String(key));
- }
- len
- }
- value => self.expected("object", &value)
- };
+ let obj = try!(expect!(self.pop(), Object));
+ let len = obj.len();
+ for (key, value) in obj.move_iter() {
+ self.stack.push(value);
+ self.stack.push(String(key));
+ }
f(self, len)
}
- fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder| -> T)
- -> T {
+ fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_map_elt_key(idx={})", idx);
f(self)
}
- fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder| -> T)
- -> T {
+ fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult<T>)
+ -> DecodeResult<T> {
debug!("read_map_elt_val(idx={})", idx);
f(self)
}
}
}
-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;
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\""
);
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 \
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\"");
}
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");
}
#[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)));
#[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)));
#[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")));
#[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(~[])));
#[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(),
]
}";
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 {
#[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));
}
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)));
#[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)]
A(f64),
B(~str)
}
- fn check_err<T: Decodable<Decoder>>(to_parse: &'static str, expected_error: &str) {
- use std::any::AnyRefExt;
- use std::task;
- let res = task::try(proc() {
- // either fails in `decode` (which is what we want), or
- // returns Some(error_message)/None if the string was
- // invalid or valid JSON.
- match from_str(to_parse) {
- Err(e) => Some(e.to_str()),
- Ok(json) => {
- let _: T = Decodable::decode(&mut Decoder::new(json));
- None
- }
- }
- });
+ fn check_err<T: Decodable<Decoder, Error>>(to_parse: &'static str, expected: Error) {
+ let res: DecodeResult<T> = match from_str(to_parse) {
+ Err(e) => Err(e),
+ Ok(json) => Decodable::decode(&mut Decoder::new(json))
+ };
match res {
- Ok(Some(parse_error)) => fail!("`{}` is not valid json: {}",
- to_parse, parse_error),
- Ok(None) => fail!("`{}` parsed & decoded ok, expecting error `{}`",
- to_parse, expected_error),
+ Ok(_) => fail!("`{}` parsed & decoded ok, expecting error `{}`",
+ to_parse, expected),
+ Err(ParseError(e, _, _)) => fail!("`{}` is not valid json: {}",
+ to_parse, e),
Err(e) => {
- let err = e.as_ref::<~str>().unwrap();
- assert!(err.contains(expected_error),
- "`{}` errored incorrectly, found `{}` expecting `{}`",
- to_parse, *err, expected_error);
+ assert_eq!(e, expected);
}
+
}
}
#[test]
fn test_decode_errors_struct() {
- check_err::<DecodeStruct>("[]", "object but found list");
+ check_err::<DecodeStruct>("[]", ExpectedError(~"Object", ~"[]"));
check_err::<DecodeStruct>("{\"x\": true, \"y\": true, \"z\": \"\", \"w\": []}",
- "number but found boolean");
+ ExpectedError(~"Number", ~"true"));
check_err::<DecodeStruct>("{\"x\": 1, \"y\": [], \"z\": \"\", \"w\": []}",
- "boolean but found list");
+ ExpectedError(~"Boolean", ~"[]"));
check_err::<DecodeStruct>("{\"x\": 1, \"y\": true, \"z\": {}, \"w\": []}",
- "string but found object");
+ ExpectedError(~"String", ~"{}"));
check_err::<DecodeStruct>("{\"x\": 1, \"y\": true, \"z\": \"\", \"w\": null}",
- "list but found null");
+ ExpectedError(~"List", ~"null"));
check_err::<DecodeStruct>("{\"x\": 1, \"y\": true, \"z\": \"\"}",
- "'w' field in object");
+ MissingFieldError(~"w"));
}
#[test]
fn test_decode_errors_enum() {
check_err::<DecodeEnum>("{}",
- "'variant' field in object");
+ MissingFieldError(~"variant"));
check_err::<DecodeEnum>("{\"variant\": 1}",
- "string but found number");
+ ExpectedError(~"String", ~"1"));
check_err::<DecodeEnum>("{\"variant\": \"A\"}",
- "'fields' field in object");
+ MissingFieldError(~"fields"));
check_err::<DecodeEnum>("{\"variant\": \"A\", \"fields\": null}",
- "list but found null");
+ ExpectedError(~"List", ~"null"));
check_err::<DecodeEnum>("{\"variant\": \"C\", \"fields\": []}",
- "unknown variant name");
+ UnknownVariantError(~"C"));
}
#[test]
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();
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();
Ok(o) => o
};
let mut decoder = Decoder::new(json_obj);
- let _hm: HashMap<uint, bool> = Decodable::decode(&mut decoder);
+ let _hm: HashMap<uint, bool> = Decodable::decode(&mut decoder).unwrap();
}
}
--- /dev/null
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Rust JSON serialization library
+// Copyright (c) 2011 Google Inc.
+
+#[forbid(non_camel_case_types)];
+#[allow(missing_doc)];
+
+/*!
+JSON parsing and serialization
+
+# What is JSON?
+
+JSON (JavaScript Object Notation) is a way to write data in Javascript.
+Like XML it allows one to encode structured data in a text format that can be read by humans easily.
+Its native compatibility with JavaScript and its simple syntax make it used widely.
+
+Json data are encoded in a form of "key":"value".
+Data types that can be encoded are JavaScript types :
+boolean (`true` or `false`), number (`f64`), string, array, object, null.
+An object is a series of string keys mapping to values, in `"key": value` format.
+Arrays are enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }).
+A simple JSON document encoding a person, his/her age, address and phone numbers could look like:
+
+```ignore
+{
+ "FirstName": "John",
+ "LastName": "Doe",
+ "Age": 43,
+ "Address": {
+ "Street": "Downing Street 10",
+ "City": "London",
+ "Country": "Great Britain"
+ },
+ "PhoneNumbers": [
+ "+44 1234567",
+ "+44 2345678"
+ ]
+}
+```
+
+# Rust Type-based Encoding and Decoding
+
+Rust provides a mechanism for low boilerplate encoding & decoding
+of values to and from JSON via the serialization API.
+To be able to encode a piece of data, it must implement the `serialize::Encodable` trait.
+To be able to decode a piece of data, it must implement the `serialize::Decodable` trait.
+The Rust compiler provides an annotation to automatically generate
+the code for these traits: `#[deriving(Decodable, Encodable)]`
+
+To encode using Encodable :
+
+```rust
+use std::io;
+use serialize::{json, Encodable};
+
+ #[deriving(Encodable)]
+ pub struct TestStruct {
+ data_str: ~str,
+ }
+
+fn main() {
+ let to_encode_object = TestStruct{data_str:~"example of string to encode"};
+ let mut m = io::MemWriter::new();
+ {
+ let mut encoder = json::Encoder::new(&mut m as &mut std::io::Writer);
+ to_encode_object.encode(&mut encoder);
+ }
+}
+```
+
+Two wrapper functions are provided to encode a Encodable object
+into a string (~str) or buffer (~[u8]): `str_encode(&m)` and `buffer_encode(&m)`.
+
+```rust
+use serialize::json;
+let to_encode_object = ~"example of string to encode";
+let encoded_str: ~str = json::Encoder::str_encode(&to_encode_object);
+```
+
+JSON API provide an enum `json::Json` and a trait `ToJson` to encode object.
+The trait `ToJson` encode object into a container `json::Json` and the API provide writer
+to encode them into a stream or a string ...
+
+When using `ToJson` the `Encodable` trait implementation is not mandatory.
+
+A basic `ToJson` example using a TreeMap of attribute name / attribute value:
+
+
+```rust
+extern crate collections;
+extern crate serialize;
+
+use serialize::json;
+use serialize::json::ToJson;
+use collections::TreeMap;
+
+pub struct MyStruct {
+ attr1: u8,
+ attr2: ~str,
+}
+
+impl ToJson for MyStruct {
+ fn to_json( &self ) -> json::Json {
+ let mut d = ~TreeMap::new();
+ d.insert(~"attr1", self.attr1.to_json());
+ d.insert(~"attr2", self.attr2.to_json());
+ json::Object(d)
+ }
+}
+
+fn main() {
+ let test2: MyStruct = MyStruct {attr1: 1, attr2:~"test"};
+ let tjson: json::Json = test2.to_json();
+ let json_str: ~str = tjson.to_str();
+}
+```
+
+To decode a JSON string using `Decodable` trait :
+
+```rust
+extern crate serialize;
+use serialize::{json, Decodable};
+
+#[deriving(Decodable)]
+pub struct MyStruct {
+ attr1: u8,
+ attr2: ~str,
+}
+
+fn main() {
+ let json_str_to_decode: ~str =
+ ~"{\"attr1\":1,\"attr2\":\"toto\"}";
+ let json_object = json::from_str(json_str_to_decode);
+ let mut decoder = json::Decoder::new(json_object.unwrap());
+ let decoded_object: MyStruct = Decodable::decode(&mut decoder); // create the final object
+}
+```
+
+# Examples of use
+
+## Using Autoserialization
+
+Create a struct called TestStruct1 and serialize and deserialize it to and from JSON
+using the serialization API, using the derived serialization code.
+
+```rust
+extern crate serialize;
+use serialize::{json, Encodable, Decodable};
+
+ #[deriving(Decodable, Encodable)] //generate Decodable, Encodable impl.
+ pub struct TestStruct1 {
+ data_int: u8,
+ data_str: ~str,
+ data_vector: ~[u8],
+ }
+
+// To serialize use the `json::str_encode` to encode an object in a string.
+// It calls the generated `Encodable` impl.
+fn main() {
+ let to_encode_object = TestStruct1
+ {data_int: 1, data_str:~"toto", data_vector:~[2,3,4,5]};
+ let encoded_str: ~str = json::Encoder::str_encode(&to_encode_object);
+
+ // To deserialize use the `json::from_str` and `json::Decoder`
+
+ let json_object = json::from_str(encoded_str);
+ let mut decoder = json::Decoder::new(json_object.unwrap());
+ let decoded1: TestStruct1 = Decodable::decode(&mut decoder); // create the final object
+}
+```
+
+## Using `ToJson`
+
+This example use the ToJson impl to deserialize the JSON string.
+Example of `ToJson` trait implementation for TestStruct1.
+
+```rust
+extern crate serialize;
+extern crate collections;
+
+use serialize::json::ToJson;
+use serialize::{json, Encodable, Decodable};
+use collections::TreeMap;
+
+#[deriving(Decodable, Encodable)] // generate Decodable, Encodable impl.
+pub struct TestStruct1 {
+ data_int: u8,
+ data_str: ~str,
+ data_vector: ~[u8],
+}
+
+impl ToJson for TestStruct1 {
+ fn to_json( &self ) -> json::Json {
+ let mut d = ~TreeMap::new();
+ d.insert(~"data_int", self.data_int.to_json());
+ d.insert(~"data_str", self.data_str.to_json());
+ d.insert(~"data_vector", self.data_vector.to_json());
+ json::Object(d)
+ }
+}
+
+fn main() {
+ // Serialization using our impl of to_json
+
+ let test2: TestStruct1 = TestStruct1 {data_int: 1, data_str:~"toto", data_vector:~[2,3,4,5]};
+ let tjson: json::Json = test2.to_json();
+ let json_str: ~str = tjson.to_str();
+
+ // Deserialize like before.
+
+ let mut decoder = json::Decoder::new(json::from_str(json_str).unwrap());
+ // create the final object
+ let decoded2: TestStruct1 = Decodable::decode(&mut decoder);
+}
+```
+
+*/
+
+use std::char;
+use std::f64;
+use collections::HashMap;
+use std::io;
+use std::io::MemWriter;
+use std::num;
+use std::str;
+use std::fmt;
+
+use Encodable;
+use collections::TreeMap;
+
+macro_rules! try( ($e:expr) => (
+ match $e { Ok(e) => e, Err(e) => { self.error = Err(e); return } }
+) )
+
+/// Represents a json value
+#[deriving(Clone, Eq)]
+pub enum Json {
+ Number(f64),
+ String(~str),
+ Boolean(bool),
+ List(List),
+ Object(~Object),
+ Null,
+}
+
+pub type List = ~[Json];
+pub type Object = TreeMap<~str, Json>;
+
+#[deriving(Eq)]
+/// If an error occurs while parsing some JSON, this is the structure which is
+/// returned
+pub struct Error {
+ /// The line number at which the error occurred
+ priv line: uint,
+ /// The column number at which the error occurred
+ priv col: uint,
+ /// A message describing the type of the error
+ priv msg: ~str,
+}
+
+fn io_error_to_error(io: io::IoError) -> Error {
+ Error {
+ line: 0,
+ col: 0,
+ msg: format!("io error: {}", io)
+ }
+}
+
+fn escape_str(s: &str) -> ~str {
+ let mut escaped = ~"\"";
+ for c in s.chars() {
+ match c {
+ '"' => escaped.push_str("\\\""),
+ '\\' => escaped.push_str("\\\\"),
+ '\x08' => escaped.push_str("\\b"),
+ '\x0c' => escaped.push_str("\\f"),
+ '\n' => escaped.push_str("\\n"),
+ '\r' => escaped.push_str("\\r"),
+ '\t' => escaped.push_str("\\t"),
+ _ => escaped.push_char(c),
+ }
+ };
+
+ escaped.push_char('"');
+
+ escaped
+}
+
+fn spaces(n: uint) -> ~str {
+ let mut ss = ~"";
+ for _ in range(0, n) { ss.push_str(" "); }
+ return ss;
+}
+
+/// A structure for implementing serialization to JSON.
+pub struct Encoder<'a> {
+ priv wr: &'a mut io::Writer,
+ priv error: io::IoResult<()>,
+}
+
+impl<'a> Encoder<'a> {
+ /// Creates a new JSON encoder whose output will be written to the writer
+ /// specified.
+ pub fn new<'a>(wr: &'a mut io::Writer) -> Encoder<'a> {
+ Encoder { wr: wr, error: Ok(()) }
+ }
+
+ /// Encode the specified struct into a json [u8]
+ pub fn buffer_encode<T:Encodable<Encoder<'a>>>(to_encode_object: &T) -> ~[u8] {
+ //Serialize the object in a string using a writer
+ let mut m = MemWriter::new();
+ {
+ let mut encoder = Encoder::new(&mut m as &mut io::Writer);
+ to_encode_object.encode(&mut encoder);
+ }
+ m.unwrap()
+ }
+
+ /// Encode the specified struct into a json str
+ pub fn str_encode<T:Encodable<Encoder<'a>>>(to_encode_object: &T) -> ~str {
+ let buff:~[u8] = Encoder::buffer_encode(to_encode_object);
+ str::from_utf8_owned(buff).unwrap()
+ }
+}
+
+impl<'a> ::Encoder for Encoder<'a> {
+ fn emit_nil(&mut self) { try!(write!(self.wr, "null")) }
+
+ fn emit_uint(&mut self, v: uint) { self.emit_f64(v as f64); }
+ fn emit_u64(&mut self, v: u64) { self.emit_f64(v as f64); }
+ fn emit_u32(&mut self, v: u32) { self.emit_f64(v as f64); }
+ fn emit_u16(&mut self, v: u16) { self.emit_f64(v as f64); }
+ fn emit_u8(&mut self, v: u8) { self.emit_f64(v as f64); }
+
+ fn emit_int(&mut self, v: int) { self.emit_f64(v as f64); }
+ fn emit_i64(&mut self, v: i64) { self.emit_f64(v as f64); }
+ fn emit_i32(&mut self, v: i32) { self.emit_f64(v as f64); }
+ fn emit_i16(&mut self, v: i16) { self.emit_f64(v as f64); }
+ fn emit_i8(&mut self, v: i8) { self.emit_f64(v as f64); }
+
+ fn emit_bool(&mut self, v: bool) {
+ if v {
+ try!(write!(self.wr, "true"));
+ } else {
+ try!(write!(self.wr, "false"));
+ }
+ }
+
+ fn emit_f64(&mut self, v: f64) {
+ try!(write!(self.wr, "{}", f64::to_str_digits(v, 6u)))
+ }
+ fn emit_f32(&mut self, v: f32) { self.emit_f64(v as f64); }
+
+ fn emit_char(&mut self, v: char) { self.emit_str(str::from_char(v)) }
+ fn emit_str(&mut self, v: &str) {
+ try!(write!(self.wr, "{}", escape_str(v)))
+ }
+
+ fn emit_enum(&mut self, _name: &str, f: |&mut Encoder<'a>|) { f(self) }
+
+ fn emit_enum_variant(&mut self,
+ name: &str,
+ _id: uint,
+ cnt: uint,
+ f: |&mut Encoder<'a>|) {
+ // enums are encoded as strings or objects
+ // Bunny => "Bunny"
+ // Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]}
+ if cnt == 0 {
+ try!(write!(self.wr, "{}", escape_str(name)));
+ } else {
+ try!(write!(self.wr, "\\{\"variant\":"));
+ try!(write!(self.wr, "{}", escape_str(name)));
+ try!(write!(self.wr, ",\"fields\":["));
+ f(self);
+ try!(write!(self.wr, "]\\}"));
+ }
+ }
+
+ fn emit_enum_variant_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+ if idx != 0 {
+ try!(write!(self.wr, ","));
+ }
+ f(self);
+ }
+
+ fn emit_enum_struct_variant(&mut self,
+ name: &str,
+ id: uint,
+ cnt: uint,
+ f: |&mut Encoder<'a>|) {
+ self.emit_enum_variant(name, id, cnt, f)
+ }
+
+ fn emit_enum_struct_variant_field(&mut self,
+ _: &str,
+ idx: uint,
+ f: |&mut Encoder<'a>|) {
+ self.emit_enum_variant_arg(idx, f)
+ }
+
+ fn emit_struct(&mut self, _: &str, _: uint, f: |&mut Encoder<'a>|) {
+ try!(write!(self.wr, r"\{"));
+ f(self);
+ try!(write!(self.wr, r"\}"));
+ }
+
+ fn emit_struct_field(&mut self,
+ name: &str,
+ idx: uint,
+ f: |&mut Encoder<'a>|) {
+ if idx != 0 { try!(write!(self.wr, ",")) }
+ try!(write!(self.wr, "{}:", escape_str(name)));
+ f(self);
+ }
+
+ fn emit_tuple(&mut self, len: uint, f: |&mut Encoder<'a>|) {
+ self.emit_seq(len, f)
+ }
+ fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+ self.emit_seq_elt(idx, f)
+ }
+
+ fn emit_tuple_struct(&mut self,
+ _name: &str,
+ len: uint,
+ f: |&mut Encoder<'a>|) {
+ self.emit_seq(len, f)
+ }
+ fn emit_tuple_struct_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+ self.emit_seq_elt(idx, f)
+ }
+
+ fn emit_option(&mut self, f: |&mut Encoder<'a>|) { f(self); }
+ fn emit_option_none(&mut self) { self.emit_nil(); }
+ fn emit_option_some(&mut self, f: |&mut Encoder<'a>|) { f(self); }
+
+ fn emit_seq(&mut self, _len: uint, f: |&mut Encoder<'a>|) {
+ try!(write!(self.wr, "["));
+ f(self);
+ try!(write!(self.wr, "]"));
+ }
+
+ fn emit_seq_elt(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+ if idx != 0 {
+ try!(write!(self.wr, ","));
+ }
+ f(self)
+ }
+
+ fn emit_map(&mut self, _len: uint, f: |&mut Encoder<'a>|) {
+ try!(write!(self.wr, r"\{"));
+ f(self);
+ try!(write!(self.wr, r"\}"));
+ }
+
+ fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
+ use std::str::from_utf8;
+ if idx != 0 { try!(write!(self.wr, ",")) }
+ // ref #12967, make sure to wrap a key in double quotes,
+ // in the event that its of a type that omits them (eg numbers)
+ let mut buf = MemWriter::new();
+ let mut check_encoder = Encoder::new(&mut buf);
+ f(&mut check_encoder);
+ let buf = buf.unwrap();
+ let out = from_utf8(buf).unwrap();
+ let needs_wrapping = out.char_at(0) != '"' &&
+ out.char_at_reverse(out.len()) != '"';
+ if needs_wrapping { try!(write!(self.wr, "\"")); }
+ f(self);
+ if needs_wrapping { try!(write!(self.wr, "\"")); }
+ }
+
+ fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
+ try!(write!(self.wr, ":"));
+ f(self)
+ }
+}
+
+/// Another encoder for JSON, but prints out human-readable JSON instead of
+/// compact data
+pub struct PrettyEncoder<'a> {
+ priv wr: &'a mut io::Writer,
+ priv indent: uint,
+ priv error: io::IoResult<()>,
+}
+
+impl<'a> PrettyEncoder<'a> {
+ /// Creates a new encoder whose output will be written to the specified writer
+ pub fn new<'a>(wr: &'a mut io::Writer) -> PrettyEncoder<'a> {
+ PrettyEncoder {
+ wr: wr,
+ indent: 0,
+ error: Ok(())
+ }
+ }
+}
+
+impl<'a> ::Encoder for PrettyEncoder<'a> {
+ fn emit_nil(&mut self) { try!(write!(self.wr, "null")); }
+
+ fn emit_uint(&mut self, v: uint) { self.emit_f64(v as f64); }
+ fn emit_u64(&mut self, v: u64) { self.emit_f64(v as f64); }
+ fn emit_u32(&mut self, v: u32) { self.emit_f64(v as f64); }
+ fn emit_u16(&mut self, v: u16) { self.emit_f64(v as f64); }
+ fn emit_u8(&mut self, v: u8) { self.emit_f64(v as f64); }
+
+ fn emit_int(&mut self, v: int) { self.emit_f64(v as f64); }
+ fn emit_i64(&mut self, v: i64) { self.emit_f64(v as f64); }
+ fn emit_i32(&mut self, v: i32) { self.emit_f64(v as f64); }
+ fn emit_i16(&mut self, v: i16) { self.emit_f64(v as f64); }
+ fn emit_i8(&mut self, v: i8) { self.emit_f64(v as f64); }
+
+ fn emit_bool(&mut self, v: bool) {
+ if v {
+ try!(write!(self.wr, "true"));
+ } else {
+ try!(write!(self.wr, "false"));
+ }
+ }
+
+ fn emit_f64(&mut self, v: f64) {
+ try!(write!(self.wr, "{}", f64::to_str_digits(v, 6u)));
+ }
+ fn emit_f32(&mut self, v: f32) { self.emit_f64(v as f64); }
+
+ fn emit_char(&mut self, v: char) { self.emit_str(str::from_char(v)) }
+ fn emit_str(&mut self, v: &str) {
+ try!(write!(self.wr, "{}", escape_str(v)));
+ }
+
+ fn emit_enum(&mut self, _name: &str, f: |&mut PrettyEncoder<'a>|) {
+ f(self)
+ }
+
+ fn emit_enum_variant(&mut self,
+ name: &str,
+ _: uint,
+ cnt: uint,
+ f: |&mut PrettyEncoder<'a>|) {
+ if cnt == 0 {
+ try!(write!(self.wr, "{}", escape_str(name)));
+ } else {
+ self.indent += 2;
+ try!(write!(self.wr, "[\n{}{},\n", spaces(self.indent),
+ escape_str(name)));
+ f(self);
+ self.indent -= 2;
+ try!(write!(self.wr, "\n{}]", spaces(self.indent)));
+ }
+ }
+
+ fn emit_enum_variant_arg(&mut self,
+ idx: uint,
+ f: |&mut PrettyEncoder<'a>|) {
+ if idx != 0 {
+ try!(write!(self.wr, ",\n"));
+ }
+ try!(write!(self.wr, "{}", spaces(self.indent)));
+ f(self)
+ }
+
+ fn emit_enum_struct_variant(&mut self,
+ name: &str,
+ id: uint,
+ cnt: uint,
+ f: |&mut PrettyEncoder<'a>|) {
+ self.emit_enum_variant(name, id, cnt, f)
+ }
+
+ fn emit_enum_struct_variant_field(&mut self,
+ _: &str,
+ idx: uint,
+ f: |&mut PrettyEncoder<'a>|) {
+ self.emit_enum_variant_arg(idx, f)
+ }
+
+
+ fn emit_struct(&mut self,
+ _: &str,
+ len: uint,
+ f: |&mut PrettyEncoder<'a>|) {
+ if len == 0 {
+ try!(write!(self.wr, "\\{\\}"));
+ } else {
+ try!(write!(self.wr, "\\{"));
+ self.indent += 2;
+ f(self);
+ self.indent -= 2;
+ try!(write!(self.wr, "\n{}\\}", spaces(self.indent)));
+ }
+ }
+
+ fn emit_struct_field(&mut self,
+ name: &str,
+ idx: uint,
+ f: |&mut PrettyEncoder<'a>|) {
+ if idx == 0 {
+ try!(write!(self.wr, "\n"));
+ } else {
+ try!(write!(self.wr, ",\n"));
+ }
+ try!(write!(self.wr, "{}{}: ", spaces(self.indent), escape_str(name)));
+ f(self);
+ }
+
+ fn emit_tuple(&mut self, len: uint, f: |&mut PrettyEncoder<'a>|) {
+ self.emit_seq(len, f)
+ }
+ fn emit_tuple_arg(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
+ self.emit_seq_elt(idx, f)
+ }
+
+ fn emit_tuple_struct(&mut self,
+ _: &str,
+ len: uint,
+ f: |&mut PrettyEncoder<'a>|) {
+ self.emit_seq(len, f)
+ }
+ fn emit_tuple_struct_arg(&mut self,
+ idx: uint,
+ f: |&mut PrettyEncoder<'a>|) {
+ self.emit_seq_elt(idx, f)
+ }
+
+ fn emit_option(&mut self, f: |&mut PrettyEncoder<'a>|) { f(self); }
+ fn emit_option_none(&mut self) { self.emit_nil(); }
+ fn emit_option_some(&mut self, f: |&mut PrettyEncoder<'a>|) { f(self); }
+
+ fn emit_seq(&mut self, len: uint, f: |&mut PrettyEncoder<'a>|) {
+ if len == 0 {
+ try!(write!(self.wr, "[]"));
+ } else {
+ try!(write!(self.wr, "["));
+ self.indent += 2;
+ f(self);
+ self.indent -= 2;
+ try!(write!(self.wr, "\n{}]", spaces(self.indent)));
+ }
+ }
+
+ fn emit_seq_elt(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
+ if idx == 0 {
+ try!(write!(self.wr, "\n"));
+ } else {
+ try!(write!(self.wr, ",\n"));
+ }
+ try!(write!(self.wr, "{}", spaces(self.indent)));
+ f(self)
+ }
+
+ fn emit_map(&mut self, len: uint, f: |&mut PrettyEncoder<'a>|) {
+ if len == 0 {
+ try!(write!(self.wr, "\\{\\}"));
+ } else {
+ try!(write!(self.wr, "\\{"));
+ self.indent += 2;
+ f(self);
+ self.indent -= 2;
+ try!(write!(self.wr, "\n{}\\}", spaces(self.indent)));
+ }
+ }
+
+ fn emit_map_elt_key(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
+ use std::str::from_utf8;
+ if idx == 0 {
+ try!(write!(self.wr, "\n"));
+ } else {
+ try!(write!(self.wr, ",\n"));
+ }
+ try!(write!(self.wr, "{}", spaces(self.indent)));
+ // ref #12967, make sure to wrap a key in double quotes,
+ // in the event that its of a type that omits them (eg numbers)
+ let mut buf = MemWriter::new();
+ let mut check_encoder = PrettyEncoder::new(&mut buf);
+ f(&mut check_encoder);
+ let buf = buf.unwrap();
+ let out = from_utf8(buf).unwrap();
+ let needs_wrapping = out.char_at(0) != '"' &&
+ out.char_at_reverse(out.len()) != '"';
+ if needs_wrapping { try!(write!(self.wr, "\"")); }
+ f(self);
+ if needs_wrapping { try!(write!(self.wr, "\"")); }
+ }
+
+ fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut PrettyEncoder<'a>|) {
+ try!(write!(self.wr, ": "));
+ f(self);
+ }
+}
+
+impl<E: ::Encoder> Encodable<E> for Json {
+ fn encode(&self, e: &mut E) {
+ match *self {
+ Number(v) => v.encode(e),
+ String(ref v) => v.encode(e),
+ Boolean(v) => v.encode(e),
+ List(ref v) => v.encode(e),
+ Object(ref v) => v.encode(e),
+ Null => e.emit_nil(),
+ }
+ }
+}
+
+impl Json {
+ /// Encodes a json value into a io::writer. Uses a single line.
+ pub fn to_writer(&self, wr: &mut io::Writer) -> io::IoResult<()> {
+ let mut encoder = Encoder::new(wr);
+ self.encode(&mut encoder);
+ encoder.error
+ }
+
+ /// Encodes a json value into a io::writer.
+ /// Pretty-prints in a more readable format.
+ pub fn to_pretty_writer(&self, wr: &mut io::Writer) -> io::IoResult<()> {
+ let mut encoder = PrettyEncoder::new(wr);
+ self.encode(&mut encoder);
+ encoder.error
+ }
+
+ /// Encodes a json value into a string
+ pub fn to_pretty_str(&self) -> ~str {
+ let mut s = MemWriter::new();
+ self.to_pretty_writer(&mut s as &mut io::Writer).unwrap();
+ str::from_utf8_owned(s.unwrap()).unwrap()
+ }
+
+ /// If the Json value is an Object, returns the value associated with the provided key.
+ /// Otherwise, returns None.
+ pub fn find<'a>(&'a self, key: &~str) -> Option<&'a Json>{
+ match self {
+ &Object(ref map) => map.find(key),
+ _ => None
+ }
+ }
+
+ /// Attempts to get a nested Json Object for each key in `keys`.
+ /// If any key is found not to exist, find_path will return None.
+ /// Otherwise, it will return the Json value associated with the final key.
+ pub fn find_path<'a>(&'a self, keys: &[&~str]) -> Option<&'a Json>{
+ let mut target = self;
+ for key in keys.iter() {
+ match target.find(*key) {
+ Some(t) => { target = t; },
+ None => return None
+ }
+ }
+ Some(target)
+ }
+
+ /// If the Json value is an Object, performs a depth-first search until
+ /// a value associated with the provided key is found. If no value is found
+ /// or the Json value is not an Object, returns None.
+ pub fn search<'a>(&'a self, key: &~str) -> Option<&'a Json> {
+ match self {
+ &Object(ref map) => {
+ match map.find(key) {
+ Some(json_value) => Some(json_value),
+ None => {
+ let mut value : Option<&'a Json> = None;
+ for (_, v) in map.iter() {
+ value = v.search(key);
+ if value.is_some() {
+ break;
+ }
+ }
+ value
+ }
+ }
+ },
+ _ => None
+ }
+ }
+
+ /// Returns true if the Json value is an Object. Returns false otherwise.
+ pub fn is_object<'a>(&'a self) -> bool {
+ self.as_object().is_some()
+ }
+
+ /// If the Json value is an Object, returns the associated TreeMap.
+ /// Returns None otherwise.
+ pub fn as_object<'a>(&'a self) -> Option<&'a Object> {
+ match self {
+ &Object(ref map) => Some(&**map),
+ _ => None
+ }
+ }
+
+ /// Returns true if the Json value is a List. Returns false otherwise.
+ pub fn is_list<'a>(&'a self) -> bool {
+ self.as_list().is_some()
+ }
+
+ /// If the Json value is a List, returns the associated vector.
+ /// Returns None otherwise.
+ pub fn as_list<'a>(&'a self) -> Option<&'a List> {
+ match self {
+ &List(ref list) => Some(&*list),
+ _ => None
+ }
+ }
+
+ /// Returns true if the Json value is a String. Returns false otherwise.
+ pub fn is_string<'a>(&'a self) -> bool {
+ self.as_string().is_some()
+ }
+
+ /// If the Json value is a String, returns the associated str.
+ /// Returns None otherwise.
+ pub fn as_string<'a>(&'a self) -> Option<&'a str> {
+ match *self {
+ String(ref s) => Some(s.as_slice()),
+ _ => None
+ }
+ }
+
+ /// Returns true if the Json value is a Number. Returns false otherwise.
+ pub fn is_number(&self) -> bool {
+ self.as_number().is_some()
+ }
+
+ /// If the Json value is a Number, returns the associated f64.
+ /// Returns None otherwise.
+ pub fn as_number(&self) -> Option<f64> {
+ match self {
+ &Number(n) => Some(n),
+ _ => None
+ }
+ }
+
+ /// Returns true if the Json value is a Boolean. Returns false otherwise.
+ pub fn is_boolean(&self) -> bool {
+ self.as_boolean().is_some()
+ }
+
+ /// If the Json value is a Boolean, returns the associated bool.
+ /// Returns None otherwise.
+ pub fn as_boolean(&self) -> Option<bool> {
+ match self {
+ &Boolean(b) => Some(b),
+ _ => None
+ }
+ }
+
+ /// Returns true if the Json value is a Null. Returns false otherwise.
+ pub fn is_null(&self) -> bool {
+ self.as_null().is_some()
+ }
+
+ /// If the Json value is a Null, returns ().
+ /// Returns None otherwise.
+ pub fn as_null(&self) -> Option<()> {
+ match self {
+ &Null => Some(()),
+ _ => None
+ }
+ }
+}
+
+pub struct Parser<T> {
+ priv rdr: T,
+ priv ch: Option<char>,
+ priv line: uint,
+ priv col: uint,
+}
+
+impl<T: Iterator<char>> Parser<T> {
+ /// Decode a json value from an Iterator<char>
+ pub fn new(rdr: T) -> Parser<T> {
+ let mut p = Parser {
+ rdr: rdr,
+ ch: Some('\x00'),
+ line: 1,
+ col: 0,
+ };
+ p.bump();
+ p
+ }
+}
+
+impl<T: Iterator<char>> Parser<T> {
+ pub fn parse(&mut self) -> Result<Json, Error> {
+ match self.parse_value() {
+ Ok(value) => {
+ // Skip trailing whitespaces.
+ self.parse_whitespace();
+ // Make sure there is no trailing characters.
+ if self.eof() {
+ Ok(value)
+ } else {
+ self.error(~"trailing characters")
+ }
+ }
+ Err(e) => Err(e)
+ }
+ }
+}
+
+impl<T : Iterator<char>> Parser<T> {
+ fn eof(&self) -> bool { self.ch.is_none() }
+ fn ch_or_null(&self) -> char { self.ch.unwrap_or('\x00') }
+ fn bump(&mut self) {
+ self.ch = self.rdr.next();
+
+ if self.ch_is('\n') {
+ self.line += 1u;
+ self.col = 1u;
+ } else {
+ self.col += 1u;
+ }
+ }
+
+ fn next_char(&mut self) -> Option<char> {
+ self.bump();
+ self.ch
+ }
+ fn ch_is(&self, c: char) -> bool {
+ self.ch == Some(c)
+ }
+
+ fn error<T>(&self, msg: ~str) -> Result<T, Error> {
+ Err(Error { line: self.line, col: self.col, msg: msg })
+ }
+
+ fn parse_value(&mut self) -> Result<Json, Error> {
+ self.parse_whitespace();
+
+ if self.eof() { return self.error(~"EOF while parsing value"); }
+
+ match self.ch_or_null() {
+ 'n' => self.parse_ident("ull", Null),
+ 't' => self.parse_ident("rue", Boolean(true)),
+ 'f' => self.parse_ident("alse", Boolean(false)),
+ '0' .. '9' | '-' => self.parse_number(),
+ '"' => {
+ match self.parse_str() {
+ Ok(s) => Ok(String(s)),
+ Err(e) => Err(e),
+ }
+ },
+ '[' => self.parse_list(),
+ '{' => self.parse_object(),
+ _ => self.error(~"invalid syntax"),
+ }
+ }
+
+ fn parse_whitespace(&mut self) {
+ while self.ch_is(' ') ||
+ self.ch_is('\n') ||
+ self.ch_is('\t') ||
+ self.ch_is('\r') { self.bump(); }
+ }
+
+ fn parse_ident(&mut self, ident: &str, value: Json) -> Result<Json, Error> {
+ if ident.chars().all(|c| Some(c) == self.next_char()) {
+ self.bump();
+ Ok(value)
+ } else {
+ self.error(~"invalid syntax")
+ }
+ }
+
+ fn parse_number(&mut self) -> Result<Json, Error> {
+ let mut neg = 1.0;
+
+ if self.ch_is('-') {
+ self.bump();
+ neg = -1.0;
+ }
+
+ let mut res = match self.parse_integer() {
+ Ok(res) => res,
+ Err(e) => return Err(e)
+ };
+
+ if self.ch_is('.') {
+ match self.parse_decimal(res) {
+ Ok(r) => res = r,
+ Err(e) => return Err(e)
+ }
+ }
+
+ if self.ch_is('e') || self.ch_is('E') {
+ match self.parse_exponent(res) {
+ Ok(r) => res = r,
+ Err(e) => return Err(e)
+ }
+ }
+
+ Ok(Number(neg * res))
+ }
+
+ fn parse_integer(&mut self) -> Result<f64, Error> {
+ let mut res = 0.0;
+
+ match self.ch_or_null() {
+ '0' => {
+ self.bump();
+
+ // There can be only one leading '0'.
+ match self.ch_or_null() {
+ '0' .. '9' => return self.error(~"invalid number"),
+ _ => ()
+ }
+ },
+ '1' .. '9' => {
+ while !self.eof() {
+ match self.ch_or_null() {
+ c @ '0' .. '9' => {
+ res *= 10.0;
+ res += ((c as int) - ('0' as int)) as f64;
+
+ self.bump();
+ }
+ _ => break,
+ }
+ }
+ }
+ _ => return self.error(~"invalid number"),
+ }
+ Ok(res)
+ }
+
+ fn parse_decimal(&mut self, res: f64) -> Result<f64, Error> {
+ self.bump();
+
+ // Make sure a digit follows the decimal place.
+ match self.ch_or_null() {
+ '0' .. '9' => (),
+ _ => return self.error(~"invalid number")
+ }
+
+ let mut res = res;
+ let mut dec = 1.0;
+ while !self.eof() {
+ match self.ch_or_null() {
+ c @ '0' .. '9' => {
+ dec /= 10.0;
+ res += (((c as int) - ('0' as int)) as f64) * dec;
+
+ self.bump();
+ }
+ _ => break,
+ }
+ }
+
+ Ok(res)
+ }
+
+ fn parse_exponent(&mut self, mut res: f64) -> Result<f64, Error> {
+ self.bump();
+
+ let mut exp = 0u;
+ let mut neg_exp = false;
+
+ if self.ch_is('+') {
+ self.bump();
+ } else if self.ch_is('-') {
+ self.bump();
+ neg_exp = true;
+ }
+
+ // Make sure a digit follows the exponent place.
+ match self.ch_or_null() {
+ '0' .. '9' => (),
+ _ => return self.error(~"invalid number")
+ }
+ while !self.eof() {
+ match self.ch_or_null() {
+ c @ '0' .. '9' => {
+ exp *= 10;
+ exp += (c as uint) - ('0' as uint);
+
+ self.bump();
+ }
+ _ => break
+ }
+ }
+
+ let exp: f64 = num::pow(10u as f64, exp);
+ if neg_exp {
+ res /= exp;
+ } else {
+ res *= exp;
+ }
+
+ Ok(res)
+ }
+
+ fn parse_str(&mut self) -> Result<~str, Error> {
+ let mut escape = false;
+ let mut res = ~"";
+
+ loop {
+ self.bump();
+ if self.eof() {
+ return self.error(~"EOF while parsing string");
+ }
+
+ if escape {
+ match self.ch_or_null() {
+ '"' => res.push_char('"'),
+ '\\' => res.push_char('\\'),
+ '/' => res.push_char('/'),
+ 'b' => res.push_char('\x08'),
+ 'f' => res.push_char('\x0c'),
+ 'n' => res.push_char('\n'),
+ 'r' => res.push_char('\r'),
+ 't' => res.push_char('\t'),
+ 'u' => {
+ // Parse \u1234.
+ let mut i = 0u;
+ let mut n = 0u;
+ while i < 4u && !self.eof() {
+ self.bump();
+ n = match self.ch_or_null() {
+ c @ '0' .. '9' => n * 16u + (c as uint) - ('0' as uint),
+ 'a' | 'A' => n * 16u + 10u,
+ 'b' | 'B' => n * 16u + 11u,
+ 'c' | 'C' => n * 16u + 12u,
+ 'd' | 'D' => n * 16u + 13u,
+ 'e' | 'E' => n * 16u + 14u,
+ 'f' | 'F' => n * 16u + 15u,
+ _ => return self.error(
+ ~"invalid \\u escape (unrecognized hex)")
+ };
+
+ i += 1u;
+ }
+
+ // Error out if we didn't parse 4 digits.
+ if i != 4u {
+ return self.error(
+ ~"invalid \\u escape (not four digits)");
+ }
+
+ res.push_char(char::from_u32(n as u32).unwrap());
+ }
+ _ => return self.error(~"invalid escape"),
+ }
+ escape = false;
+ } else if self.ch_is('\\') {
+ escape = true;
+ } else {
+ match self.ch {
+ Some('"') => { self.bump(); return Ok(res); },
+ Some(c) => res.push_char(c),
+ None => unreachable!()
+ }
+ }
+ }
+ }
+
+ fn parse_list(&mut self) -> Result<Json, Error> {
+ self.bump();
+ self.parse_whitespace();
+
+ let mut values = ~[];
+
+ if self.ch_is(']') {
+ self.bump();
+ return Ok(List(values));
+ }
+
+ loop {
+ match self.parse_value() {
+ Ok(v) => values.push(v),
+ Err(e) => return Err(e)
+ }
+
+ self.parse_whitespace();
+ if self.eof() {
+ return self.error(~"EOF while parsing list");
+ }
+
+ if self.ch_is(',') {
+ self.bump();
+ } else if self.ch_is(']') {
+ self.bump();
+ return Ok(List(values));
+ } else {
+ return self.error(~"expected `,` or `]`")
+ }
+ };
+ }
+
+ fn parse_object(&mut self) -> Result<Json, Error> {
+ self.bump();
+ self.parse_whitespace();
+
+ let mut values = ~TreeMap::new();
+
+ if self.ch_is('}') {
+ self.bump();
+ return Ok(Object(values));
+ }
+
+ while !self.eof() {
+ self.parse_whitespace();
+
+ if !self.ch_is('"') {
+ return self.error(~"key must be a string");
+ }
+
+ let key = match self.parse_str() {
+ Ok(key) => key,
+ Err(e) => return Err(e)
+ };
+
+ self.parse_whitespace();
+
+ if !self.ch_is(':') {
+ if self.eof() { break; }
+ return self.error(~"expected `:`");
+ }
+ self.bump();
+
+ match self.parse_value() {
+ Ok(value) => { values.insert(key, value); }
+ Err(e) => return Err(e)
+ }
+ self.parse_whitespace();
+
+ match self.ch_or_null() {
+ ',' => self.bump(),
+ '}' => { self.bump(); return Ok(Object(values)); },
+ _ => {
+ if self.eof() { break; }
+ return self.error(~"expected `,` or `}`");
+ }
+ }
+ }
+
+ return self.error(~"EOF while parsing object");
+ }
+}
+
+/// Decodes a json value from an `&mut io::Reader`
+pub fn from_reader(rdr: &mut io::Reader) -> Result<Json, Error> {
+ let contents = match rdr.read_to_end() {
+ Ok(c) => c,
+ Err(e) => return Err(io_error_to_error(e))
+ };
+ let s = match str::from_utf8_owned(contents) {
+ Some(s) => s,
+ None => return Err(Error { line: 0, col: 0, msg: ~"contents not utf-8" })
+ };
+ let mut parser = Parser::new(s.chars());
+ parser.parse()
+}
+
+/// Decodes a json value from a string
+pub fn from_str(s: &str) -> Result<Json, Error> {
+ let mut parser = Parser::new(s.chars());
+ parser.parse()
+}
+
+/// A structure to decode JSON to values in rust.
+pub struct Decoder {
+ priv stack: ~[Json],
+}
+
+impl Decoder {
+ /// Creates a new decoder instance for decoding the specified JSON value.
+ pub fn new(json: Json) -> Decoder {
+ Decoder {
+ stack: ~[json]
+ }
+ }
+}
+
+impl Decoder {
+ fn err(&self, msg: &str) -> ! {
+ fail!("JSON decode error: {}", msg);
+ }
+ fn missing_field(&self, field: &str, object: ~Object) -> ! {
+ self.err(format!("missing required '{}' field in object: {}",
+ field, Object(object).to_str()))
+ }
+ fn expected(&self, expected: &str, found: &Json) -> ! {
+ let found_s = match *found {
+ Null => "null",
+ List(..) => "list",
+ Object(..) => "object",
+ Number(..) => "number",
+ String(..) => "string",
+ Boolean(..) => "boolean"
+ };
+ self.err(format!("expected {expct} but found {fnd}: {val}",
+ expct=expected, fnd=found_s, val=found.to_str()))
+ }
+}
+
+impl ::Decoder for Decoder {
+ fn read_nil(&mut self) -> () {
+ debug!("read_nil");
+ match self.stack.pop().unwrap() {
+ Null => (),
+ value => self.expected("null", &value)
+ }
+ }
+
+ fn read_u64(&mut self) -> u64 { self.read_f64() as u64 }
+ fn read_u32(&mut self) -> u32 { self.read_f64() as u32 }
+ fn read_u16(&mut self) -> u16 { self.read_f64() as u16 }
+ fn read_u8 (&mut self) -> u8 { self.read_f64() as u8 }
+ fn read_uint(&mut self) -> uint { self.read_f64() as uint }
+
+ fn read_i64(&mut self) -> i64 { self.read_f64() as i64 }
+ fn read_i32(&mut self) -> i32 { self.read_f64() as i32 }
+ fn read_i16(&mut self) -> i16 { self.read_f64() as i16 }
+ fn read_i8 (&mut self) -> i8 { self.read_f64() as i8 }
+ fn read_int(&mut self) -> int { self.read_f64() as int }
+
+ fn read_bool(&mut self) -> bool {
+ debug!("read_bool");
+ match self.stack.pop().unwrap() {
+ Boolean(b) => b,
+ value => self.expected("boolean", &value)
+ }
+ }
+
+ fn read_f64(&mut self) -> f64 {
+ use std::from_str::FromStr;
+ debug!("read_f64");
+ match self.stack.pop().unwrap() {
+ Number(f) => f,
+ String(s) => {
+ // re: #12967.. a type w/ numeric keys (ie HashMap<uint, V> etc)
+ // is going to have a string here, as per JSON spec..
+ FromStr::from_str(s).unwrap()
+ },
+ value => self.expected("number", &value)
+ }
+ }
+
+ fn read_f32(&mut self) -> f32 { self.read_f64() as f32 }
+
+ fn read_char(&mut self) -> char {
+ let s = self.read_str();
+ {
+ let mut it = s.chars();
+ match (it.next(), it.next()) {
+ // exactly one character
+ (Some(c), None) => return c,
+ _ => ()
+ }
+ }
+ self.expected("single character string", &String(s))
+ }
+
+ fn read_str(&mut self) -> ~str {
+ debug!("read_str");
+ match self.stack.pop().unwrap() {
+ String(s) => s,
+ value => self.expected("string", &value)
+ }
+ }
+
+ fn read_enum<T>(&mut self, name: &str, f: |&mut Decoder| -> T) -> T {
+ debug!("read_enum({})", name);
+ f(self)
+ }
+
+ fn read_enum_variant<T>(&mut self,
+ names: &[&str],
+ f: |&mut Decoder, uint| -> T)
+ -> T {
+ debug!("read_enum_variant(names={:?})", names);
+ let name = match self.stack.pop().unwrap() {
+ String(s) => s,
+ Object(mut o) => {
+ let n = match o.pop(&~"variant") {
+ Some(String(s)) => s,
+ Some(val) => self.expected("string", &val),
+ None => self.missing_field("variant", o)
+ };
+ match o.pop(&~"fields") {
+ Some(List(l)) => {
+ for field in l.move_rev_iter() {
+ self.stack.push(field.clone());
+ }
+ },
+ Some(val) => self.expected("list", &val),
+ None => {
+ // re-insert the variant field so we're
+ // printing the "whole" struct in the error
+ // message... ick.
+ o.insert(~"variant", String(n));
+ self.missing_field("fields", o);
+ }
+ }
+ n
+ }
+ json => self.expected("string or object", &json)
+ };
+ let idx = match names.iter().position(|n| str::eq_slice(*n, name)) {
+ Some(idx) => idx,
+ None => self.err(format!("unknown variant name: {}", name))
+ };
+ f(self, idx)
+ }
+
+ fn read_enum_variant_arg<T>(&mut self, idx: uint, f: |&mut Decoder| -> T)
+ -> T {
+ debug!("read_enum_variant_arg(idx={})", idx);
+ f(self)
+ }
+
+ fn read_enum_struct_variant<T>(&mut self,
+ names: &[&str],
+ f: |&mut Decoder, uint| -> T)
+ -> T {
+ debug!("read_enum_struct_variant(names={:?})", names);
+ self.read_enum_variant(names, f)
+ }
+
+
+ fn read_enum_struct_variant_field<T>(&mut self,
+ name: &str,
+ idx: uint,
+ f: |&mut Decoder| -> T)
+ -> T {
+ debug!("read_enum_struct_variant_field(name={}, idx={})", name, idx);
+ self.read_enum_variant_arg(idx, f)
+ }
+
+ fn read_struct<T>(&mut self,
+ name: &str,
+ len: uint,
+ f: |&mut Decoder| -> T)
+ -> T {
+ debug!("read_struct(name={}, len={})", name, len);
+ let value = f(self);
+ self.stack.pop().unwrap();
+ value
+ }
+
+ fn read_struct_field<T>(&mut self,
+ name: &str,
+ idx: uint,
+ f: |&mut Decoder| -> T)
+ -> T {
+ debug!("read_struct_field(name={}, idx={})", name, idx);
+ match self.stack.pop().unwrap() {
+ Object(mut obj) => {
+ let value = match obj.pop(&name.to_owned()) {
+ None => self.missing_field(name, obj),
+ Some(json) => {
+ self.stack.push(json);
+ f(self)
+ }
+ };
+ self.stack.push(Object(obj));
+ value
+ }
+ value => self.expected("object", &value)
+ }
+ }
+
+ fn read_tuple<T>(&mut self, f: |&mut Decoder, uint| -> T) -> T {
+ debug!("read_tuple()");
+ self.read_seq(f)
+ }
+
+ fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder| -> T) -> T {
+ debug!("read_tuple_arg(idx={})", idx);
+ self.read_seq_elt(idx, f)
+ }
+
+ fn read_tuple_struct<T>(&mut self,
+ name: &str,
+ f: |&mut Decoder, uint| -> T)
+ -> T {
+ debug!("read_tuple_struct(name={})", name);
+ self.read_tuple(f)
+ }
+
+ fn read_tuple_struct_arg<T>(&mut self,
+ idx: uint,
+ f: |&mut Decoder| -> T)
+ -> T {
+ debug!("read_tuple_struct_arg(idx={})", idx);
+ self.read_tuple_arg(idx, f)
+ }
+
+ fn read_option<T>(&mut self, f: |&mut Decoder, bool| -> T) -> T {
+ match self.stack.pop().unwrap() {
+ Null => f(self, false),
+ value => { self.stack.push(value); f(self, true) }
+ }
+ }
+
+ fn read_seq<T>(&mut self, f: |&mut Decoder, uint| -> T) -> T {
+ debug!("read_seq()");
+ let len = match self.stack.pop().unwrap() {
+ List(list) => {
+ let len = list.len();
+ for v in list.move_rev_iter() {
+ self.stack.push(v);
+ }
+ len
+ }
+ value => self.expected("list", &value)
+ };
+ f(self, len)
+ }
+
+ fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder| -> T) -> T {
+ debug!("read_seq_elt(idx={})", idx);
+ f(self)
+ }
+
+ fn read_map<T>(&mut self, f: |&mut Decoder, uint| -> T) -> T {
+ debug!("read_map()");
+ let len = match self.stack.pop().unwrap() {
+ Object(obj) => {
+ let len = obj.len();
+ for (key, value) in obj.move_iter() {
+ self.stack.push(value);
+ self.stack.push(String(key));
+ }
+ len
+ }
+ value => self.expected("object", &value)
+ };
+ f(self, len)
+ }
+
+ fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder| -> T)
+ -> T {
+ debug!("read_map_elt_key(idx={})", idx);
+ f(self)
+ }
+
+ fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder| -> T)
+ -> T {
+ debug!("read_map_elt_val(idx={})", idx);
+ f(self)
+ }
+}
+
+/// Test if two json values are less than one another
+impl Ord for Json {
+ fn lt(&self, other: &Json) -> bool {
+ match *self {
+ Number(f0) => {
+ match *other {
+ Number(f1) => f0 < f1,
+ String(_) | Boolean(_) | List(_) | Object(_) |
+ Null => true
+ }
+ }
+
+ String(ref s0) => {
+ match *other {
+ Number(_) => false,
+ String(ref s1) => s0 < s1,
+ Boolean(_) | List(_) | Object(_) | Null => true
+ }
+ }
+
+ Boolean(b0) => {
+ match *other {
+ Number(_) | String(_) => false,
+ Boolean(b1) => b0 < b1,
+ List(_) | Object(_) | Null => true
+ }
+ }
+
+ List(ref l0) => {
+ match *other {
+ Number(_) | String(_) | Boolean(_) => false,
+ List(ref l1) => (*l0) < (*l1),
+ Object(_) | Null => true
+ }
+ }
+
+ Object(ref d0) => {
+ match *other {
+ Number(_) | String(_) | Boolean(_) | List(_) => false,
+ Object(ref d1) => d0 < d1,
+ Null => true
+ }
+ }
+
+ Null => {
+ match *other {
+ Number(_) | String(_) | Boolean(_) | List(_) |
+ Object(_) =>
+ false,
+ Null => true
+ }
+ }
+ }
+ }
+}
+
+/// A trait for converting values to JSON
+pub trait ToJson {
+ /// Converts the value of `self` to an instance of JSON
+ fn to_json(&self) -> Json;
+}
+
+impl ToJson for Json {
+ fn to_json(&self) -> Json { (*self).clone() }
+}
+
+impl ToJson for int {
+ fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for i8 {
+ fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for i16 {
+ fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for i32 {
+ fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for i64 {
+ fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for uint {
+ fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for u8 {
+ fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for u16 {
+ fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for u32 {
+ fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for u64 {
+ fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for f32 {
+ fn to_json(&self) -> Json { Number(*self as f64) }
+}
+
+impl ToJson for f64 {
+ fn to_json(&self) -> Json { Number(*self) }
+}
+
+impl ToJson for () {
+ fn to_json(&self) -> Json { Null }
+}
+
+impl ToJson for bool {
+ fn to_json(&self) -> Json { Boolean(*self) }
+}
+
+impl ToJson for ~str {
+ fn to_json(&self) -> Json { String((*self).clone()) }
+}
+
+impl<A:ToJson,B:ToJson> ToJson for (A, B) {
+ fn to_json(&self) -> Json {
+ match *self {
+ (ref a, ref b) => {
+ List(~[a.to_json(), b.to_json()])
+ }
+ }
+ }
+}
+
+impl<A:ToJson,B:ToJson,C:ToJson> ToJson for (A, B, C) {
+ fn to_json(&self) -> Json {
+ match *self {
+ (ref a, ref b, ref c) => {
+ List(~[a.to_json(), b.to_json(), c.to_json()])
+ }
+ }
+ }
+}
+
+impl<A:ToJson> ToJson for ~[A] {
+ fn to_json(&self) -> Json { List(self.map(|elt| elt.to_json())) }
+}
+
+impl<A:ToJson> ToJson for TreeMap<~str, A> {
+ fn to_json(&self) -> Json {
+ let mut d = TreeMap::new();
+ for (key, value) in self.iter() {
+ d.insert((*key).clone(), value.to_json());
+ }
+ Object(~d)
+ }
+}
+
+impl<A:ToJson> ToJson for HashMap<~str, A> {
+ fn to_json(&self) -> Json {
+ let mut d = TreeMap::new();
+ for (key, value) in self.iter() {
+ d.insert((*key).clone(), value.to_json());
+ }
+ Object(~d)
+ }
+}
+
+impl<A:ToJson> ToJson for Option<A> {
+ fn to_json(&self) -> Json {
+ match *self {
+ None => Null,
+ Some(ref value) => value.to_json()
+ }
+ }
+}
+
+impl fmt::Show for Json {
+ /// Encodes a json value into a string
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ self.to_writer(f.buf)
+ }
+}
+
+impl fmt::Show for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f.buf, "{}:{}: {}", self.line, self.col, self.msg)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use {Encodable, Decodable};
+ use super::{Encoder, Decoder, Error, Boolean, Number, List, String, Null,
+ PrettyEncoder, Object, Json, from_str};
+ use std::io;
+ use collections::TreeMap;
+
+ #[deriving(Eq, Encodable, Decodable, Show)]
+ enum Animal {
+ Dog,
+ Frog(~str, int)
+ }
+
+ #[deriving(Eq, Encodable, Decodable, Show)]
+ struct Inner {
+ a: (),
+ b: uint,
+ c: ~[~str],
+ }
+
+ #[deriving(Eq, Encodable, Decodable, Show)]
+ struct Outer {
+ inner: ~[Inner],
+ }
+
+ fn mk_object(items: &[(~str, Json)]) -> Json {
+ let mut d = ~TreeMap::new();
+
+ for item in items.iter() {
+ match *item {
+ (ref key, ref value) => { d.insert((*key).clone(), (*value).clone()); },
+ }
+ };
+
+ Object(d)
+ }
+
+ #[test]
+ fn test_write_null() {
+ assert_eq!(Null.to_str(), ~"null");
+ assert_eq!(Null.to_pretty_str(), ~"null");
+ }
+
+
+ #[test]
+ fn test_write_number() {
+ assert_eq!(Number(3.0).to_str(), ~"3");
+ assert_eq!(Number(3.0).to_pretty_str(), ~"3");
+
+ assert_eq!(Number(3.1).to_str(), ~"3.1");
+ assert_eq!(Number(3.1).to_pretty_str(), ~"3.1");
+
+ assert_eq!(Number(-1.5).to_str(), ~"-1.5");
+ assert_eq!(Number(-1.5).to_pretty_str(), ~"-1.5");
+
+ assert_eq!(Number(0.5).to_str(), ~"0.5");
+ assert_eq!(Number(0.5).to_pretty_str(), ~"0.5");
+ }
+
+ #[test]
+ fn test_write_str() {
+ assert_eq!(String(~"").to_str(), ~"\"\"");
+ assert_eq!(String(~"").to_pretty_str(), ~"\"\"");
+
+ assert_eq!(String(~"foo").to_str(), ~"\"foo\"");
+ assert_eq!(String(~"foo").to_pretty_str(), ~"\"foo\"");
+ }
+
+ #[test]
+ fn test_write_bool() {
+ assert_eq!(Boolean(true).to_str(), ~"true");
+ assert_eq!(Boolean(true).to_pretty_str(), ~"true");
+
+ assert_eq!(Boolean(false).to_str(), ~"false");
+ assert_eq!(Boolean(false).to_pretty_str(), ~"false");
+ }
+
+ #[test]
+ fn test_write_list() {
+ assert_eq!(List(~[]).to_str(), ~"[]");
+ assert_eq!(List(~[]).to_pretty_str(), ~"[]");
+
+ assert_eq!(List(~[Boolean(true)]).to_str(), ~"[true]");
+ assert_eq!(
+ List(~[Boolean(true)]).to_pretty_str(),
+ ~"\
+ [\n \
+ true\n\
+ ]"
+ );
+
+ let long_test_list = List(~[
+ Boolean(false),
+ Null,
+ List(~[String(~"foo\nbar"), Number(3.5)])]);
+
+ assert_eq!(long_test_list.to_str(),
+ ~"[false,null,[\"foo\\nbar\",3.5]]");
+ assert_eq!(
+ long_test_list.to_pretty_str(),
+ ~"\
+ [\n \
+ false,\n \
+ null,\n \
+ [\n \
+ \"foo\\nbar\",\n \
+ 3.5\n \
+ ]\n\
+ ]"
+ );
+ }
+
+ #[test]
+ fn test_write_object() {
+ assert_eq!(mk_object([]).to_str(), ~"{}");
+ assert_eq!(mk_object([]).to_pretty_str(), ~"{}");
+
+ assert_eq!(
+ mk_object([(~"a", Boolean(true))]).to_str(),
+ ~"{\"a\":true}"
+ );
+ assert_eq!(
+ mk_object([(~"a", Boolean(true))]).to_pretty_str(),
+ ~"\
+ {\n \
+ \"a\": true\n\
+ }"
+ );
+
+ let complex_obj = mk_object([
+ (~"b", List(~[
+ mk_object([(~"c", String(~"\x0c\r"))]),
+ mk_object([(~"d", String(~""))])
+ ]))
+ ]);
+
+ assert_eq!(
+ complex_obj.to_str(),
+ ~"{\
+ \"b\":[\
+ {\"c\":\"\\f\\r\"},\
+ {\"d\":\"\"}\
+ ]\
+ }"
+ );
+ assert_eq!(
+ complex_obj.to_pretty_str(),
+ ~"\
+ {\n \
+ \"b\": [\n \
+ {\n \
+ \"c\": \"\\f\\r\"\n \
+ },\n \
+ {\n \
+ \"d\": \"\"\n \
+ }\n \
+ ]\n\
+ }"
+ );
+
+ let a = mk_object([
+ (~"a", Boolean(true)),
+ (~"b", List(~[
+ mk_object([(~"c", String(~"\x0c\r"))]),
+ mk_object([(~"d", String(~""))])
+ ]))
+ ]);
+
+ // We can't compare the strings directly because the object fields be
+ // printed in a different order.
+ assert_eq!(a.clone(), from_str(a.to_str()).unwrap());
+ assert_eq!(a.clone(), from_str(a.to_pretty_str()).unwrap());
+ }
+
+ fn with_str_writer(f: |&mut io::Writer|) -> ~str {
+ use std::io::MemWriter;
+ use std::str;
+
+ let mut m = MemWriter::new();
+ f(&mut m as &mut io::Writer);
+ str::from_utf8_owned(m.unwrap()).unwrap()
+ }
+
+ #[test]
+ fn test_write_enum() {
+ let animal = Dog;
+ assert_eq!(
+ with_str_writer(|wr| {
+ let mut encoder = Encoder::new(wr);
+ animal.encode(&mut encoder);
+ }),
+ ~"\"Dog\""
+ );
+ assert_eq!(
+ with_str_writer(|wr| {
+ let mut encoder = PrettyEncoder::new(wr);
+ animal.encode(&mut encoder);
+ }),
+ ~"\"Dog\""
+ );
+
+ let animal = Frog(~"Henry", 349);
+ assert_eq!(
+ with_str_writer(|wr| {
+ let mut encoder = Encoder::new(wr);
+ animal.encode(&mut encoder);
+ }),
+ ~"{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}"
+ );
+ assert_eq!(
+ with_str_writer(|wr| {
+ let mut encoder = PrettyEncoder::new(wr);
+ animal.encode(&mut encoder);
+ }),
+ ~"\
+ [\n \
+ \"Frog\",\n \
+ \"Henry\",\n \
+ 349\n\
+ ]"
+ );
+ }
+
+ #[test]
+ fn test_write_some() {
+ let value = Some(~"jodhpurs");
+ let s = with_str_writer(|wr| {
+ let mut encoder = Encoder::new(wr);
+ value.encode(&mut encoder);
+ });
+ assert_eq!(s, ~"\"jodhpurs\"");
+
+ let value = Some(~"jodhpurs");
+ let s = with_str_writer(|wr| {
+ let mut encoder = PrettyEncoder::new(wr);
+ value.encode(&mut encoder);
+ });
+ assert_eq!(s, ~"\"jodhpurs\"");
+ }
+
+ #[test]
+ fn test_write_none() {
+ let value: Option<~str> = None;
+ let s = with_str_writer(|wr| {
+ let mut encoder = Encoder::new(wr);
+ value.encode(&mut encoder);
+ });
+ assert_eq!(s, ~"null");
+
+ let s = with_str_writer(|wr| {
+ let mut encoder = Encoder::new(wr);
+ value.encode(&mut encoder);
+ });
+ assert_eq!(s, ~"null");
+ }
+
+ #[test]
+ fn test_trailing_characters() {
+ assert_eq!(from_str("nulla"),
+ Err(Error {line: 1u, col: 5u, msg: ~"trailing characters"}));
+ assert_eq!(from_str("truea"),
+ Err(Error {line: 1u, col: 5u, msg: ~"trailing characters"}));
+ assert_eq!(from_str("falsea"),
+ Err(Error {line: 1u, col: 6u, msg: ~"trailing characters"}));
+ assert_eq!(from_str("1a"),
+ Err(Error {line: 1u, col: 2u, msg: ~"trailing characters"}));
+ assert_eq!(from_str("[]a"),
+ Err(Error {line: 1u, col: 3u, msg: ~"trailing characters"}));
+ assert_eq!(from_str("{}a"),
+ Err(Error {line: 1u, col: 3u, msg: ~"trailing characters"}));
+ }
+
+ #[test]
+ fn test_read_identifiers() {
+ assert_eq!(from_str("n"),
+ Err(Error {line: 1u, col: 2u, msg: ~"invalid syntax"}));
+ assert_eq!(from_str("nul"),
+ Err(Error {line: 1u, col: 4u, msg: ~"invalid syntax"}));
+
+ assert_eq!(from_str("t"),
+ Err(Error {line: 1u, col: 2u, msg: ~"invalid syntax"}));
+ assert_eq!(from_str("truz"),
+ Err(Error {line: 1u, col: 4u, msg: ~"invalid syntax"}));
+
+ assert_eq!(from_str("f"),
+ Err(Error {line: 1u, col: 2u, msg: ~"invalid syntax"}));
+ assert_eq!(from_str("faz"),
+ Err(Error {line: 1u, col: 3u, msg: ~"invalid syntax"}));
+
+ assert_eq!(from_str("null"), Ok(Null));
+ assert_eq!(from_str("true"), Ok(Boolean(true)));
+ assert_eq!(from_str("false"), Ok(Boolean(false)));
+ assert_eq!(from_str(" null "), Ok(Null));
+ assert_eq!(from_str(" true "), Ok(Boolean(true)));
+ assert_eq!(from_str(" false "), Ok(Boolean(false)));
+ }
+
+ #[test]
+ fn test_decode_identifiers() {
+ let mut decoder = Decoder::new(from_str("null").unwrap());
+ let v: () = Decodable::decode(&mut decoder);
+ assert_eq!(v, ());
+
+ let mut decoder = Decoder::new(from_str("true").unwrap());
+ let v: bool = Decodable::decode(&mut decoder);
+ assert_eq!(v, true);
+
+ let mut decoder = Decoder::new(from_str("false").unwrap());
+ let v: bool = Decodable::decode(&mut decoder);
+ assert_eq!(v, false);
+ }
+
+ #[test]
+ fn test_read_number() {
+ assert_eq!(from_str("+"),
+ Err(Error {line: 1u, col: 1u, msg: ~"invalid syntax"}));
+ assert_eq!(from_str("."),
+ Err(Error {line: 1u, col: 1u, msg: ~"invalid syntax"}));
+
+ assert_eq!(from_str("-"),
+ Err(Error {line: 1u, col: 2u, msg: ~"invalid number"}));
+ assert_eq!(from_str("00"),
+ Err(Error {line: 1u, col: 2u, msg: ~"invalid number"}));
+ assert_eq!(from_str("1."),
+ Err(Error {line: 1u, col: 3u, msg: ~"invalid number"}));
+ assert_eq!(from_str("1e"),
+ Err(Error {line: 1u, col: 3u, msg: ~"invalid number"}));
+ assert_eq!(from_str("1e+"),
+ Err(Error {line: 1u, col: 4u, msg: ~"invalid number"}));
+
+ assert_eq!(from_str("3"), Ok(Number(3.0)));
+ assert_eq!(from_str("3.1"), Ok(Number(3.1)));
+ assert_eq!(from_str("-1.2"), Ok(Number(-1.2)));
+ assert_eq!(from_str("0.4"), Ok(Number(0.4)));
+ assert_eq!(from_str("0.4e5"), Ok(Number(0.4e5)));
+ assert_eq!(from_str("0.4e+15"), Ok(Number(0.4e15)));
+ assert_eq!(from_str("0.4e-01"), Ok(Number(0.4e-01)));
+ assert_eq!(from_str(" 3 "), Ok(Number(3.0)));
+ }
+
+ #[test]
+ fn test_decode_numbers() {
+ let mut decoder = Decoder::new(from_str("3").unwrap());
+ let v: f64 = Decodable::decode(&mut decoder);
+ assert_eq!(v, 3.0);
+
+ let mut decoder = Decoder::new(from_str("3.1").unwrap());
+ let v: f64 = Decodable::decode(&mut decoder);
+ assert_eq!(v, 3.1);
+
+ let mut decoder = Decoder::new(from_str("-1.2").unwrap());
+ let v: f64 = Decodable::decode(&mut decoder);
+ assert_eq!(v, -1.2);
+
+ let mut decoder = Decoder::new(from_str("0.4").unwrap());
+ let v: f64 = Decodable::decode(&mut decoder);
+ assert_eq!(v, 0.4);
+
+ let mut decoder = Decoder::new(from_str("0.4e5").unwrap());
+ let v: f64 = Decodable::decode(&mut decoder);
+ assert_eq!(v, 0.4e5);
+
+ let mut decoder = Decoder::new(from_str("0.4e15").unwrap());
+ let v: f64 = Decodable::decode(&mut decoder);
+ assert_eq!(v, 0.4e15);
+
+ let mut decoder = Decoder::new(from_str("0.4e-01").unwrap());
+ let v: f64 = Decodable::decode(&mut decoder);
+ assert_eq!(v, 0.4e-01);
+ }
+
+ #[test]
+ fn test_read_str() {
+ assert_eq!(from_str("\""),
+ Err(Error {line: 1u, col: 2u, msg: ~"EOF while parsing string"
+ }));
+ assert_eq!(from_str("\"lol"),
+ Err(Error {line: 1u, col: 5u, msg: ~"EOF while parsing string"
+ }));
+
+ assert_eq!(from_str("\"\""), Ok(String(~"")));
+ assert_eq!(from_str("\"foo\""), Ok(String(~"foo")));
+ assert_eq!(from_str("\"\\\"\""), Ok(String(~"\"")));
+ assert_eq!(from_str("\"\\b\""), Ok(String(~"\x08")));
+ assert_eq!(from_str("\"\\n\""), Ok(String(~"\n")));
+ assert_eq!(from_str("\"\\r\""), Ok(String(~"\r")));
+ assert_eq!(from_str("\"\\t\""), Ok(String(~"\t")));
+ assert_eq!(from_str(" \"foo\" "), Ok(String(~"foo")));
+ assert_eq!(from_str("\"\\u12ab\""), Ok(String(~"\u12ab")));
+ assert_eq!(from_str("\"\\uAB12\""), Ok(String(~"\uAB12")));
+ }
+
+ #[test]
+ fn test_decode_str() {
+ let mut decoder = Decoder::new(from_str("\"\"").unwrap());
+ let v: ~str = Decodable::decode(&mut decoder);
+ assert_eq!(v, ~"");
+
+ let mut decoder = Decoder::new(from_str("\"foo\"").unwrap());
+ let v: ~str = Decodable::decode(&mut decoder);
+ assert_eq!(v, ~"foo");
+
+ let mut decoder = Decoder::new(from_str("\"\\\"\"").unwrap());
+ let v: ~str = Decodable::decode(&mut decoder);
+ assert_eq!(v, ~"\"");
+
+ let mut decoder = Decoder::new(from_str("\"\\b\"").unwrap());
+ let v: ~str = Decodable::decode(&mut decoder);
+ assert_eq!(v, ~"\x08");
+
+ let mut decoder = Decoder::new(from_str("\"\\n\"").unwrap());
+ let v: ~str = Decodable::decode(&mut decoder);
+ assert_eq!(v, ~"\n");
+
+ let mut decoder = Decoder::new(from_str("\"\\r\"").unwrap());
+ let v: ~str = Decodable::decode(&mut decoder);
+ assert_eq!(v, ~"\r");
+
+ let mut decoder = Decoder::new(from_str("\"\\t\"").unwrap());
+ let v: ~str = Decodable::decode(&mut decoder);
+ assert_eq!(v, ~"\t");
+
+ let mut decoder = Decoder::new(from_str("\"\\u12ab\"").unwrap());
+ let v: ~str = Decodable::decode(&mut decoder);
+ assert_eq!(v, ~"\u12ab");
+
+ let mut decoder = Decoder::new(from_str("\"\\uAB12\"").unwrap());
+ let v: ~str = Decodable::decode(&mut decoder);
+ assert_eq!(v, ~"\uAB12");
+ }
+
+ #[test]
+ fn test_read_list() {
+ assert_eq!(from_str("["),
+ Err(Error {line: 1u, col: 2u, msg: ~"EOF while parsing value"}));
+ assert_eq!(from_str("[1"),
+ Err(Error {line: 1u, col: 3u, msg: ~"EOF while parsing list"}));
+ assert_eq!(from_str("[1,"),
+ Err(Error {line: 1u, col: 4u, msg: ~"EOF while parsing value"}));
+ assert_eq!(from_str("[1,]"),
+ Err(Error {line: 1u, col: 4u, msg: ~"invalid syntax"}));
+ assert_eq!(from_str("[6 7]"),
+ Err(Error {line: 1u, col: 4u, msg: ~"expected `,` or `]`"}));
+
+ assert_eq!(from_str("[]"), Ok(List(~[])));
+ assert_eq!(from_str("[ ]"), Ok(List(~[])));
+ assert_eq!(from_str("[true]"), Ok(List(~[Boolean(true)])));
+ assert_eq!(from_str("[ false ]"), Ok(List(~[Boolean(false)])));
+ assert_eq!(from_str("[null]"), Ok(List(~[Null])));
+ assert_eq!(from_str("[3, 1]"),
+ Ok(List(~[Number(3.0), Number(1.0)])));
+ assert_eq!(from_str("\n[3, 2]\n"),
+ Ok(List(~[Number(3.0), Number(2.0)])));
+ assert_eq!(from_str("[2, [4, 1]]"),
+ Ok(List(~[Number(2.0), List(~[Number(4.0), Number(1.0)])])));
+ }
+
+ #[test]
+ fn test_decode_list() {
+ let mut decoder = Decoder::new(from_str("[]").unwrap());
+ let v: ~[()] = Decodable::decode(&mut decoder);
+ assert_eq!(v, ~[]);
+
+ let mut decoder = Decoder::new(from_str("[null]").unwrap());
+ let v: ~[()] = Decodable::decode(&mut decoder);
+ assert_eq!(v, ~[()]);
+
+ let mut decoder = Decoder::new(from_str("[true]").unwrap());
+ let v: ~[bool] = Decodable::decode(&mut decoder);
+ assert_eq!(v, ~[true]);
+
+ let mut decoder = Decoder::new(from_str("[true]").unwrap());
+ let v: ~[bool] = Decodable::decode(&mut decoder);
+ assert_eq!(v, ~[true]);
+
+ let mut decoder = Decoder::new(from_str("[3, 1]").unwrap());
+ let v: ~[int] = Decodable::decode(&mut decoder);
+ assert_eq!(v, ~[3, 1]);
+
+ let mut decoder = Decoder::new(from_str("[[3], [1, 2]]").unwrap());
+ let v: ~[~[uint]] = Decodable::decode(&mut decoder);
+ assert_eq!(v, ~[~[3], ~[1, 2]]);
+ }
+
+ #[test]
+ fn test_read_object() {
+ assert_eq!(from_str("{"),
+ Err(Error {
+ line: 1u,
+ col: 2u,
+ msg: ~"EOF while parsing object"}));
+ assert_eq!(from_str("{ "),
+ Err(Error {
+ line: 1u,
+ col: 3u,
+ msg: ~"EOF while parsing object"}));
+ assert_eq!(from_str("{1"),
+ Err(Error {
+ line: 1u,
+ col: 2u,
+ msg: ~"key must be a string"}));
+ assert_eq!(from_str("{ \"a\""),
+ Err(Error {
+ line: 1u,
+ col: 6u,
+ msg: ~"EOF while parsing object"}));
+ assert_eq!(from_str("{\"a\""),
+ Err(Error {
+ line: 1u,
+ col: 5u,
+ msg: ~"EOF while parsing object"}));
+ assert_eq!(from_str("{\"a\" "),
+ Err(Error {
+ line: 1u,
+ col: 6u,
+ msg: ~"EOF while parsing object"}));
+
+ assert_eq!(from_str("{\"a\" 1"),
+ Err(Error {line: 1u, col: 6u, msg: ~"expected `:`"}));
+ assert_eq!(from_str("{\"a\":"),
+ Err(Error {line: 1u, col: 6u, msg: ~"EOF while parsing value"}));
+ assert_eq!(from_str("{\"a\":1"),
+ Err(Error {
+ line: 1u,
+ col: 7u,
+ msg: ~"EOF while parsing object"}));
+ assert_eq!(from_str("{\"a\":1 1"),
+ Err(Error {line: 1u, col: 8u, msg: ~"expected `,` or `}`"}));
+ assert_eq!(from_str("{\"a\":1,"),
+ Err(Error {
+ line: 1u,
+ col: 8u,
+ msg: ~"EOF while parsing object"}));
+
+ assert_eq!(from_str("{}").unwrap(), mk_object([]));
+ assert_eq!(from_str("{\"a\": 3}").unwrap(),
+ mk_object([(~"a", Number(3.0))]));
+
+ assert_eq!(from_str(
+ "{ \"a\": null, \"b\" : true }").unwrap(),
+ mk_object([
+ (~"a", Null),
+ (~"b", Boolean(true))]));
+ assert_eq!(from_str("\n{ \"a\": null, \"b\" : true }\n").unwrap(),
+ mk_object([
+ (~"a", Null),
+ (~"b", Boolean(true))]));
+ assert_eq!(from_str(
+ "{\"a\" : 1.0 ,\"b\": [ true ]}").unwrap(),
+ mk_object([
+ (~"a", Number(1.0)),
+ (~"b", List(~[Boolean(true)]))
+ ]));
+ assert_eq!(from_str(
+ ~"{" +
+ "\"a\": 1.0, " +
+ "\"b\": [" +
+ "true," +
+ "\"foo\\nbar\", " +
+ "{ \"c\": {\"d\": null} } " +
+ "]" +
+ "}").unwrap(),
+ mk_object([
+ (~"a", Number(1.0)),
+ (~"b", List(~[
+ Boolean(true),
+ String(~"foo\nbar"),
+ mk_object([
+ (~"c", mk_object([(~"d", Null)]))
+ ])
+ ]))
+ ]));
+ }
+
+ #[test]
+ fn test_decode_struct() {
+ let s = ~"{
+ \"inner\": [
+ { \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] }
+ ]
+ }";
+ let mut decoder = Decoder::new(from_str(s).unwrap());
+ let v: Outer = Decodable::decode(&mut decoder);
+ assert_eq!(
+ v,
+ Outer {
+ inner: ~[
+ Inner { a: (), b: 2, c: ~[~"abc", ~"xyz"] }
+ ]
+ }
+ );
+ }
+
+ #[test]
+ fn test_decode_option() {
+ let mut decoder = Decoder::new(from_str("null").unwrap());
+ let value: Option<~str> = Decodable::decode(&mut decoder);
+ assert_eq!(value, None);
+
+ let mut decoder = Decoder::new(from_str("\"jodhpurs\"").unwrap());
+ let value: Option<~str> = Decodable::decode(&mut decoder);
+ assert_eq!(value, Some(~"jodhpurs"));
+ }
+
+ #[test]
+ fn test_decode_enum() {
+ let mut decoder = Decoder::new(from_str("\"Dog\"").unwrap());
+ let value: Animal = Decodable::decode(&mut decoder);
+ assert_eq!(value, Dog);
+
+ let s = "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}";
+ let mut decoder = Decoder::new(from_str(s).unwrap());
+ let value: Animal = Decodable::decode(&mut decoder);
+ assert_eq!(value, Frog(~"Henry", 349));
+ }
+
+ #[test]
+ fn test_decode_map() {
+ let s = ~"{\"a\": \"Dog\", \"b\": {\"variant\":\"Frog\",\"fields\":[\"Henry\", 349]}}";
+ let mut decoder = Decoder::new(from_str(s).unwrap());
+ let mut map: TreeMap<~str, Animal> = Decodable::decode(&mut decoder);
+
+ assert_eq!(map.pop(&~"a"), Some(Dog));
+ assert_eq!(map.pop(&~"b"), Some(Frog(~"Henry", 349)));
+ }
+
+ #[test]
+ fn test_multiline_errors() {
+ assert_eq!(from_str("{\n \"foo\":\n \"bar\""),
+ Err(Error {
+ line: 3u,
+ col: 8u,
+ msg: ~"EOF while parsing object"}));
+ }
+
+ #[deriving(Decodable)]
+ struct DecodeStruct {
+ x: f64,
+ y: bool,
+ z: ~str,
+ w: ~[DecodeStruct]
+ }
+ #[deriving(Decodable)]
+ enum DecodeEnum {
+ A(f64),
+ B(~str)
+ }
+ fn check_err<T: Decodable<Decoder>>(to_parse: &'static str, expected_error: &str) {
+ use std::any::AnyRefExt;
+ use std::task;
+ let res = task::try(proc() {
+ // either fails in `decode` (which is what we want), or
+ // returns Some(error_message)/None if the string was
+ // invalid or valid JSON.
+ match from_str(to_parse) {
+ Err(e) => Some(e.to_str()),
+ Ok(json) => {
+ let _: T = Decodable::decode(&mut Decoder::new(json));
+ None
+ }
+ }
+ });
+ match res {
+ Ok(Some(parse_error)) => fail!("`{}` is not valid json: {}",
+ to_parse, parse_error),
+ Ok(None) => fail!("`{}` parsed & decoded ok, expecting error `{}`",
+ to_parse, expected_error),
+ Err(e) => {
+ let err = e.as_ref::<~str>().unwrap();
+ assert!(err.contains(expected_error),
+ "`{}` errored incorrectly, found `{}` expecting `{}`",
+ to_parse, *err, expected_error);
+ }
+ }
+ }
+ #[test]
+ fn test_decode_errors_struct() {
+ check_err::<DecodeStruct>("[]", "object but found list");
+ check_err::<DecodeStruct>("{\"x\": true, \"y\": true, \"z\": \"\", \"w\": []}",
+ "number but found boolean");
+ check_err::<DecodeStruct>("{\"x\": 1, \"y\": [], \"z\": \"\", \"w\": []}",
+ "boolean but found list");
+ check_err::<DecodeStruct>("{\"x\": 1, \"y\": true, \"z\": {}, \"w\": []}",
+ "string but found object");
+ check_err::<DecodeStruct>("{\"x\": 1, \"y\": true, \"z\": \"\", \"w\": null}",
+ "list but found null");
+ check_err::<DecodeStruct>("{\"x\": 1, \"y\": true, \"z\": \"\"}",
+ "'w' field in object");
+ }
+ #[test]
+ fn test_decode_errors_enum() {
+ check_err::<DecodeEnum>("{}",
+ "'variant' field in object");
+ check_err::<DecodeEnum>("{\"variant\": 1}",
+ "string but found number");
+ check_err::<DecodeEnum>("{\"variant\": \"A\"}",
+ "'fields' field in object");
+ check_err::<DecodeEnum>("{\"variant\": \"A\", \"fields\": null}",
+ "list but found null");
+ check_err::<DecodeEnum>("{\"variant\": \"C\", \"fields\": []}",
+ "unknown variant name");
+ }
+
+ #[test]
+ fn test_find(){
+ let json_value = from_str("{\"dog\" : \"cat\"}").unwrap();
+ let found_str = json_value.find(&~"dog");
+ assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == &"cat");
+ }
+
+ #[test]
+ fn test_find_path(){
+ let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap();
+ let found_str = json_value.find_path(&[&~"dog", &~"cat", &~"mouse"]);
+ assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == &"cheese");
+ }
+
+ #[test]
+ fn test_search(){
+ let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap();
+ let found_str = json_value.search(&~"mouse").and_then(|j| j.as_string());
+ assert!(found_str.is_some());
+ assert!(found_str.unwrap() == &"cheese");
+ }
+
+ #[test]
+ fn test_is_object(){
+ let json_value = from_str("{}").unwrap();
+ assert!(json_value.is_object());
+ }
+
+ #[test]
+ fn test_as_object(){
+ let json_value = from_str("{}").unwrap();
+ let json_object = json_value.as_object();
+ assert!(json_object.is_some());
+ }
+
+ #[test]
+ fn test_is_list(){
+ let json_value = from_str("[1, 2, 3]").unwrap();
+ assert!(json_value.is_list());
+ }
+
+ #[test]
+ fn test_as_list(){
+ let json_value = from_str("[1, 2, 3]").unwrap();
+ let json_list = json_value.as_list();
+ let expected_length = 3;
+ assert!(json_list.is_some() && json_list.unwrap().len() == expected_length);
+ }
+
+ #[test]
+ fn test_is_string(){
+ let json_value = from_str("\"dog\"").unwrap();
+ assert!(json_value.is_string());
+ }
+
+ #[test]
+ fn test_as_string(){
+ let json_value = from_str("\"dog\"").unwrap();
+ let json_str = json_value.as_string();
+ let expected_str = &"dog";
+ assert_eq!(json_str, Some(expected_str));
+ }
+
+ #[test]
+ fn test_is_number(){
+ let json_value = from_str("12").unwrap();
+ assert!(json_value.is_number());
+ }
+
+ #[test]
+ fn test_as_number(){
+ let json_value = from_str("12").unwrap();
+ let json_num = json_value.as_number();
+ let expected_num = 12f64;
+ assert!(json_num.is_some() && json_num.unwrap() == expected_num);
+ }
+
+ #[test]
+ fn test_is_boolean(){
+ let json_value = from_str("false").unwrap();
+ assert!(json_value.is_boolean());
+ }
+
+ #[test]
+ fn test_as_boolean(){
+ let json_value = from_str("false").unwrap();
+ let json_bool = json_value.as_boolean();
+ let expected_bool = false;
+ assert!(json_bool.is_some() && json_bool.unwrap() == expected_bool);
+ }
+
+ #[test]
+ fn test_is_null(){
+ let json_value = from_str("null").unwrap();
+ assert!(json_value.is_null());
+ }
+
+ #[test]
+ fn test_as_null(){
+ let json_value = from_str("null").unwrap();
+ let json_null = json_value.as_null();
+ let expected_null = ();
+ assert!(json_null.is_some() && json_null.unwrap() == expected_null);
+ }
+
+ #[test]
+ fn test_encode_hashmap_with_numeric_key() {
+ use std::str::from_utf8;
+ use std::io::Writer;
+ use std::io::MemWriter;
+ use collections::HashMap;
+ let mut hm: HashMap<uint, bool> = HashMap::new();
+ hm.insert(1, true);
+ let mut mem_buf = MemWriter::new();
+ {
+ let mut encoder = Encoder::new(&mut mem_buf as &mut io::Writer);
+ hm.encode(&mut encoder)
+ }
+ let bytes = mem_buf.unwrap();
+ let json_str = from_utf8(bytes).unwrap();
+ match from_str(json_str) {
+ Err(_) => fail!("Unable to parse json_str: {:?}", json_str),
+ _ => {} // it parsed and we are good to go
+ }
+ }
+ #[test]
+ fn test_prettyencode_hashmap_with_numeric_key() {
+ use std::str::from_utf8;
+ use std::io::Writer;
+ use std::io::MemWriter;
+ use collections::HashMap;
+ let mut hm: HashMap<uint, bool> = HashMap::new();
+ hm.insert(1, true);
+ let mut mem_buf = MemWriter::new();
+ {
+ let mut encoder = PrettyEncoder::new(&mut mem_buf as &mut io::Writer);
+ hm.encode(&mut encoder)
+ }
+ let bytes = mem_buf.unwrap();
+ let json_str = from_utf8(bytes).unwrap();
+ match from_str(json_str) {
+ Err(_) => fail!("Unable to parse json_str: {:?}", json_str),
+ _ => {} // it parsed and we are good to go
+ }
+ }
+ #[test]
+ fn test_hashmap_with_numeric_key_can_handle_double_quote_delimited_key() {
+ use collections::HashMap;
+ use Decodable;
+ let json_str = "{\"1\":true}";
+ let json_obj = match from_str(json_str) {
+ Err(_) => fail!("Unable to parse json_str: {:?}", json_str),
+ Ok(o) => o
+ };
+ let mut decoder = Decoder::new(json_obj);
+ let _hm: HashMap<uint, bool> = Decodable::decode(&mut decoder);
+ }
+}
+
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;
use std::rc::Rc;
use std::slice;
-pub trait Encoder {
+pub trait Encoder<E> {
// Primitive types:
- fn emit_nil(&mut self);
- fn emit_uint(&mut self, v: uint);
- fn emit_u64(&mut self, v: u64);
- fn emit_u32(&mut self, v: u32);
- fn emit_u16(&mut self, v: u16);
- fn emit_u8(&mut self, v: u8);
- fn emit_int(&mut self, v: int);
- fn emit_i64(&mut self, v: i64);
- fn emit_i32(&mut self, v: i32);
- fn emit_i16(&mut self, v: i16);
- fn emit_i8(&mut self, v: i8);
- fn emit_bool(&mut self, v: bool);
- fn emit_f64(&mut self, v: f64);
- fn emit_f32(&mut self, v: f32);
- fn emit_char(&mut self, v: char);
- fn emit_str(&mut self, v: &str);
+ fn emit_nil(&mut self) -> Result<(), E>;
+ fn emit_uint(&mut self, v: uint) -> Result<(), E>;
+ fn emit_u64(&mut self, v: u64) -> Result<(), E>;
+ fn emit_u32(&mut self, v: u32) -> Result<(), E>;
+ fn emit_u16(&mut self, v: u16) -> Result<(), E>;
+ fn emit_u8(&mut self, v: u8) -> Result<(), E>;
+ fn emit_int(&mut self, v: int) -> Result<(), E>;
+ fn emit_i64(&mut self, v: i64) -> Result<(), E>;
+ fn emit_i32(&mut self, v: i32) -> Result<(), E>;
+ fn emit_i16(&mut self, v: i16) -> Result<(), E>;
+ fn emit_i8(&mut self, v: i8) -> Result<(), E>;
+ fn emit_bool(&mut self, v: bool) -> Result<(), E>;
+ fn emit_f64(&mut self, v: f64) -> Result<(), E>;
+ fn emit_f32(&mut self, v: f32) -> Result<(), E>;
+ fn emit_char(&mut self, v: char) -> Result<(), E>;
+ fn emit_str(&mut self, v: &str) -> Result<(), E>;
// Compound types:
- fn emit_enum(&mut self, name: &str, f: |&mut Self|);
+ fn emit_enum(&mut self, name: &str, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
fn emit_enum_variant(&mut self,
v_name: &str,
v_id: uint,
len: uint,
- f: |&mut Self|);
- fn emit_enum_variant_arg(&mut self, a_idx: uint, f: |&mut Self|);
+ f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
+ fn emit_enum_variant_arg(&mut self,
+ a_idx: uint,
+ f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
fn emit_enum_struct_variant(&mut self,
v_name: &str,
v_id: uint,
len: uint,
- f: |&mut Self|);
+ f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
fn emit_enum_struct_variant_field(&mut self,
f_name: &str,
f_idx: uint,
- f: |&mut Self|);
+ f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
- fn emit_struct(&mut self, name: &str, len: uint, f: |&mut Self|);
+ fn emit_struct(&mut self,
+ name: &str,
+ len: uint,
+ f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
fn emit_struct_field(&mut self,
f_name: &str,
f_idx: uint,
- f: |&mut Self|);
+ f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
- fn emit_tuple(&mut self, len: uint, f: |&mut Self|);
- fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Self|);
+ fn emit_tuple(&mut self, len: uint, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
+ fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
- fn emit_tuple_struct(&mut self, name: &str, len: uint, f: |&mut Self|);
- fn emit_tuple_struct_arg(&mut self, f_idx: uint, f: |&mut Self|);
+ fn emit_tuple_struct(&mut self,
+ name: &str,
+ len: uint,
+ f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
+ fn emit_tuple_struct_arg(&mut self,
+ f_idx: uint,
+ f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
// Specialized types:
- fn emit_option(&mut self, f: |&mut Self|);
- fn emit_option_none(&mut self);
- fn emit_option_some(&mut self, f: |&mut Self|);
+ fn emit_option(&mut self, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
+ fn emit_option_none(&mut self) -> Result<(), E>;
+ fn emit_option_some(&mut self, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
- fn emit_seq(&mut self, len: uint, f: |this: &mut Self|);
- fn emit_seq_elt(&mut self, idx: uint, f: |this: &mut Self|);
+ fn emit_seq(&mut self, len: uint, f: |this: &mut Self| -> Result<(), E>) -> Result<(), E>;
+ fn emit_seq_elt(&mut self, idx: uint, f: |this: &mut Self| -> Result<(), E>) -> Result<(), E>;
- fn emit_map(&mut self, len: uint, f: |&mut Self|);
- fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Self|);
- fn emit_map_elt_val(&mut self, idx: uint, f: |&mut Self|);
+ fn emit_map(&mut self, len: uint, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
+ fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
+ fn emit_map_elt_val(&mut self, idx: uint, f: |&mut Self| -> Result<(), E>) -> Result<(), E>;
}
-pub trait Decoder {
+pub trait Decoder<E> {
// Primitive types:
- fn read_nil(&mut self) -> ();
- fn read_uint(&mut self) -> uint;
- fn read_u64(&mut self) -> u64;
- fn read_u32(&mut self) -> u32;
- fn read_u16(&mut self) -> u16;
- fn read_u8(&mut self) -> u8;
- fn read_int(&mut self) -> int;
- fn read_i64(&mut self) -> i64;
- fn read_i32(&mut self) -> i32;
- fn read_i16(&mut self) -> i16;
- fn read_i8(&mut self) -> i8;
- fn read_bool(&mut self) -> bool;
- fn read_f64(&mut self) -> f64;
- fn read_f32(&mut self) -> f32;
- fn read_char(&mut self) -> char;
- fn read_str(&mut self) -> ~str;
+ fn read_nil(&mut self) -> Result<(), E>;
+ fn read_uint(&mut self) -> Result<uint, E>;
+ fn read_u64(&mut self) -> Result<u64, E>;
+ fn read_u32(&mut self) -> Result<u32, E>;
+ fn read_u16(&mut self) -> Result<u16, E>;
+ fn read_u8(&mut self) -> Result<u8, E>;
+ fn read_int(&mut self) -> Result<int, E>;
+ fn read_i64(&mut self) -> Result<i64, E>;
+ fn read_i32(&mut self) -> Result<i32, E>;
+ fn read_i16(&mut self) -> Result<i16, E>;
+ fn read_i8(&mut self) -> Result<i8, E>;
+ fn read_bool(&mut self) -> Result<bool, E>;
+ fn read_f64(&mut self) -> Result<f64, E>;
+ fn read_f32(&mut self) -> Result<f32, E>;
+ fn read_char(&mut self) -> Result<char, E>;
+ fn read_str(&mut self) -> Result<~str, E>;
// Compound types:
- fn read_enum<T>(&mut self, name: &str, f: |&mut Self| -> T) -> T;
+ fn read_enum<T>(&mut self, name: &str, f: |&mut Self| -> Result<T, E>) -> Result<T, E>;
fn read_enum_variant<T>(&mut self,
names: &[&str],
- f: |&mut Self, uint| -> T)
- -> T;
+ f: |&mut Self, uint| -> Result<T, E>)
+ -> Result<T, E>;
fn read_enum_variant_arg<T>(&mut self,
a_idx: uint,
- f: |&mut Self| -> T)
- -> T;
+ f: |&mut Self| -> Result<T, E>)
+ -> Result<T, E>;
fn read_enum_struct_variant<T>(&mut self,
names: &[&str],
- f: |&mut Self, uint| -> T)
- -> T;
+ f: |&mut Self, uint| -> Result<T, E>)
+ -> Result<T, E>;
fn read_enum_struct_variant_field<T>(&mut self,
&f_name: &str,
f_idx: uint,
- f: |&mut Self| -> T)
- -> T;
+ f: |&mut Self| -> Result<T, E>)
+ -> Result<T, E>;
- fn read_struct<T>(&mut self, s_name: &str, len: uint, f: |&mut Self| -> T)
- -> T;
+ fn read_struct<T>(&mut self, s_name: &str, len: uint, f: |&mut Self| -> Result<T, E>)
+ -> Result<T, E>;
fn read_struct_field<T>(&mut self,
f_name: &str,
f_idx: uint,
- f: |&mut Self| -> T)
- -> T;
+ f: |&mut Self| -> Result<T, E>)
+ -> Result<T, E>;
- fn read_tuple<T>(&mut self, f: |&mut Self, uint| -> T) -> T;
- fn read_tuple_arg<T>(&mut self, a_idx: uint, f: |&mut Self| -> T) -> T;
+ fn read_tuple<T>(&mut self, f: |&mut Self, uint| -> Result<T, E>) -> Result<T, E>;
+ fn read_tuple_arg<T>(&mut self, a_idx: uint, f: |&mut Self| -> Result<T, E>) -> Result<T, E>;
fn read_tuple_struct<T>(&mut self,
s_name: &str,
- f: |&mut Self, uint| -> T)
- -> T;
+ f: |&mut Self, uint| -> Result<T, E>)
+ -> Result<T, E>;
fn read_tuple_struct_arg<T>(&mut self,
a_idx: uint,
- f: |&mut Self| -> T)
- -> T;
+ f: |&mut Self| -> Result<T, E>)
+ -> Result<T, E>;
// Specialized types:
- fn read_option<T>(&mut self, f: |&mut Self, bool| -> T) -> T;
+ fn read_option<T>(&mut self, f: |&mut Self, bool| -> Result<T, E>) -> Result<T, E>;
- fn read_seq<T>(&mut self, f: |&mut Self, uint| -> T) -> T;
- fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Self| -> T) -> T;
+ fn read_seq<T>(&mut self, f: |&mut Self, uint| -> Result<T, E>) -> Result<T, E>;
+ fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Self| -> Result<T, E>) -> Result<T, E>;
- fn read_map<T>(&mut self, f: |&mut Self, uint| -> T) -> T;
- fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Self| -> T) -> T;
- fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Self| -> T) -> T;
+ fn read_map<T>(&mut self, f: |&mut Self, uint| -> Result<T, E>) -> Result<T, E>;
+ fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Self| -> Result<T, E>) -> Result<T, E>;
+ fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Self| -> Result<T, E>) -> Result<T, E>;
}
-pub trait Encodable<S:Encoder> {
- fn encode(&self, s: &mut S);
+pub trait Encodable<S:Encoder<E>, E> {
+ fn encode(&self, s: &mut S) -> Result<(), E>;
}
-pub trait Decodable<D:Decoder> {
- fn decode(d: &mut D) -> Self;
+pub trait Decodable<D:Decoder<E>, E> {
+ fn decode(d: &mut D) -> Result<Self, E>;
}
-impl<S:Encoder> Encodable<S> for uint {
- fn encode(&self, s: &mut S) {
+macro_rules! try ( ($e:expr) => (
+ match $e { Ok(v) => v, Err(e) => return Err(e) }
+))
+
+impl<E, S:Encoder<E>> Encodable<S, E> for uint {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_uint(*self)
}
}
-impl<D:Decoder> Decodable<D> for uint {
- fn decode(d: &mut D) -> uint {
+impl<E, D:Decoder<E>> Decodable<D, E> for uint {
+ fn decode(d: &mut D) -> Result<uint, E> {
d.read_uint()
}
}
-impl<S:Encoder> Encodable<S> for u8 {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for u8 {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_u8(*self)
}
}
-impl<D:Decoder> Decodable<D> for u8 {
- fn decode(d: &mut D) -> u8 {
+impl<E, D:Decoder<E>> Decodable<D, E> for u8 {
+ fn decode(d: &mut D) -> Result<u8, E> {
d.read_u8()
}
}
-impl<S:Encoder> Encodable<S> for u16 {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for u16 {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_u16(*self)
}
}
-impl<D:Decoder> Decodable<D> for u16 {
- fn decode(d: &mut D) -> u16 {
+impl<E, D:Decoder<E>> Decodable<D, E> for u16 {
+ fn decode(d: &mut D) -> Result<u16, E> {
d.read_u16()
}
}
-impl<S:Encoder> Encodable<S> for u32 {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for u32 {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_u32(*self)
}
}
-impl<D:Decoder> Decodable<D> for u32 {
- fn decode(d: &mut D) -> u32 {
+impl<E, D:Decoder<E>> Decodable<D, E> for u32 {
+ fn decode(d: &mut D) -> Result<u32, E> {
d.read_u32()
}
}
-impl<S:Encoder> Encodable<S> for u64 {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for u64 {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_u64(*self)
}
}
-impl<D:Decoder> Decodable<D> for u64 {
- fn decode(d: &mut D) -> u64 {
+impl<E, D:Decoder<E>> Decodable<D, E> for u64 {
+ fn decode(d: &mut D) -> Result<u64, E> {
d.read_u64()
}
}
-impl<S:Encoder> Encodable<S> for int {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for int {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_int(*self)
}
}
-impl<D:Decoder> Decodable<D> for int {
- fn decode(d: &mut D) -> int {
+impl<E, D:Decoder<E>> Decodable<D, E> for int {
+ fn decode(d: &mut D) -> Result<int, E> {
d.read_int()
}
}
-impl<S:Encoder> Encodable<S> for i8 {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for i8 {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_i8(*self)
}
}
-impl<D:Decoder> Decodable<D> for i8 {
- fn decode(d: &mut D) -> i8 {
+impl<E, D:Decoder<E>> Decodable<D, E> for i8 {
+ fn decode(d: &mut D) -> Result<i8, E> {
d.read_i8()
}
}
-impl<S:Encoder> Encodable<S> for i16 {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for i16 {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_i16(*self)
}
}
-impl<D:Decoder> Decodable<D> for i16 {
- fn decode(d: &mut D) -> i16 {
+impl<E, D:Decoder<E>> Decodable<D, E> for i16 {
+ fn decode(d: &mut D) -> Result<i16, E> {
d.read_i16()
}
}
-impl<S:Encoder> Encodable<S> for i32 {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for i32 {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_i32(*self)
}
}
-impl<D:Decoder> Decodable<D> for i32 {
- fn decode(d: &mut D) -> i32 {
+impl<E, D:Decoder<E>> Decodable<D, E> for i32 {
+ fn decode(d: &mut D) -> Result<i32, E> {
d.read_i32()
}
}
-impl<S:Encoder> Encodable<S> for i64 {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for i64 {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_i64(*self)
}
}
-impl<D:Decoder> Decodable<D> for i64 {
- fn decode(d: &mut D) -> i64 {
+impl<E, D:Decoder<E>> Decodable<D, E> for i64 {
+ fn decode(d: &mut D) -> Result<i64, E> {
d.read_i64()
}
}
-impl<'a, S:Encoder> Encodable<S> for &'a str {
- fn encode(&self, s: &mut S) {
+impl<'a, E, S:Encoder<E>> Encodable<S, E> for &'a str {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_str(*self)
}
}
-impl<S:Encoder> Encodable<S> for ~str {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for ~str {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_str(*self)
}
}
-impl<D:Decoder> Decodable<D> for ~str {
- fn decode(d: &mut D) -> ~str {
+impl<E, D:Decoder<E>> Decodable<D, E> for ~str {
+ fn decode(d: &mut D) -> Result<~str, E> {
d.read_str()
}
}
-impl<S:Encoder> Encodable<S> for f32 {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for f32 {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_f32(*self)
}
}
-impl<D:Decoder> Decodable<D> for f32 {
- fn decode(d: &mut D) -> f32 {
+impl<E, D:Decoder<E>> Decodable<D, E> for f32 {
+ fn decode(d: &mut D) -> Result<f32, E> {
d.read_f32()
}
}
-impl<S:Encoder> Encodable<S> for f64 {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for f64 {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_f64(*self)
}
}
-impl<D:Decoder> Decodable<D> for f64 {
- fn decode(d: &mut D) -> f64 {
+impl<E, D:Decoder<E>> Decodable<D, E> for f64 {
+ fn decode(d: &mut D) -> Result<f64, E> {
d.read_f64()
}
}
-impl<S:Encoder> Encodable<S> for bool {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for bool {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_bool(*self)
}
}
-impl<D:Decoder> Decodable<D> for bool {
- fn decode(d: &mut D) -> bool {
+impl<E, D:Decoder<E>> Decodable<D, E> for bool {
+ fn decode(d: &mut D) -> Result<bool, E> {
d.read_bool()
}
}
-impl<S:Encoder> Encodable<S> for char {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for char {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_char(*self)
}
}
-impl<D:Decoder> Decodable<D> for char {
- fn decode(d: &mut D) -> char {
+impl<E, D:Decoder<E>> Decodable<D, E> for char {
+ fn decode(d: &mut D) -> Result<char, E> {
d.read_char()
}
}
-impl<S:Encoder> Encodable<S> for () {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>> Encodable<S, E> for () {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_nil()
}
}
-impl<D:Decoder> Decodable<D> for () {
- fn decode(d: &mut D) -> () {
+impl<E, D:Decoder<E>> Decodable<D, E> for () {
+ fn decode(d: &mut D) -> Result<(), E> {
d.read_nil()
}
}
-impl<'a, S:Encoder,T:Encodable<S>> Encodable<S> for &'a T {
- fn encode(&self, s: &mut S) {
+impl<'a, E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for &'a T {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
(**self).encode(s)
}
}
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for ~T {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for ~T {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
(**self).encode(s)
}
}
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for ~T {
- fn decode(d: &mut D) -> ~T {
- ~Decodable::decode(d)
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for ~T {
+ fn decode(d: &mut D) -> Result<~T, E> {
+ Ok(~try!(Decodable::decode(d)))
}
}
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for @T {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for @T {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
(**self).encode(s)
}
}
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for Rc<T> {
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Rc<T> {
#[inline]
- fn encode(&self, s: &mut S) {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
(**self).encode(s)
}
}
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for Rc<T> {
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Rc<T> {
#[inline]
- fn decode(d: &mut D) -> Rc<T> {
- Rc::new(Decodable::decode(d))
+ fn decode(d: &mut D) -> Result<Rc<T>, E> {
+ Ok(Rc::new(try!(Decodable::decode(d))))
}
}
-impl<D:Decoder,T:Decodable<D> + 'static> Decodable<D> for @T {
- fn decode(d: &mut D) -> @T {
- @Decodable::decode(d)
+impl<E, D:Decoder<E>,T:Decodable<D, E> + 'static> Decodable<D, E> for @T {
+ fn decode(d: &mut D) -> Result<@T, E> {
+ Ok(@try!(Decodable::decode(d)))
}
}
-impl<'a, S:Encoder,T:Encodable<S>> Encodable<S> for &'a [T] {
- fn encode(&self, s: &mut S) {
+impl<'a, E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for &'a [T] {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
- s.emit_seq_elt(i, |s| e.encode(s))
+ try!(s.emit_seq_elt(i, |s| e.encode(s)))
}
+ Ok(())
})
}
}
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for ~[T] {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for ~[T] {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
- s.emit_seq_elt(i, |s| e.encode(s))
+ try!(s.emit_seq_elt(i, |s| e.encode(s)))
}
+ Ok(())
})
}
}
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for ~[T] {
- fn decode(d: &mut D) -> ~[T] {
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for ~[T] {
+ fn decode(d: &mut D) -> Result<~[T], E> {
d.read_seq(|d, len| {
- slice::from_fn(len, |i| {
- d.read_seq_elt(i, |d| Decodable::decode(d))
- })
+ let mut v: ~[T] = slice::with_capacity(len);
+ for i in range(0, len) {
+ v.push(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
+ }
+ Ok(v)
})
}
}
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for Vec<T> {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Vec<T> {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
- s.emit_seq_elt(i, |s| e.encode(s))
+ try!(s.emit_seq_elt(i, |s| e.encode(s)))
}
+ Ok(())
})
}
}
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for Vec<T> {
- fn decode(d: &mut D) -> Vec<T> {
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Vec<T> {
+ fn decode(d: &mut D) -> Result<Vec<T>, E> {
d.read_seq(|d, len| {
- Vec::from_fn(len, |i| {
- d.read_seq_elt(i, |d| Decodable::decode(d))
- })
+ let mut v = Vec::with_capacity(len);
+ for i in range(0, len) {
+ v.push(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
+ }
+ Ok(v)
})
}
}
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for Option<T> {
- fn encode(&self, s: &mut S) {
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Option<T> {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_option(|s| {
match *self {
None => s.emit_option_none(),
}
}
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for Option<T> {
- fn decode(d: &mut D) -> Option<T> {
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Option<T> {
+ fn decode(d: &mut D) -> Result<Option<T>, E> {
d.read_option(|d, b| {
if b {
- Some(Decodable::decode(d))
+ Ok(Some(try!(Decodable::decode(d))))
} else {
- None
+ Ok(None)
}
})
}
macro_rules! tuple (
() => ();
( $($name:ident,)+ ) => (
- impl<D:Decoder,$($name:Decodable<D>),*> Decodable<D> for ($($name,)*) {
+ impl<E, D:Decoder<E>,$($name:Decodable<D, E>),*> Decodable<D,E> for ($($name,)*) {
#[allow(uppercase_variables)]
- fn decode(d: &mut D) -> ($($name,)*) {
+ fn decode(d: &mut D) -> Result<($($name,)*), E> {
d.read_tuple(|d, amt| {
let mut i = 0;
- let ret = ($(d.read_tuple_arg({ i+=1; i-1 }, |d| -> $name {
+ let ret = ($(try!(d.read_tuple_arg({ i+=1; i-1 }, |d| -> Result<$name,E> {
Decodable::decode(d)
- }),)*);
+ })),)*);
assert!(amt == i,
"expected tuple of length `{}`, found tuple \
of length `{}`", i, amt);
- return ret;
+ return Ok(ret);
})
}
}
- impl<S:Encoder,$($name:Encodable<S>),*> Encodable<S> for ($($name,)*) {
+ impl<E, S:Encoder<E>,$($name:Encodable<S, E>),*> Encodable<S, E> for ($($name,)*) {
#[allow(uppercase_variables)]
- fn encode(&self, s: &mut S) {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
let ($(ref $name,)*) = *self;
let mut n = 0;
$(let $name = $name; n += 1;)*
s.emit_tuple(n, |s| {
let mut i = 0;
- $(s.emit_seq_elt({ i+=1; i-1 }, |s| $name.encode(s));)*
+ $(try!(s.emit_seq_elt({ i+=1; i-1 }, |s| $name.encode(s)));)*
+ Ok(())
})
}
}
tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
-impl<E: Encoder> Encodable<E> for path::posix::Path {
- fn encode(&self, e: &mut E) {
+impl<E, S: Encoder<E>> Encodable<S, E> for path::posix::Path {
+ fn encode(&self, e: &mut S) -> Result<(), E> {
self.as_vec().encode(e)
}
}
-impl<D: Decoder> Decodable<D> for path::posix::Path {
- fn decode(d: &mut D) -> path::posix::Path {
- let bytes: ~[u8] = Decodable::decode(d);
- path::posix::Path::new(bytes)
+impl<E, D: Decoder<E>> Decodable<D, E> for path::posix::Path {
+ fn decode(d: &mut D) -> Result<path::posix::Path, E> {
+ let bytes: ~[u8] = try!(Decodable::decode(d));
+ Ok(path::posix::Path::new(bytes))
}
}
-impl<E: Encoder> Encodable<E> for path::windows::Path {
- fn encode(&self, e: &mut E) {
+impl<E, S: Encoder<E>> Encodable<S, E> for path::windows::Path {
+ fn encode(&self, e: &mut S) -> Result<(), E> {
self.as_vec().encode(e)
}
}
-impl<D: Decoder> Decodable<D> for path::windows::Path {
- fn decode(d: &mut D) -> path::windows::Path {
- let bytes: ~[u8] = Decodable::decode(d);
- path::windows::Path::new(bytes)
+impl<E, D: Decoder<E>> Decodable<D, E> for path::windows::Path {
+ fn decode(d: &mut D) -> Result<path::windows::Path, E> {
+ let bytes: ~[u8] = try!(Decodable::decode(d));
+ Ok(path::windows::Path::new(bytes))
}
}
//
// In some cases, these should eventually be coded as traits.
-pub trait EncoderHelpers {
- fn emit_from_vec<T>(&mut self, v: &[T], f: |&mut Self, v: &T|);
+pub trait EncoderHelpers<E> {
+ fn emit_from_vec<T>(&mut self,
+ v: &[T],
+ f: |&mut Self, v: &T| -> Result<(), E>) -> Result<(), E>;
}
-impl<S:Encoder> EncoderHelpers for S {
- fn emit_from_vec<T>(&mut self, v: &[T], f: |&mut S, &T|) {
+impl<E, S:Encoder<E>> EncoderHelpers<E> for S {
+ fn emit_from_vec<T>(&mut self, v: &[T], f: |&mut S, &T| -> Result<(), E>) -> Result<(), E> {
self.emit_seq(v.len(), |this| {
for (i, e) in v.iter().enumerate() {
- this.emit_seq_elt(i, |this| {
+ try!(this.emit_seq_elt(i, |this| {
f(this, e)
- })
+ }));
}
+ Ok(())
})
}
}
-pub trait DecoderHelpers {
- fn read_to_vec<T>(&mut self, f: |&mut Self| -> T) -> ~[T];
+pub trait DecoderHelpers<E> {
+ fn read_to_vec<T>(&mut self, f: |&mut Self| -> Result<T, E>) -> Result<~[T], E>;
}
-impl<D:Decoder> DecoderHelpers for D {
- fn read_to_vec<T>(&mut self, f: |&mut D| -> T) -> ~[T] {
+impl<E, D:Decoder<E>> DecoderHelpers<E> for D {
+ fn read_to_vec<T>(&mut self, f: |&mut D| -> Result<T, E>) -> Result<~[T], E> {
self.read_seq(|this, len| {
- slice::from_fn(len, |i| {
- this.read_seq_elt(i, |this| f(this))
- })
+ let mut v = slice::with_capacity(len);
+ for i in range(0, len) {
+ v.push(try!(this.read_seq_elt(i, |this| f(this))));
+ }
+ Ok(v)
})
}
}
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Support code for encoding and decoding types.
+
+/*
+Core encoding and decoding interfaces.
+*/
+
+use std::path;
+use std::rc::Rc;
+use std::slice;
+
+pub trait Encoder {
+ // Primitive types:
+ fn emit_nil(&mut self);
+ fn emit_uint(&mut self, v: uint);
+ fn emit_u64(&mut self, v: u64);
+ fn emit_u32(&mut self, v: u32);
+ fn emit_u16(&mut self, v: u16);
+ fn emit_u8(&mut self, v: u8);
+ fn emit_int(&mut self, v: int);
+ fn emit_i64(&mut self, v: i64);
+ fn emit_i32(&mut self, v: i32);
+ fn emit_i16(&mut self, v: i16);
+ fn emit_i8(&mut self, v: i8);
+ fn emit_bool(&mut self, v: bool);
+ fn emit_f64(&mut self, v: f64);
+ fn emit_f32(&mut self, v: f32);
+ fn emit_char(&mut self, v: char);
+ fn emit_str(&mut self, v: &str);
+
+ // Compound types:
+ fn emit_enum(&mut self, name: &str, f: |&mut Self|);
+
+ fn emit_enum_variant(&mut self,
+ v_name: &str,
+ v_id: uint,
+ len: uint,
+ f: |&mut Self|);
+ fn emit_enum_variant_arg(&mut self, a_idx: uint, f: |&mut Self|);
+
+ fn emit_enum_struct_variant(&mut self,
+ v_name: &str,
+ v_id: uint,
+ len: uint,
+ f: |&mut Self|);
+ fn emit_enum_struct_variant_field(&mut self,
+ f_name: &str,
+ f_idx: uint,
+ f: |&mut Self|);
+
+ fn emit_struct(&mut self, name: &str, len: uint, f: |&mut Self|);
+ fn emit_struct_field(&mut self,
+ f_name: &str,
+ f_idx: uint,
+ f: |&mut Self|);
+
+ fn emit_tuple(&mut self, len: uint, f: |&mut Self|);
+ fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Self|);
+
+ fn emit_tuple_struct(&mut self, name: &str, len: uint, f: |&mut Self|);
+ fn emit_tuple_struct_arg(&mut self, f_idx: uint, f: |&mut Self|);
+
+ // Specialized types:
+ fn emit_option(&mut self, f: |&mut Self|);
+ fn emit_option_none(&mut self);
+ fn emit_option_some(&mut self, f: |&mut Self|);
+
+ fn emit_seq(&mut self, len: uint, f: |this: &mut Self|);
+ fn emit_seq_elt(&mut self, idx: uint, f: |this: &mut Self|);
+
+ fn emit_map(&mut self, len: uint, f: |&mut Self|);
+ fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Self|);
+ fn emit_map_elt_val(&mut self, idx: uint, f: |&mut Self|);
+}
+
+pub trait Decoder {
+ // Primitive types:
+ fn read_nil(&mut self) -> ();
+ fn read_uint(&mut self) -> uint;
+ fn read_u64(&mut self) -> u64;
+ fn read_u32(&mut self) -> u32;
+ fn read_u16(&mut self) -> u16;
+ fn read_u8(&mut self) -> u8;
+ fn read_int(&mut self) -> int;
+ fn read_i64(&mut self) -> i64;
+ fn read_i32(&mut self) -> i32;
+ fn read_i16(&mut self) -> i16;
+ fn read_i8(&mut self) -> i8;
+ fn read_bool(&mut self) -> bool;
+ fn read_f64(&mut self) -> f64;
+ fn read_f32(&mut self) -> f32;
+ fn read_char(&mut self) -> char;
+ fn read_str(&mut self) -> ~str;
+
+ // Compound types:
+ fn read_enum<T>(&mut self, name: &str, f: |&mut Self| -> T) -> T;
+
+ fn read_enum_variant<T>(&mut self,
+ names: &[&str],
+ f: |&mut Self, uint| -> T)
+ -> T;
+ fn read_enum_variant_arg<T>(&mut self,
+ a_idx: uint,
+ f: |&mut Self| -> T)
+ -> T;
+
+ fn read_enum_struct_variant<T>(&mut self,
+ names: &[&str],
+ f: |&mut Self, uint| -> T)
+ -> T;
+ fn read_enum_struct_variant_field<T>(&mut self,
+ &f_name: &str,
+ f_idx: uint,
+ f: |&mut Self| -> T)
+ -> T;
+
+ fn read_struct<T>(&mut self, s_name: &str, len: uint, f: |&mut Self| -> T)
+ -> T;
+ fn read_struct_field<T>(&mut self,
+ f_name: &str,
+ f_idx: uint,
+ f: |&mut Self| -> T)
+ -> T;
+
+ fn read_tuple<T>(&mut self, f: |&mut Self, uint| -> T) -> T;
+ fn read_tuple_arg<T>(&mut self, a_idx: uint, f: |&mut Self| -> T) -> T;
+
+ fn read_tuple_struct<T>(&mut self,
+ s_name: &str,
+ f: |&mut Self, uint| -> T)
+ -> T;
+ fn read_tuple_struct_arg<T>(&mut self,
+ a_idx: uint,
+ f: |&mut Self| -> T)
+ -> T;
+
+ // Specialized types:
+ fn read_option<T>(&mut self, f: |&mut Self, bool| -> T) -> T;
+
+ fn read_seq<T>(&mut self, f: |&mut Self, uint| -> T) -> T;
+ fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Self| -> T) -> T;
+
+ fn read_map<T>(&mut self, f: |&mut Self, uint| -> T) -> T;
+ fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Self| -> T) -> T;
+ fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Self| -> T) -> T;
+}
+
+pub trait Encodable<S:Encoder> {
+ fn encode(&self, s: &mut S);
+}
+
+pub trait Decodable<D:Decoder> {
+ fn decode(d: &mut D) -> Self;
+}
+
+impl<S:Encoder> Encodable<S> for uint {
+ fn encode(&self, s: &mut S) {
+ s.emit_uint(*self)
+ }
+}
+
+impl<D:Decoder> Decodable<D> for uint {
+ fn decode(d: &mut D) -> uint {
+ d.read_uint()
+ }
+}
+
+impl<S:Encoder> Encodable<S> for u8 {
+ fn encode(&self, s: &mut S) {
+ s.emit_u8(*self)
+ }
+}
+
+impl<D:Decoder> Decodable<D> for u8 {
+ fn decode(d: &mut D) -> u8 {
+ d.read_u8()
+ }
+}
+
+impl<S:Encoder> Encodable<S> for u16 {
+ fn encode(&self, s: &mut S) {
+ s.emit_u16(*self)
+ }
+}
+
+impl<D:Decoder> Decodable<D> for u16 {
+ fn decode(d: &mut D) -> u16 {
+ d.read_u16()
+ }
+}
+
+impl<S:Encoder> Encodable<S> for u32 {
+ fn encode(&self, s: &mut S) {
+ s.emit_u32(*self)
+ }
+}
+
+impl<D:Decoder> Decodable<D> for u32 {
+ fn decode(d: &mut D) -> u32 {
+ d.read_u32()
+ }
+}
+
+impl<S:Encoder> Encodable<S> for u64 {
+ fn encode(&self, s: &mut S) {
+ s.emit_u64(*self)
+ }
+}
+
+impl<D:Decoder> Decodable<D> for u64 {
+ fn decode(d: &mut D) -> u64 {
+ d.read_u64()
+ }
+}
+
+impl<S:Encoder> Encodable<S> for int {
+ fn encode(&self, s: &mut S) {
+ s.emit_int(*self)
+ }
+}
+
+impl<D:Decoder> Decodable<D> for int {
+ fn decode(d: &mut D) -> int {
+ d.read_int()
+ }
+}
+
+impl<S:Encoder> Encodable<S> for i8 {
+ fn encode(&self, s: &mut S) {
+ s.emit_i8(*self)
+ }
+}
+
+impl<D:Decoder> Decodable<D> for i8 {
+ fn decode(d: &mut D) -> i8 {
+ d.read_i8()
+ }
+}
+
+impl<S:Encoder> Encodable<S> for i16 {
+ fn encode(&self, s: &mut S) {
+ s.emit_i16(*self)
+ }
+}
+
+impl<D:Decoder> Decodable<D> for i16 {
+ fn decode(d: &mut D) -> i16 {
+ d.read_i16()
+ }
+}
+
+impl<S:Encoder> Encodable<S> for i32 {
+ fn encode(&self, s: &mut S) {
+ s.emit_i32(*self)
+ }
+}
+
+impl<D:Decoder> Decodable<D> for i32 {
+ fn decode(d: &mut D) -> i32 {
+ d.read_i32()
+ }
+}
+
+impl<S:Encoder> Encodable<S> for i64 {
+ fn encode(&self, s: &mut S) {
+ s.emit_i64(*self)
+ }
+}
+
+impl<D:Decoder> Decodable<D> for i64 {
+ fn decode(d: &mut D) -> i64 {
+ d.read_i64()
+ }
+}
+
+impl<'a, S:Encoder> Encodable<S> for &'a str {
+ fn encode(&self, s: &mut S) {
+ s.emit_str(*self)
+ }
+}
+
+impl<S:Encoder> Encodable<S> for ~str {
+ fn encode(&self, s: &mut S) {
+ s.emit_str(*self)
+ }
+}
+
+impl<D:Decoder> Decodable<D> for ~str {
+ fn decode(d: &mut D) -> ~str {
+ d.read_str()
+ }
+}
+
+impl<S:Encoder> Encodable<S> for f32 {
+ fn encode(&self, s: &mut S) {
+ s.emit_f32(*self)
+ }
+}
+
+impl<D:Decoder> Decodable<D> for f32 {
+ fn decode(d: &mut D) -> f32 {
+ d.read_f32()
+ }
+}
+
+impl<S:Encoder> Encodable<S> for f64 {
+ fn encode(&self, s: &mut S) {
+ s.emit_f64(*self)
+ }
+}
+
+impl<D:Decoder> Decodable<D> for f64 {
+ fn decode(d: &mut D) -> f64 {
+ d.read_f64()
+ }
+}
+
+impl<S:Encoder> Encodable<S> for bool {
+ fn encode(&self, s: &mut S) {
+ s.emit_bool(*self)
+ }
+}
+
+impl<D:Decoder> Decodable<D> for bool {
+ fn decode(d: &mut D) -> bool {
+ d.read_bool()
+ }
+}
+
+impl<S:Encoder> Encodable<S> for char {
+ fn encode(&self, s: &mut S) {
+ s.emit_char(*self)
+ }
+}
+
+impl<D:Decoder> Decodable<D> for char {
+ fn decode(d: &mut D) -> char {
+ d.read_char()
+ }
+}
+
+impl<S:Encoder> Encodable<S> for () {
+ fn encode(&self, s: &mut S) {
+ s.emit_nil()
+ }
+}
+
+impl<D:Decoder> Decodable<D> for () {
+ fn decode(d: &mut D) -> () {
+ d.read_nil()
+ }
+}
+
+impl<'a, S:Encoder,T:Encodable<S>> Encodable<S> for &'a T {
+ fn encode(&self, s: &mut S) {
+ (**self).encode(s)
+ }
+}
+
+impl<S:Encoder,T:Encodable<S>> Encodable<S> for ~T {
+ fn encode(&self, s: &mut S) {
+ (**self).encode(s)
+ }
+}
+
+impl<D:Decoder,T:Decodable<D>> Decodable<D> for ~T {
+ fn decode(d: &mut D) -> ~T {
+ ~Decodable::decode(d)
+ }
+}
+
+impl<S:Encoder,T:Encodable<S>> Encodable<S> for @T {
+ fn encode(&self, s: &mut S) {
+ (**self).encode(s)
+ }
+}
+
+impl<S:Encoder,T:Encodable<S>> Encodable<S> for Rc<T> {
+ #[inline]
+ fn encode(&self, s: &mut S) {
+ (**self).encode(s)
+ }
+}
+
+impl<D:Decoder,T:Decodable<D>> Decodable<D> for Rc<T> {
+ #[inline]
+ fn decode(d: &mut D) -> Rc<T> {
+ Rc::new(Decodable::decode(d))
+ }
+}
+
+impl<D:Decoder,T:Decodable<D> + 'static> Decodable<D> for @T {
+ fn decode(d: &mut D) -> @T {
+ @Decodable::decode(d)
+ }
+}
+
+impl<'a, S:Encoder,T:Encodable<S>> Encodable<S> for &'a [T] {
+ fn encode(&self, s: &mut S) {
+ s.emit_seq(self.len(), |s| {
+ for (i, e) in self.iter().enumerate() {
+ s.emit_seq_elt(i, |s| e.encode(s))
+ }
+ })
+ }
+}
+
+impl<S:Encoder,T:Encodable<S>> Encodable<S> for ~[T] {
+ fn encode(&self, s: &mut S) {
+ s.emit_seq(self.len(), |s| {
+ for (i, e) in self.iter().enumerate() {
+ s.emit_seq_elt(i, |s| e.encode(s))
+ }
+ })
+ }
+}
+
+impl<D:Decoder,T:Decodable<D>> Decodable<D> for ~[T] {
+ fn decode(d: &mut D) -> ~[T] {
+ d.read_seq(|d, len| {
+ slice::from_fn(len, |i| {
+ d.read_seq_elt(i, |d| Decodable::decode(d))
+ })
+ })
+ }
+}
+
+impl<S:Encoder,T:Encodable<S>> Encodable<S> for Vec<T> {
+ fn encode(&self, s: &mut S) {
+ s.emit_seq(self.len(), |s| {
+ for (i, e) in self.iter().enumerate() {
+ s.emit_seq_elt(i, |s| e.encode(s))
+ }
+ })
+ }
+}
+
+impl<D:Decoder,T:Decodable<D>> Decodable<D> for Vec<T> {
+ fn decode(d: &mut D) -> Vec<T> {
+ d.read_seq(|d, len| {
+ Vec::from_fn(len, |i| {
+ d.read_seq_elt(i, |d| Decodable::decode(d))
+ })
+ })
+ }
+}
+
+impl<S:Encoder,T:Encodable<S>> Encodable<S> for Option<T> {
+ fn encode(&self, s: &mut S) {
+ s.emit_option(|s| {
+ match *self {
+ None => s.emit_option_none(),
+ Some(ref v) => s.emit_option_some(|s| v.encode(s)),
+ }
+ })
+ }
+}
+
+impl<D:Decoder,T:Decodable<D>> Decodable<D> for Option<T> {
+ fn decode(d: &mut D) -> Option<T> {
+ d.read_option(|d, b| {
+ if b {
+ Some(Decodable::decode(d))
+ } else {
+ None
+ }
+ })
+ }
+}
+
+impl<S:Encoder,T0:Encodable<S>,T1:Encodable<S>> Encodable<S> for (T0, T1) {
+ fn encode(&self, s: &mut S) {
+ match *self {
+ (ref t0, ref t1) => {
+ s.emit_seq(2, |s| {
+ s.emit_seq_elt(0, |s| t0.encode(s));
+ s.emit_seq_elt(1, |s| t1.encode(s));
+ })
+ }
+ }
+ }
+}
+
+impl<D:Decoder,T0:Decodable<D>,T1:Decodable<D>> Decodable<D> for (T0, T1) {
+ fn decode(d: &mut D) -> (T0, T1) {
+ d.read_seq(|d, len| {
+ assert_eq!(len, 2);
+ (
+ d.read_seq_elt(0, |d| Decodable::decode(d)),
+ d.read_seq_elt(1, |d| Decodable::decode(d))
+ )
+ })
+ }
+}
+
+impl<
+ S: Encoder,
+ T0: Encodable<S>,
+ T1: Encodable<S>,
+ T2: Encodable<S>
+> Encodable<S> for (T0, T1, T2) {
+ fn encode(&self, s: &mut S) {
+ match *self {
+ (ref t0, ref t1, ref t2) => {
+ s.emit_seq(3, |s| {
+ s.emit_seq_elt(0, |s| t0.encode(s));
+ s.emit_seq_elt(1, |s| t1.encode(s));
+ s.emit_seq_elt(2, |s| t2.encode(s));
+ })
+ }
+ }
+ }
+}
+
+impl<
+ D: Decoder,
+ T0: Decodable<D>,
+ T1: Decodable<D>,
+ T2: Decodable<D>
+> Decodable<D> for (T0, T1, T2) {
+ fn decode(d: &mut D) -> (T0, T1, T2) {
+ d.read_seq(|d, len| {
+ assert_eq!(len, 3);
+ (
+ d.read_seq_elt(0, |d| Decodable::decode(d)),
+ d.read_seq_elt(1, |d| Decodable::decode(d)),
+ d.read_seq_elt(2, |d| Decodable::decode(d))
+ )
+ })
+ }
+}
+
+impl<
+ S: Encoder,
+ T0: Encodable<S>,
+ T1: Encodable<S>,
+ T2: Encodable<S>,
+ T3: Encodable<S>
+> Encodable<S> for (T0, T1, T2, T3) {
+ fn encode(&self, s: &mut S) {
+ match *self {
+ (ref t0, ref t1, ref t2, ref t3) => {
+ s.emit_seq(4, |s| {
+ s.emit_seq_elt(0, |s| t0.encode(s));
+ s.emit_seq_elt(1, |s| t1.encode(s));
+ s.emit_seq_elt(2, |s| t2.encode(s));
+ s.emit_seq_elt(3, |s| t3.encode(s));
+ })
+ }
+ }
+ }
+}
+
+impl<
+ D: Decoder,
+ T0: Decodable<D>,
+ T1: Decodable<D>,
+ T2: Decodable<D>,
+ T3: Decodable<D>
+> Decodable<D> for (T0, T1, T2, T3) {
+ fn decode(d: &mut D) -> (T0, T1, T2, T3) {
+ d.read_seq(|d, len| {
+ assert_eq!(len, 4);
+ (
+ d.read_seq_elt(0, |d| Decodable::decode(d)),
+ d.read_seq_elt(1, |d| Decodable::decode(d)),
+ d.read_seq_elt(2, |d| Decodable::decode(d)),
+ d.read_seq_elt(3, |d| Decodable::decode(d))
+ )
+ })
+ }
+}
+
+impl<
+ S: Encoder,
+ T0: Encodable<S>,
+ T1: Encodable<S>,
+ T2: Encodable<S>,
+ T3: Encodable<S>,
+ T4: Encodable<S>
+> Encodable<S> for (T0, T1, T2, T3, T4) {
+ fn encode(&self, s: &mut S) {
+ match *self {
+ (ref t0, ref t1, ref t2, ref t3, ref t4) => {
+ s.emit_seq(5, |s| {
+ s.emit_seq_elt(0, |s| t0.encode(s));
+ s.emit_seq_elt(1, |s| t1.encode(s));
+ s.emit_seq_elt(2, |s| t2.encode(s));
+ s.emit_seq_elt(3, |s| t3.encode(s));
+ s.emit_seq_elt(4, |s| t4.encode(s));
+ })
+ }
+ }
+ }
+}
+
+impl<
+ D: Decoder,
+ T0: Decodable<D>,
+ T1: Decodable<D>,
+ T2: Decodable<D>,
+ T3: Decodable<D>,
+ T4: Decodable<D>
+> Decodable<D> for (T0, T1, T2, T3, T4) {
+ fn decode(d: &mut D) -> (T0, T1, T2, T3, T4) {
+ d.read_seq(|d, len| {
+ assert_eq!(len, 5);
+ (
+ d.read_seq_elt(0, |d| Decodable::decode(d)),
+ d.read_seq_elt(1, |d| Decodable::decode(d)),
+ d.read_seq_elt(2, |d| Decodable::decode(d)),
+ d.read_seq_elt(3, |d| Decodable::decode(d)),
+ d.read_seq_elt(4, |d| Decodable::decode(d))
+ )
+ })
+ }
+}
+
+impl<E: Encoder> Encodable<E> for path::posix::Path {
+ fn encode(&self, e: &mut E) {
+ self.as_vec().encode(e)
+ }
+}
+
+impl<D: Decoder> Decodable<D> for path::posix::Path {
+ fn decode(d: &mut D) -> path::posix::Path {
+ let bytes: ~[u8] = Decodable::decode(d);
+ path::posix::Path::new(bytes)
+ }
+}
+
+impl<E: Encoder> Encodable<E> for path::windows::Path {
+ fn encode(&self, e: &mut E) {
+ self.as_vec().encode(e)
+ }
+}
+
+impl<D: Decoder> Decodable<D> for path::windows::Path {
+ fn decode(d: &mut D) -> path::windows::Path {
+ let bytes: ~[u8] = Decodable::decode(d);
+ path::windows::Path::new(bytes)
+ }
+}
+
+// ___________________________________________________________________________
+// Helper routines
+//
+// In some cases, these should eventually be coded as traits.
+
+pub trait EncoderHelpers {
+ fn emit_from_vec<T>(&mut self, v: &[T], f: |&mut Self, v: &T|);
+}
+
+impl<S:Encoder> EncoderHelpers for S {
+ fn emit_from_vec<T>(&mut self, v: &[T], f: |&mut S, &T|) {
+ self.emit_seq(v.len(), |this| {
+ for (i, e) in v.iter().enumerate() {
+ this.emit_seq_elt(i, |this| {
+ f(this, e)
+ })
+ }
+ })
+ }
+}
+
+pub trait DecoderHelpers {
+ fn read_to_vec<T>(&mut self, f: |&mut Self| -> T) -> ~[T];
+}
+
+impl<D:Decoder> DecoderHelpers for D {
+ fn read_to_vec<T>(&mut self, f: |&mut D| -> T) -> ~[T] {
+ self.read_seq(|this, len| {
+ slice::from_fn(len, |i| {
+ this.read_seq_elt(i, |this| f(this))
+ })
+ })
+ }
+}
+
/// A mark represents a unique id associated with a macro expansion
pub type Mrk = u32;
+// FIXME: remove stage0 Encodables after snapshot
+#[cfg(stage0)]
impl<S: Encoder> Encodable<S> for Ident {
fn encode(&self, s: &mut S) {
s.emit_str(token::get_ident(*self).get());
}
}
+#[cfg(stage0)]
impl<D:Decoder> Decodable<D> for Ident {
fn decode(d: &mut D) -> Ident {
str_to_ident(d.read_str())
}
}
+#[cfg(not(stage0))]
+impl<S: Encoder<E>, E> Encodable<S, E> for Ident {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
+ s.emit_str(token::get_ident(*self).get())
+ }
+}
+
+#[cfg(not(stage0))]
+impl<D:Decoder<E>, E> Decodable<D, E> for Ident {
+ fn decode(d: &mut D) -> Result<Ident, E> {
+ Ok(str_to_ident(try!(d.read_str())))
+ }
+}
+
/// Function name (not all functions have names)
pub type FnIdent = Option<Ident>;
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()},
// doesn't matter which encoder we use....
let _f = &e as &serialize::Encodable<json::Encoder>;
}
+
+ #[test]
+ #[cfg(not(stage0))]
+ fn check_asts_encodable() {
+ use std::io;
+ let e = Crate {
+ module: Mod {view_items: Vec::new(), items: Vec::new()},
+ attrs: Vec::new(),
+ config: Vec::new(),
+ span: Span {
+ lo: BytePos(10),
+ hi: BytePos(20),
+ expn_info: None,
+ },
+ };
+ // doesn't matter which encoder we use....
+ let _f = &e as &serialize::Encodable<json::Encoder, io::IoError>;
+ }
}
impl TotalEq for Span {}
+// FIXME: remove stage0 Encodables/Decodables after snapshot
+#[cfg(stage0)]
impl<S:Encoder> Encodable<S> for Span {
/* Note #1972 -- spans are encoded but not decoded */
fn encode(&self, s: &mut S) {
}
}
+#[cfg(stage0)]
impl<D:Decoder> Decodable<D> for Span {
fn decode(_d: &mut D) -> Span {
DUMMY_SP
}
}
+#[cfg(not(stage0))]
+impl<S:Encoder<E>, E> Encodable<S, E> for Span {
+ /* Note #1972 -- spans are encoded but not decoded */
+ fn encode(&self, s: &mut S) -> Result<(), E> {
+ s.emit_nil()
+ }
+}
+
+#[cfg(not(stage0))]
+impl<D:Decoder<E>, E> Decodable<D, E> for Span {
+ fn decode(_d: &mut D) -> Result<Span, E> {
+ Ok(DUMMY_SP)
+ }
+}
+
pub fn spanned<T>(lo: BytePos, hi: BytePos, t: T) -> Spanned<T> {
respan(mk_sp(lo, hi), t)
}
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;
"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 }
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 {
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,
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"),
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,
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,
```
*/
-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;
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,
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_,
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));
}
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);
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,
}
}
+// FIXME: remove stage0 Encodables/Decodables after snapshot
+#[cfg(stage0)]
impl<S: Encoder, T: Encodable<S>> Encodable<S> for OwnedSlice<T> {
fn encode(&self, s: &mut S) {
self.as_slice().encode(s)
}
}
+#[cfg(stage0)]
impl<D: Decoder, T: Decodable<D>> Decodable<D> for OwnedSlice<T> {
fn decode(d: &mut D) -> OwnedSlice<T> {
OwnedSlice::from_vec(Decodable::decode(d))
}
}
+
+#[cfg(not(stage0))]
+impl<S: Encoder<E>, T: Encodable<S, E>, E> Encodable<S, E> for OwnedSlice<T> {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
+ self.as_slice().encode(s)
+ }
+}
+
+#[cfg(not(stage0))]
+impl<D: Decoder<E>, T: Decodable<D, E>, E> Decodable<D, E> for OwnedSlice<T> {
+ fn decode(d: &mut D) -> Result<OwnedSlice<T>, E> {
+ Ok(OwnedSlice::from_vec(match Decodable::decode(d) {
+ Ok(t) => t,
+ Err(e) => return Err(e)
+ }))
+ }
+}
use util::parser_testing::{string_to_expr, string_to_item};
use util::parser_testing::string_to_stmt;
- #[cfg(test)]
+ // FIXME: remove stage0 to_json_str after snapshot
+ #[cfg(stage0)]
fn to_json_str<'a, E: Encodable<json::Encoder<'a>>>(val: &E) -> ~str {
let mut writer = MemWriter::new();
let mut encoder = json::Encoder::new(&mut writer as &mut io::Writer);
str::from_utf8_owned(writer.unwrap()).unwrap()
}
+ #[cfg(not(stage0))]
+ fn to_json_str<'a, E: Encodable<json::Encoder<'a>, io::IoError>>(val: &E) -> ~str {
+ let mut writer = MemWriter::new();
+ let mut encoder = json::Encoder::new(&mut writer as &mut io::Writer);
+ let _ = val.encode(&mut encoder);
+ str::from_utf8_owned(writer.unwrap()).unwrap()
+ }
+
// produce a codemap::span
fn sp(a: u32, b: u32) -> Span {
Span{lo:BytePos(a),hi:BytePos(b),expn_info:None}
}
}
+// FIXME: remove stage0 Encodables/Decodables after snapshot
+#[cfg(stage0)]
impl<D:Decoder> Decodable<D> for InternedString {
fn decode(d: &mut D) -> InternedString {
get_name(get_ident_interner().intern(d.read_str()))
}
}
+#[cfg(stage0)]
impl<E:Encoder> Encodable<E> for InternedString {
fn encode(&self, e: &mut E) {
e.emit_str(self.string.as_slice())
}
}
+#[cfg(not(stage0))]
+impl<D:Decoder<E>, E> Decodable<D, E> for InternedString {
+ fn decode(d: &mut D) -> Result<InternedString, E> {
+ Ok(get_name(get_ident_interner().intern(try!(d.read_str()))))
+ }
+}
+
+#[cfg(not(stage0))]
+impl<S:Encoder<E>, E> Encodable<S, E> for InternedString {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
+ s.emit_str(self.string.as_slice())
+ }
+}
+
/// Returns the string contents of a name, using the task-local interner.
#[inline]
pub fn get_name(name: Name) -> InternedString {
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};
}
}
+// 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 {
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.
impl TotalEq for Uuid {}
// FIXME #9845: Test these more thoroughly
+// FIXME: remove stage0 Encodable/Decodable after snapshot
+#[cfg(stage0)]
impl<T: Encoder> Encodable<T> for Uuid {
/// Encode a UUID as a hypenated string
fn encode(&self, e: &mut T) {
- e.emit_str(self.to_hyphenated_str());
+ e.emit_str(self.to_hyphenated_str())
}
}
+#[cfg(stage0)]
impl<T: Decoder> Decodable<T> for Uuid {
/// Decode a UUID from a string
fn decode(d: &mut T) -> Uuid {
}
}
+#[cfg(not(stage0))]
+impl<T: Encoder<E>, E> Encodable<T, E> for Uuid {
+ /// Encode a UUID as a hypenated string
+ fn encode(&self, e: &mut T) -> Result<(), E> {
+ e.emit_str(self.to_hyphenated_str())
+ }
+}
+
+#[cfg(not(stage0))]
+impl<T: Decoder<E>, E> Decodable<T, E> for Uuid {
+ /// Decode a UUID from a string
+ fn decode(d: &mut T) -> Result<Uuid, E> {
+ Ok(from_str(try!(d.read_str())).unwrap())
+ }
+}
+
/// Generates a random instance of UUID (V4 conformant)
impl rand::Rand for Uuid {
#[inline]
use std::str;
use std::io::MemWriter;
+ // FIXME: remove unwrap_ after snapshot
+ #[cfg(stage0)]
+ fn unwrap_<T>(t: T) -> T {
+ t
+ }
+
+ #[cfg(not(stage0))]
+ fn unwrap_<T, E>(t: Result<T, E>) -> T {
+ t.unwrap()
+ }
+
#[test]
fn test_nil() {
let nil = Uuid::nil();
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);
}
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();
}
}
}
WorkFromTask(&'a Prep<'a>, Receiver<(Exec, T)>),
}
-fn json_encode<'a, T:Encodable<json::Encoder<'a>>>(t: &T) -> ~str {
+fn json_encode<'a, T:Encodable<json::Encoder<'a>, io::IoError>>(t: &T) -> ~str {
let mut writer = MemWriter::new();
let mut encoder = json::Encoder::new(&mut writer as &mut io::Writer);
- t.encode(&mut encoder);
+ let _ = t.encode(&mut encoder);
str::from_utf8_owned(writer.unwrap()).unwrap()
}
// FIXME(#5121)
-fn json_decode<T:Decodable<json::Decoder>>(s: &str) -> T {
+fn json_decode<T:Decodable<json::Decoder, json::Error>>(s: &str) -> T {
debug!("json decoding: {}", s);
let j = json::from_str(s).unwrap();
let mut decoder = json::Decoder::new(j);
- Decodable::decode(&mut decoder)
+ Decodable::decode(&mut decoder).unwrap()
}
impl Context {
}
pub fn exec<'a, T:Send +
- Encodable<json::Encoder<'a>> +
- Decodable<json::Decoder>>(
+ Encodable<json::Encoder<'a>, io::IoError> +
+ Decodable<json::Decoder, json::Error>>(
&'a self, blk: proc:Send(&mut Exec) -> T) -> T {
self.exec_work(blk).unwrap()
}
fn exec_work<'a, T:Send +
- Encodable<json::Encoder<'a>> +
- Decodable<json::Decoder>>( // FIXME(#5121)
+ Encodable<json::Encoder<'a>, io::IoError> +
+ Decodable<json::Decoder, json::Error>>( // FIXME(#5121)
&'a self, blk: proc:Send(&mut Exec) -> T) -> Work<'a, T> {
let mut bo = Some(blk);
}
impl<'a, T:Send +
- Encodable<json::Encoder<'a>> +
- Decodable<json::Decoder>>
+ Encodable<json::Encoder<'a>, io::IoError> +
+ Decodable<json::Decoder, json::Error>>
Work<'a, T> { // FIXME(#5121)
pub fn from_value(elt: T) -> Work<'a, T> {
use serialize::{json, Decodable};
-trait JD : Decodable<json::Decoder> { }
+trait JD : Decodable<json::Decoder, json::Error> { }
fn exec<T: JD>() {
let doc = json::from_str("").unwrap();
let mut decoder = json::Decoder::new(doc);
- let _v: T = Decodable::decode(&mut decoder);
+ let _v: T = Decodable::decode(&mut decoder).unwrap();
fail!()
}
pub fn main() {
let json = json::from_str("[1]").unwrap();
let mut decoder = json::Decoder::new(json);
- let _x: Vec<int> = Decodable::decode(&mut decoder);
+ let _x: Vec<int> = Decodable::decode(&mut decoder).unwrap();
}