about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--mk/crates.mk9
-rw-r--r--mk/tests.mk2
-rw-r--r--src/librbml/Cargo.toml13
-rw-r--r--src/librbml/lib.rs63
-rw-r--r--src/librustc/Cargo.toml1
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/middle/cstore.rs6
-rw-r--r--src/librustc_incremental/Cargo.toml3
-rw-r--r--src/librustc_incremental/lib.rs1
-rw-r--r--src/librustc_incremental/persist/hash.rs5
-rw-r--r--src/librustc_incremental/persist/load.rs5
-rw-r--r--src/librustc_incremental/persist/save.rs2
-rw-r--r--src/librustc_metadata/Cargo.toml1
-rw-r--r--src/librustc_metadata/astencode.rs2
-rw-r--r--src/librustc_metadata/common.rs9
-rw-r--r--src/librustc_metadata/csearch.rs21
-rw-r--r--src/librustc_metadata/decoder.rs59
-rw-r--r--src/librustc_metadata/encoder.rs244
-rw-r--r--src/librustc_metadata/index.rs6
-rw-r--r--src/librustc_metadata/index_builder.rs13
-rw-r--r--src/librustc_metadata/lib.rs3
-rw-r--r--src/librustc_metadata/rbml/reader.rs595
-rw-r--r--src/librustc_metadata/rbml/writer.rs379
-rw-r--r--src/librustc_metadata/tydecode.rs2
-rw-r--r--src/librustc_metadata/tyencode.rs5
-rw-r--r--src/librustc_trans/base.rs3
-rw-r--r--src/libserialize/leb128.rs (renamed from src/librbml/leb128.rs)0
-rw-r--r--src/libserialize/lib.rs3
-rw-r--r--src/libserialize/opaque.rs (renamed from src/librbml/opaque.rs)260
-rw-r--r--src/libserialize/serialize.rs194
-rw-r--r--src/rustc/Cargo.lock11
-rw-r--r--src/test/run-pass-fulldeps/issue-11881.rs6
32 files changed, 411 insertions, 1516 deletions
diff --git a/mk/crates.mk b/mk/crates.mk
index d2c79441d86..86bb3a8ca0c 100644
--- a/mk/crates.mk
+++ b/mk/crates.mk
@@ -61,7 +61,7 @@ RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_
                 rustc_plugin rustc_metadata rustc_passes rustc_save_analysis \
                 rustc_const_eval rustc_const_math rustc_incremental rustc_macro
 HOST_CRATES := syntax syntax_ext proc_macro syntax_pos $(RUSTC_CRATES) rustdoc fmt_macros \
-		flate arena graphviz rbml log serialize
+		flate arena graphviz log serialize
 TOOLS := compiletest rustdoc rustc rustbook error_index_generator
 
 DEPS_core :=
@@ -96,7 +96,6 @@ DEPS_getopts := std
 DEPS_graphviz := std
 DEPS_log := std
 DEPS_num := std
-DEPS_rbml := std log serialize
 DEPS_serialize := std log
 DEPS_term := std
 DEPS_test := std getopts term native:rust_test_helpers
@@ -110,7 +109,7 @@ DEPS_rustc_const_math := std syntax log serialize
 DEPS_rustc_const_eval := rustc_const_math rustc syntax log serialize \
 			     rustc_back graphviz syntax_pos
 
-DEPS_rustc := syntax fmt_macros flate arena serialize getopts rbml \
+DEPS_rustc := syntax fmt_macros flate arena serialize getopts \
               log graphviz rustc_llvm rustc_back rustc_data_structures\
 	      rustc_const_math syntax_pos rustc_errors
 DEPS_rustc_back := std syntax flate log libc
@@ -126,7 +125,7 @@ DEPS_rustc_errors := log libc serialize syntax_pos
 DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval
 DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
 DEPS_rustc_macro := std syntax
-DEPS_rustc_metadata := rustc syntax syntax_pos rustc_errors rbml rustc_const_math \
+DEPS_rustc_metadata := rustc syntax syntax_pos rustc_errors rustc_const_math \
 			rustc_macro syntax_ext
 DEPS_rustc_passes := syntax syntax_pos rustc core rustc_const_eval rustc_errors
 DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags
@@ -137,7 +136,7 @@ DEPS_rustc_privacy := rustc log syntax syntax_pos
 DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
                     log syntax serialize rustc_llvm rustc_platform_intrinsics \
                     rustc_const_math rustc_const_eval rustc_incremental rustc_errors syntax_pos
-DEPS_rustc_incremental := rbml rustc syntax_pos serialize rustc_data_structures
+DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures
 DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize
 DEPS_rustc_typeck := rustc syntax syntax_pos rustc_platform_intrinsics rustc_const_math \
                      rustc_const_eval rustc_errors
diff --git a/mk/tests.mk b/mk/tests.mk
index c135aa9b8fb..fc1f4b5561a 100644
--- a/mk/tests.mk
+++ b/mk/tests.mk
@@ -27,7 +27,7 @@ TEST_TARGET_CRATES = $(filter-out core rustc_unicode alloc_system libc \
 				  panic_abort,$(TARGET_CRATES)) \
 			collectionstest coretest
 TEST_DOC_CRATES = $(DOC_CRATES) arena flate fmt_macros getopts graphviz \
-                log rand rbml serialize syntax term test
+                log rand serialize syntax term test
 TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve \
 		   		rustc_trans rustc_lint,\
                      $(HOST_CRATES))
diff --git a/src/librbml/Cargo.toml b/src/librbml/Cargo.toml
deleted file mode 100644
index ab89ac2b7a1..00000000000
--- a/src/librbml/Cargo.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-name = "rbml"
-version = "0.0.0"
-
-[lib]
-name = "rbml"
-path = "lib.rs"
-crate-type = ["dylib"]
-
-[dependencies]
-log = { path = "../liblog" }
-serialize = { path = "../libserialize" }
diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs
deleted file mode 100644
index 65259f903a9..00000000000
--- a/src/librbml/lib.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2012-2015 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.
-
-//! Skeleton of RBML (Really Bad Markup Language).
-//! See `src/librustc_metadata/reader.rs` for more details.
-
-#![crate_name = "rbml"]
-#![unstable(feature = "rustc_private", issue = "27812")]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
-#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
-       html_root_url = "https://doc.rust-lang.org/nightly/",
-       html_playground_url = "https://play.rust-lang.org/",
-       test(attr(deny(warnings))))]
-#![cfg_attr(not(stage0), deny(warnings))]
-
-#![feature(rustc_private)]
-#![feature(staged_api)]
-#![feature(question_mark)]
-
-#![cfg_attr(test, feature(test))]
-
-extern crate serialize;
-
-#[cfg(test)]
-extern crate serialize as rustc_serialize; // Used by RustcEncodable
-
-#[macro_use]
-extern crate log;
-
-#[cfg(test)]
-extern crate test;
-
-pub mod opaque;
-pub mod leb128;
-
-pub use self::Error::*;
-
-use std::fmt;
-
-#[derive(Debug)]
-pub enum Error {
-    IntTooBig(usize),
-    InvalidTag(usize),
-    Expected(String),
-    IoError(std::io::Error),
-    ApplicationError(String),
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        // FIXME: this should be a more useful display form
-        fmt::Debug::fmt(self, f)
-    }
-}
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index aaef8e8423c..578ef68b003 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -14,7 +14,6 @@ flate = { path = "../libflate" }
 fmt_macros = { path = "../libfmt_macros" }
 graphviz = { path = "../libgraphviz" }
 log = { path = "../liblog" }
-rbml = { path = "../librbml" }
 rustc_back = { path = "../librustc_back" }
 rustc_bitflags = { path = "../librustc_bitflags" }
 rustc_const_math = { path = "../librustc_const_math" }
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index d2a2f8a972d..c34286f0195 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -50,7 +50,6 @@ extern crate fmt_macros;
 extern crate getopts;
 extern crate graphviz;
 extern crate libc;
-extern crate rbml;
 extern crate rustc_llvm as llvm;
 extern crate rustc_back;
 extern crate rustc_data_structures;
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 513fa30861a..1d6047579f6 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -265,8 +265,7 @@ pub trait CrateStore<'tcx> {
                            reexports: &def::ExportMap,
                            link_meta: &LinkMeta,
                            reachable: &NodeSet,
-                           mir_map: &MirMap<'tcx>,
-                           krate: &hir::Crate) -> Vec<u8>;
+                           mir_map: &MirMap<'tcx>) -> Vec<u8>;
     fn metadata_encoding_version(&self) -> &[u8];
 }
 
@@ -472,8 +471,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
                            reexports: &def::ExportMap,
                            link_meta: &LinkMeta,
                            reachable: &NodeSet,
-                           mir_map: &MirMap<'tcx>,
-                           krate: &hir::Crate) -> Vec<u8> { vec![] }
+                           mir_map: &MirMap<'tcx>) -> Vec<u8> { vec![] }
     fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
 }
 
diff --git a/src/librustc_incremental/Cargo.toml b/src/librustc_incremental/Cargo.toml
index 7db1a6348b2..e3ee7527545 100644
--- a/src/librustc_incremental/Cargo.toml
+++ b/src/librustc_incremental/Cargo.toml
@@ -10,10 +10,9 @@ crate-type = ["dylib"]
 
 [dependencies]
 graphviz = { path = "../libgraphviz" }
-rbml = { path = "../librbml" }
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 serialize = { path = "../libserialize" }
 log = { path = "../liblog" }
 syntax = { path = "../libsyntax" }
-syntax_pos = { path = "../libsyntax_pos" }
\ No newline at end of file
+syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs
index 1f823eedda0..42b5657e212 100644
--- a/src/librustc_incremental/lib.rs
+++ b/src/librustc_incremental/lib.rs
@@ -27,7 +27,6 @@
 #![feature(core_intrinsics)]
 
 extern crate graphviz;
-extern crate rbml;
 #[macro_use] extern crate rustc;
 extern crate rustc_data_structures;
 extern crate serialize as rustc_serialize;
diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs
index 6dcf2c28891..5a4716e45f6 100644
--- a/src/librustc_incremental/persist/hash.rs
+++ b/src/librustc_incremental/persist/hash.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rbml::Error;
-use rbml::opaque::Decoder;
 use rustc::dep_graph::DepNode;
 use rustc::hir::def_id::{CrateNum, DefId};
 use rustc::hir::svh::Svh;
@@ -17,6 +15,7 @@ use rustc::ty::TyCtxt;
 use rustc_data_structures::fnv::FnvHashMap;
 use rustc_data_structures::flock;
 use rustc_serialize::Decodable;
+use rustc_serialize::opaque::Decoder;
 use std::io::{ErrorKind, Read};
 use std::fs::File;
 
@@ -188,7 +187,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
     fn load_from_data(&mut self,
                       cnum: CrateNum,
                       data: &[u8],
-                      expected_svh: Svh) -> Result<(), Error> {
+                      expected_svh: Svh) -> Result<(), String> {
         debug!("load_from_data(cnum={})", cnum);
 
         // Load up the hashes for the def-ids from this crate.
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index 6e6464e4968..b051e6c5ab7 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -10,14 +10,13 @@
 
 //! Code to save/load the dep-graph from files.
 
-use rbml::Error;
-use rbml::opaque::Decoder;
 use rustc::dep_graph::DepNode;
 use rustc::hir::def_id::DefId;
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fnv::FnvHashSet;
 use rustc_serialize::Decodable as RustcDecodable;
+use rustc_serialize::opaque::Decoder;
 use std::io::Read;
 use std::fs::{self, File};
 use std::path::{Path};
@@ -121,7 +120,7 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   incremental_hashes_map: &IncrementalHashesMap,
                                   dep_graph_data: &[u8],
                                   work_products_data: &[u8])
-                                  -> Result<(), Error>
+                                  -> Result<(), String>
 {
     // Decode the list of work_products
     let mut work_product_decoder = Decoder::new(work_products_data, 0);
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index 41212d8e138..5b45874840f 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rbml::opaque::Encoder;
 use rustc::dep_graph::DepNode;
 use rustc::hir::def_id::DefId;
 use rustc::hir::svh::Svh;
@@ -16,6 +15,7 @@ use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fnv::FnvHashMap;
 use rustc_serialize::Encodable as RustcEncodable;
+use rustc_serialize::opaque::Encoder;
 use std::hash::{Hash, Hasher, SipHasher};
 use std::io::{self, Cursor, Write};
 use std::fs::{self, File};
diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml
index d70510896b9..fede6f66341 100644
--- a/src/librustc_metadata/Cargo.toml
+++ b/src/librustc_metadata/Cargo.toml
@@ -11,7 +11,6 @@ crate-type = ["dylib"]
 [dependencies]
 flate = { path = "../libflate" }
 log = { path = "../liblog" }
-rbml = { path = "../librbml" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_bitflags = { path = "../librustc_bitflags" }
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index ce15ec6a29d..f00c4b82a85 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -217,7 +217,7 @@ fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) {
 }
 
 fn decode_side_tables(dcx: &mut DecodeContext, ast_doc: rbml::Doc) {
-    while dcx.position() < ast_doc.end {
+    while dcx.opaque.position() < ast_doc.end {
         let table = Decodable::decode(dcx).unwrap();
         let id = Decodable::decode(dcx).unwrap();
         debug!("decode_side_tables: entry for id={}, table={:?}", id, table);
diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs
index 512f4ca6584..3b63ee6b5fa 100644
--- a/src/librustc_metadata/common.rs
+++ b/src/librustc_metadata/common.rs
@@ -10,12 +10,9 @@
 
 #![allow(non_camel_case_types, non_upper_case_globals)]
 
-// RBML enum definitions and utils shared by the encoder and decoder
-//
-// 0x00..0x1f: reserved for RBML generic type tags
-// 0x20..0xef: free for use, preferred for frequent tags
-// 0xf0..0xff: internally used by RBML to encode 0x100..0xfff in two bytes
-// 0x100..0xfff: free for use, preferred for infrequent tags
+pub const tag_opaque: usize = 0x00;
+
+// GAP 0x01...0x19
 
 pub const tag_items: usize = 0x100; // top-level only
 
diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs
index aae87005bf4..b291c4927aa 100644
--- a/src/librustc_metadata/csearch.rs
+++ b/src/librustc_metadata/csearch.rs
@@ -13,7 +13,6 @@ use common;
 use decoder;
 use encoder;
 use loader;
-use rbml;
 
 use middle::cstore::{InlinedItem, CrateStore, CrateSource, ChildItem, ExternCrate, DefLike};
 use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference};
@@ -30,7 +29,6 @@ use rustc::mir::mir_map::MirMap;
 use rustc::util::nodemap::{FnvHashMap, NodeSet, DefIdMap};
 use rustc::session::config::PanicStrategy;
 
-use std::cell::RefCell;
 use std::rc::Rc;
 use std::path::PathBuf;
 use syntax::ast;
@@ -697,22 +695,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
                            reexports: &def::ExportMap,
                            link_meta: &LinkMeta,
                            reachable: &NodeSet,
-                           mir_map: &MirMap<'tcx>,
-                           krate: &hir::Crate) -> Vec<u8>
-    {
-        let type_abbrevs = RefCell::new(FnvHashMap());
-        let ecx = encoder::EncodeContext {
-            rbml_w: rbml::writer::Encoder::new(),
-            tcx: tcx,
-            reexports: reexports,
-            link_meta: link_meta,
-            cstore: self,
-            reachable: reachable,
-            mir_map: mir_map,
-            type_abbrevs: &type_abbrevs,
-        };
-        encoder::encode_metadata(ecx, krate)
-
+                           mir_map: &MirMap<'tcx>) -> Vec<u8>
+    {
+        encoder::encode_metadata(tcx, self, reexports, link_meta, reachable, mir_map)
     }
 
     fn metadata_encoding_version(&self) -> &[u8]
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 1bec365e472..ba593e5be99 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -45,14 +45,14 @@ use rustc_const_math::ConstInt;
 use rustc::mir::repr::Mir;
 
 use std::io;
-use std::ops::{Deref, DerefMut};
 use std::rc::Rc;
 use std::str;
 use std::u32;
 
 use rbml::reader;
 use rbml;
-use rustc_serialize::{Decodable, SpecializedDecoder};
+use rustc_serialize::{Decodable, SpecializedDecoder, opaque};
+use rustc_serialize as serialize;
 use syntax::attr;
 use syntax::parse::token;
 use syntax::ast::{self, NodeId};
@@ -60,7 +60,7 @@ use syntax::print::pprust;
 use syntax_pos::{self, Span, BytePos, NO_EXPANSION};
 
 pub struct DecodeContext<'a, 'tcx: 'a> {
-    rbml_r: rbml::reader::Decoder<'a>,
+    pub opaque: opaque::Decoder<'a>,
     pub tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
     pub cdata: Option<&'a cstore::CrateMetadata>,
     pub from_id_range: IdRange,
@@ -76,7 +76,7 @@ impl<'doc> rbml::Doc<'doc> {
             max: NodeId::from_u32(u32::MAX)
         };
         DecodeContext {
-            rbml_r: reader::Decoder::new(self),
+            opaque: opaque::Decoder::new(self.data, self.start),
             cdata: None,
             tcx: None,
             from_id_range: id_range,
@@ -98,24 +98,49 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
     fn read_ty_encoded<F, R>(&mut self, op: F) -> R
         where F: for<'x> FnOnce(&mut TyDecoder<'x,'tcx>) -> R
     {
-        self.read_opaque(|this, doc| {
-            Ok(op(&mut TyDecoder::with_doc(
-                this.tcx(), this.cdata().cnum, doc,
-                &mut |d| translate_def_id(this.cdata(), d))))
-        }).unwrap()
+        let pos = self.opaque.position();
+        let doc = rbml::Doc::at(self.opaque.data, pos);
+        self.opaque.advance(doc.end - pos);
+        op(&mut TyDecoder::with_doc(self.tcx(), self.cdata().cnum, doc,
+                                    &mut |d| translate_def_id(self.cdata(), d)))
     }
 }
 
-impl<'a, 'tcx> Deref for DecodeContext<'a, 'tcx> {
-    type Target = rbml::reader::Decoder<'a>;
-    fn deref(&self) -> &Self::Target {
-        &self.rbml_r
+macro_rules! decoder_methods {
+    ($($name:ident -> $ty:ty;)*) => {
+        $(fn $name(&mut self) -> Result<$ty, Self::Error> {
+            self.opaque.$name()
+        })*
     }
 }
 
-impl<'a, 'tcx> DerefMut for DecodeContext<'a, 'tcx> {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        &mut self.rbml_r
+impl<'doc, 'tcx> serialize::Decoder for ::decoder::DecodeContext<'doc, 'tcx> {
+    type Error = <opaque::Decoder<'doc> as serialize::Decoder>::Error;
+
+    decoder_methods! {
+        read_nil -> ();
+
+        read_u64 -> u64;
+        read_u32 -> u32;
+        read_u16 -> u16;
+        read_u8 -> u8;
+        read_usize -> usize;
+
+        read_i64 -> i64;
+        read_i32 -> i32;
+        read_i16 -> i16;
+        read_i8 -> i8;
+        read_isize -> isize;
+
+        read_bool -> bool;
+        read_f64 -> f64;
+        read_f32 -> f32;
+        read_char -> char;
+        read_str -> String;
+    }
+
+    fn error(&mut self, err: &str) -> Self::Error {
+        self.opaque.error(err)
     }
 }
 
@@ -256,7 +281,7 @@ pub type Cmd<'a> = &'a CrateMetadata;
 impl CrateMetadata {
     fn get_item(&self, item_id: DefIndex) -> Option<rbml::Doc> {
         self.index.lookup_item(self.data(), item_id).map(|pos| {
-            reader::doc_at(self.data(), pos as usize).unwrap().doc
+            rbml::Doc::at(self.data(), pos as usize)
         })
     }
 
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 409982289d8..4b603fcb105 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -35,9 +35,10 @@ use rustc::mir::mir_map::MirMap;
 use rustc::session::config::{self, PanicStrategy, CrateTypeRustcMacro};
 use rustc::util::nodemap::{FnvHashMap, NodeSet};
 
-use rustc_serialize::{Encodable, SpecializedEncoder};
+use rustc_serialize::{Encodable, SpecializedEncoder, opaque};
+use rustc_serialize as serialize;
 use std::io::prelude::*;
-use std::io::SeekFrom;
+use std::io::Cursor;
 use std::ops::{Deref, DerefMut};
 use std::rc::Rc;
 use std::u32;
@@ -55,7 +56,7 @@ use rustc::hir::map::DefKey;
 use super::index_builder::{FromId, IndexBuilder, ItemContentBuilder, Untracked, XRef};
 
 pub struct EncodeContext<'a, 'tcx: 'a> {
-    pub rbml_w: rbml::writer::Encoder,
+    pub rbml_w: rbml::writer::Encoder<'a>,
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub reexports: &'a def::ExportMap,
     pub link_meta: &'a LinkMeta,
@@ -66,7 +67,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> Deref for EncodeContext<'a, 'tcx> {
-    type Target = rbml::writer::Encoder;
+    type Target = rbml::writer::Encoder<'a>;
     fn deref(&self) -> &Self::Target {
         &self.rbml_w
     }
@@ -78,21 +79,61 @@ impl<'a, 'tcx> DerefMut for EncodeContext<'a, 'tcx> {
     }
 }
 
+macro_rules! encoder_methods {
+    ($($name:ident($ty:ty);)*) => {
+        $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
+            self.opaque.$name(value)
+        })*
+    }
+}
+
+impl<'a, 'tcx> serialize::Encoder for ::encoder::EncodeContext<'a, 'tcx> {
+    type Error = <opaque::Encoder<'a> as serialize::Encoder>::Error;
+
+    fn emit_nil(&mut self) -> Result<(), Self::Error> {
+        Ok(())
+    }
+
+    encoder_methods! {
+        emit_usize(usize);
+        emit_u64(u64);
+        emit_u32(u32);
+        emit_u16(u16);
+        emit_u8(u8);
+
+        emit_isize(isize);
+        emit_i64(i64);
+        emit_i32(i32);
+        emit_i16(i16);
+        emit_i8(i8);
+
+        emit_bool(bool);
+        emit_f64(f64);
+        emit_f32(f32);
+        emit_char(char);
+        emit_str(&str);
+    }
+}
+
 impl<'a, 'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'a, 'tcx> {
     fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
         let cx = self.ty_str_ctxt();
-        self.emit_opaque(|opaque_encoder| {
-            Ok(tyencode::enc_ty(opaque_encoder.cursor, &cx, ty))
-        })
+
+        self.start_tag(tag_opaque)?;
+        tyencode::enc_ty(&mut self.rbml_w.opaque.cursor, &cx, ty);
+        self.mark_stable_position();
+        self.end_tag()
     }
 }
 
 impl<'a, 'tcx> SpecializedEncoder<&'tcx Substs<'tcx>> for EncodeContext<'a, 'tcx> {
     fn specialized_encode(&mut self, substs: &&'tcx Substs<'tcx>) -> Result<(), Self::Error> {
         let cx = self.ty_str_ctxt();
-        self.emit_opaque(|opaque_encoder| {
-            Ok(tyencode::enc_substs(opaque_encoder.cursor, &cx, substs))
-        })
+
+        self.start_tag(tag_opaque)?;
+        tyencode::enc_substs(&mut self.rbml_w.opaque.cursor, &cx, substs);
+        self.mark_stable_position();
+        self.end_tag()
     }
 }
 
@@ -124,7 +165,7 @@ fn encode_trait_ref<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>,
                               tag: usize) {
     let cx = ecx.ty_str_ctxt();
     ecx.start_tag(tag);
-    tyencode::enc_trait_ref(&mut ecx.writer, &cx, trait_ref);
+    tyencode::enc_trait_ref(&mut ecx.opaque.cursor, &cx, trait_ref);
     ecx.mark_stable_position();
     ecx.end_tag();
 }
@@ -173,7 +214,7 @@ fn encode_variant_id(ecx: &mut EncodeContext, vid: DefId) {
 fn write_closure_type<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>,
                                 closure_type: &ty::ClosureTy<'tcx>) {
     let cx = ecx.ty_str_ctxt();
-    tyencode::enc_closure_ty(&mut ecx.writer, &cx, closure_type);
+    tyencode::enc_closure_ty(&mut ecx.opaque.cursor, &cx, closure_type);
     ecx.mark_stable_position();
 }
 
@@ -181,7 +222,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> {
     fn encode_type(&mut self, typ: Ty<'tcx>) {
         let cx = self.ty_str_ctxt();
         self.start_tag(tag_items_data_item_type);
-        tyencode::enc_ty(&mut self.writer, &cx, typ);
+        tyencode::enc_ty(&mut self.opaque.cursor, &cx, typ);
         self.mark_stable_position();
         self.end_tag();
     }
@@ -480,7 +521,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> {
     {
         let cx = self.ty_str_ctxt();
         self.start_tag(tag_item_generics);
-        tyencode::enc_generics(&mut self.writer, &cx, generics);
+        tyencode::enc_generics(&mut self.opaque.cursor, &cx, generics);
         self.mark_stable_position();
         self.end_tag();
         self.encode_predicates(predicates, tag_item_predicates);
@@ -829,7 +870,7 @@ fn encode_xrefs<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>,
         xref_positions[id as usize] = ecx.mark_stable_position() as u32;
         match xref {
             XRef::Predicate(p) => {
-                tyencode::enc_predicate(&mut ecx.writer, &cx, &p)
+                tyencode::enc_predicate(&mut ecx.opaque.cursor, &cx, &p)
             }
         }
     }
@@ -837,7 +878,7 @@ fn encode_xrefs<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>,
     ecx.end_tag();
 
     ecx.start_tag(tag_xref_index);
-    index::write_dense_index(xref_positions, &mut ecx.writer);
+    index::write_dense_index(xref_positions, &mut ecx.opaque.cursor);
     ecx.end_tag();
 }
 
@@ -1396,7 +1437,7 @@ fn encode_info_for_items<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>)
 
 fn encode_item_index(ecx: &mut EncodeContext, index: IndexData) {
     ecx.start_tag(tag_index);
-    index.write_index(&mut ecx.writer);
+    index.write_index(&mut ecx.opaque.cursor);
     ecx.end_tag();
 }
 
@@ -1710,15 +1751,33 @@ fn encode_panic_strategy(ecx: &mut EncodeContext) {
     }
 }
 
-pub fn encode_metadata(mut ecx: EncodeContext, krate: &hir::Crate) -> Vec<u8> {
-    encode_metadata_inner(&mut ecx, krate);
+pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                 cstore: &cstore::CStore,
+                                 reexports: &def::ExportMap,
+                                 link_meta: &LinkMeta,
+                                 reachable: &NodeSet,
+                                 mir_map: &MirMap<'tcx>) -> Vec<u8> {
+    let mut cursor = Cursor::new(vec![]);
+    cursor.write_all(&[0, 0, 0, 0]).unwrap();
+    cursor.write_all(metadata_encoding_version).unwrap();
+    // Will be filed with the length after encoding the crate.
+    cursor.write_all(&[0, 0, 0, 0]).unwrap();
+
+    encode_metadata_inner(&mut EncodeContext {
+        rbml_w: rbml::writer::Encoder::new(&mut cursor),
+        tcx: tcx,
+        reexports: reexports,
+        link_meta: link_meta,
+        cstore: cstore,
+        reachable: reachable,
+        mir_map: mir_map,
+        type_abbrevs: &Default::default(),
+    });
 
     // RBML compacts the encoded bytes whenever appropriate,
     // so there are some garbages left after the end of the data.
-    let metalen = ecx.rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() as usize;
-    let mut v = ecx.rbml_w.writer.into_inner();
-    v.truncate(metalen);
-    assert_eq!(v.len(), metalen);
+    let meta_len = cursor.position() as usize;
+    cursor.get_mut().truncate(meta_len);
 
     // And here we run into yet another obscure archive bug: in which metadata
     // loaded from archives may have trailing garbage bytes. Awhile back one of
@@ -1744,55 +1803,17 @@ pub fn encode_metadata(mut ecx: EncodeContext, krate: &hir::Crate) -> Vec<u8> {
     // this metadata, there are 4 zero bytes at the start, which are
     // treated as a length of 0 by old compilers.
 
-    let len = v.len();
-    let mut result = vec![];
-    result.push(0);
-    result.push(0);
-    result.push(0);
-    result.push(0);
-    result.extend(metadata_encoding_version.iter().cloned());
-    result.push((len >> 24) as u8);
-    result.push((len >> 16) as u8);
-    result.push((len >>  8) as u8);
-    result.push((len >>  0) as u8);
-    result.extend(v);
+    let meta_start = 8 + ::common::metadata_encoding_version.len();
+    let len = meta_len - meta_start;
+    let mut result = cursor.into_inner();
+    result[meta_start - 4] = (len >> 24) as u8;
+    result[meta_start - 3] = (len >> 16) as u8;
+    result[meta_start - 2] = (len >>  8) as u8;
+    result[meta_start - 1] = (len >>  0) as u8;
     result
 }
 
-fn encode_metadata_inner(ecx: &mut EncodeContext, krate: &hir::Crate) {
-    struct Stats {
-        attr_bytes: u64,
-        dep_bytes: u64,
-        lang_item_bytes: u64,
-        native_lib_bytes: u64,
-        plugin_registrar_fn_bytes: u64,
-        codemap_bytes: u64,
-        macro_defs_bytes: u64,
-        impl_bytes: u64,
-        reachable_bytes: u64,
-        item_bytes: u64,
-        index_bytes: u64,
-        xref_bytes: u64,
-        zero_bytes: u64,
-        total_bytes: u64,
-    }
-    let mut stats = Stats {
-        attr_bytes: 0,
-        dep_bytes: 0,
-        lang_item_bytes: 0,
-        native_lib_bytes: 0,
-        plugin_registrar_fn_bytes: 0,
-        codemap_bytes: 0,
-        macro_defs_bytes: 0,
-        impl_bytes: 0,
-        reachable_bytes: 0,
-        item_bytes: 0,
-        index_bytes: 0,
-        xref_bytes: 0,
-        zero_bytes: 0,
-        total_bytes: 0,
-    };
-
+fn encode_metadata_inner(ecx: &mut EncodeContext) {
     encode_rustc_version(ecx);
 
     let tcx = ecx.tcx;
@@ -1804,89 +1825,92 @@ fn encode_metadata_inner(ecx: &mut EncodeContext, krate: &hir::Crate) {
     encode_dylib_dependency_formats(ecx);
     encode_panic_strategy(ecx);
 
-    let mut i = ecx.writer.seek(SeekFrom::Current(0)).unwrap();
+    let krate = tcx.map.krate();
+
+    let mut i = ecx.position();
     encode_attributes(ecx, &krate.attrs);
-    stats.attr_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i;
+    let attr_bytes = ecx.position() - i;
 
-    i = ecx.writer.seek(SeekFrom::Current(0)).unwrap();
+    i = ecx.position();
     encode_crate_deps(ecx, ecx.cstore);
-    stats.dep_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i;
+    let dep_bytes = ecx.position() - i;
 
     // Encode the language items.
-    i = ecx.writer.seek(SeekFrom::Current(0)).unwrap();
+    i = ecx.position();
     encode_lang_items(ecx);
-    stats.lang_item_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i;
+    let lang_item_bytes = ecx.position() - i;
 
     // Encode the native libraries used
-    i = ecx.writer.seek(SeekFrom::Current(0)).unwrap();
+    i = ecx.position();
     encode_native_libraries(ecx);
-    stats.native_lib_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i;
+    let native_lib_bytes = ecx.position() - i;
 
     // Encode the plugin registrar function
-    i = ecx.writer.seek(SeekFrom::Current(0)).unwrap();
+    i = ecx.position();
     encode_plugin_registrar_fn(ecx);
-    stats.plugin_registrar_fn_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i;
+    let plugin_registrar_fn_bytes = ecx.position() - i;
 
     // Encode codemap
-    i = ecx.writer.seek(SeekFrom::Current(0)).unwrap();
+    i = ecx.position();
     encode_codemap(ecx);
-    stats.codemap_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i;
+    let codemap_bytes = ecx.position() - i;
 
     // Encode macro definitions
-    i = ecx.writer.seek(SeekFrom::Current(0)).unwrap();
+    i = ecx.position();
     encode_macro_defs(ecx, krate);
-    stats.macro_defs_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i;
+    let macro_defs_bytes = ecx.position() - i;
 
     // Encode the def IDs of impls, for coherence checking.
-    i = ecx.writer.seek(SeekFrom::Current(0)).unwrap();
+    i = ecx.position();
     encode_impls(ecx, krate);
-    stats.impl_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i;
+    let impl_bytes = ecx.position() - i;
 
     // Encode reachability info.
-    i = ecx.writer.seek(SeekFrom::Current(0)).unwrap();
+    i = ecx.position();
     encode_reachable(ecx);
-    stats.reachable_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i;
+    let reachable_bytes = ecx.position() - i;
 
     // Encode and index the items.
     ecx.start_tag(tag_items);
-    i = ecx.writer.seek(SeekFrom::Current(0)).unwrap();
+    i = ecx.position();
     let (items, xrefs) = encode_info_for_items(ecx);
-    stats.item_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i;
+    let item_bytes = ecx.position() - i;
     ecx.end_tag();
 
-    i = ecx.writer.seek(SeekFrom::Current(0)).unwrap();
+    i = ecx.position();
     encode_item_index(ecx, items);
-    stats.index_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i;
+    let index_bytes = ecx.position() - i;
 
-    i = ecx.writer.seek(SeekFrom::Current(0)).unwrap();
+    i = ecx.position();
     encode_xrefs(ecx, xrefs);
-    stats.xref_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i;
+    let xref_bytes = ecx.position() - i;
 
     encode_struct_field_attrs(ecx, krate);
 
-    stats.total_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap();
+    let total_bytes = ecx.position();
 
     if ecx.tcx.sess.meta_stats() {
-        for e in ecx.writer.get_ref() {
+        let mut zero_bytes = 0;
+        for e in ecx.opaque.cursor.get_ref() {
             if *e == 0 {
-                stats.zero_bytes += 1;
+                zero_bytes += 1;
             }
         }
 
         println!("metadata stats:");
-        println!("       attribute bytes: {}", stats.attr_bytes);
-        println!("             dep bytes: {}", stats.dep_bytes);
-        println!("       lang item bytes: {}", stats.lang_item_bytes);
-        println!("          native bytes: {}", stats.native_lib_bytes);
-        println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
-        println!("         codemap bytes: {}", stats.codemap_bytes);
-        println!("       macro def bytes: {}", stats.macro_defs_bytes);
-        println!("            impl bytes: {}", stats.impl_bytes);
-        println!("       reachable bytes: {}", stats.reachable_bytes);
-        println!("            item bytes: {}", stats.item_bytes);
-        println!("           index bytes: {}", stats.index_bytes);
-        println!("            xref bytes: {}", stats.xref_bytes);
-        println!("            zero bytes: {}", stats.zero_bytes);
-        println!("           total bytes: {}", stats.total_bytes);
+        println!("       attribute bytes: {}", attr_bytes);
+        println!("             dep bytes: {}", dep_bytes);
+        println!("       lang item bytes: {}", lang_item_bytes);
+        println!("          native bytes: {}", native_lib_bytes);
+        println!("plugin registrar bytes: {}", plugin_registrar_fn_bytes);
+        println!("         codemap bytes: {}", codemap_bytes);
+        println!("       macro def bytes: {}", macro_defs_bytes);
+        println!("            impl bytes: {}", impl_bytes);
+        println!("       reachable bytes: {}", reachable_bytes);
+        println!("            item bytes: {}", item_bytes);
+        println!("           index bytes: {}", index_bytes);
+        println!("            xref bytes: {}", xref_bytes);
+        println!("            zero bytes: {}", zero_bytes);
+        println!("           total bytes: {}", total_bytes);
     }
 }
diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs
index b850073462f..63d7f1b58bb 100644
--- a/src/librustc_metadata/index.rs
+++ b/src/librustc_metadata/index.rs
@@ -73,15 +73,15 @@ impl IndexData {
         }
     }
 
-    pub fn record(&mut self, def_id: DefId, position: u64) {
+    pub fn record(&mut self, def_id: DefId, position: usize) {
         assert!(def_id.is_local());
         self.record_index(def_id.index, position);
     }
 
-    pub fn record_index(&mut self, item: DefIndex, position: u64) {
+    pub fn record_index(&mut self, item: DefIndex, position: usize) {
         let item = item.as_usize();
 
-        assert!(position < (u32::MAX as u64));
+        assert!(position < (u32::MAX as usize));
         let position = position as u32;
 
         assert!(self.positions[item] == u32::MAX,
diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs
index de2f1c4fb0c..fd25128575f 100644
--- a/src/librustc_metadata/index_builder.rs
+++ b/src/librustc_metadata/index_builder.rs
@@ -28,10 +28,9 @@
 //! incremental compilation purposes.
 //!
 //! The `IndexBuilder` facilitates both of these. It is created
-//! with an RBML encoder isntance (`rbml_w`) along with an
-//! `EncodingContext` (`ecx`), which it encapsulates. It has one main
-//! method, `record()`. You invoke `record` like so to create a new
-//! `data_item` element in the list:
+//! with an `EncodingContext` (`ecx`), which it encapsulates.
+//! It has one main method, `record()`. You invoke `record`
+//! like so to create a new `data_item` element in the list:
 //!
 //! ```
 //! index.record(some_def_id, callback_fn, data)
@@ -43,9 +42,9 @@
 //! returns, the `common::data_item` tag will be closed.
 //!
 //! The `ItemContentBuilder` is another type that just offers access
-//! to the `ecx` and `rbml_w` that were given in, as well as
-//! maintaining a list of `xref` instances, which are used to extract
-//! common data so it is not re-serialized.
+//! to the `ecx` that was given in, as well as maintaining a list of
+//! `xref` instances, which are used to extract common data so it is
+//! not re-serialized.
 //!
 //! `ItemContentBuilder` is a distinct type which does not offer the
 //! `record` method, so that we can ensure that `common::data_item` elements
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 428b33f2bfa..7205a88618f 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -51,9 +51,6 @@ extern crate rustc_const_math;
 extern crate test;
 
 pub mod rbml {
-    pub extern crate rbml as rbml_crate;
-    pub use self::rbml_crate::{Error, leb128, opaque};
-
     pub mod writer;
     pub mod reader;
     pub use self::reader::Doc;
diff --git a/src/librustc_metadata/rbml/reader.rs b/src/librustc_metadata/rbml/reader.rs
index d66ca38e624..9bbeb73ce3e 100644
--- a/src/librustc_metadata/rbml/reader.rs
+++ b/src/librustc_metadata/rbml/reader.rs
@@ -45,87 +45,13 @@
 //! **Data** can be either binary bytes or zero or more nested RBML documents.
 //! Nested documents cannot overflow, and should be entirely contained
 //! within a parent document.
-//!
-//! # Predefined Tags
-//!
-//! Most RBML tags are defined by the application.
-//! (For the rust object metadata, see also `rustc::metadata::common`.)
-//! RBML itself does define a set of predefined tags however,
-//! intended for the auto-serialization implementation.
-//!
-//! Predefined tags with an implicit length:
-//!
-//! - `U8`  (`00`): 1-byte unsigned integer.
-//! - `U16` (`01`): 2-byte big endian unsigned integer.
-//! - `U32` (`02`): 4-byte big endian unsigned integer.
-//! - `U64` (`03`): 8-byte big endian unsigned integer.
-//!   Any of `U*` tags can be used to encode primitive unsigned integer types,
-//!   as long as it is no greater than the actual size.
-//!   For example, `u8` can only be represented via the `U8` tag.
-//!
-//! - `I8`  (`04`): 1-byte signed integer.
-//! - `I16` (`05`): 2-byte big endian signed integer.
-//! - `I32` (`06`): 4-byte big endian signed integer.
-//! - `I64` (`07`): 8-byte big endian signed integer.
-//!   Similar to `U*` tags. Always uses two's complement encoding.
-//!
-//! - `Bool` (`08`): 1-byte boolean value, `00` for false and `01` for true.
-//!
-//! - `Char` (`09`): 4-byte big endian Unicode scalar value.
-//!   Surrogate pairs or out-of-bound values are invalid.
-//!
-//! - `F32` (`0a`): 4-byte big endian unsigned integer representing
-//!   IEEE 754 binary32 floating-point format.
-//! - `F64` (`0b`): 8-byte big endian unsigned integer representing
-//!   IEEE 754 binary64 floating-point format.
-//!
-//! - `Sub8`  (`0c`): 1-byte unsigned integer for supplementary information.
-//! - `Sub32` (`0d`): 4-byte unsigned integer for supplementary information.
-//!   Those two tags normally occur as the first subdocument of certain tags,
-//!   namely `Enum`, `Vec` and `Map`, to provide a variant or size information.
-//!   They can be used interchangeably.
-//!
-//! Predefined tags with an explicit length:
-//!
-//! - `Str` (`10`): A UTF-8-encoded string.
-//!
-//! - `Enum` (`11`): An enum.
-//!   The first subdocument should be `Sub*` tags with a variant ID.
-//!   Subsequent subdocuments, if any, encode variant arguments.
-//!
-//! - `Vec` (`12`): A vector (sequence).
-//! - `VecElt` (`13`): A vector element.
-//!   The first subdocument should be `Sub*` tags with the number of elements.
-//!   Subsequent subdocuments should be `VecElt` tag per each element.
-//!
-//! - `Map` (`14`): A map (associated array).
-//! - `MapKey` (`15`): A key part of the map entry.
-//! - `MapVal` (`16`): A value part of the map entry.
-//!   The first subdocument should be `Sub*` tags with the number of entries.
-//!   Subsequent subdocuments should be an alternating sequence of
-//!   `MapKey` and `MapVal` tags per each entry.
-//!
-//! - `Opaque` (`17`): An opaque, custom-format tag.
-//!   Used to wrap ordinary custom tags or data in the auto-serialized context.
-//!   Rustc typically uses this to encode type information.
-//!
-//! First 0x20 tags are reserved by RBML; custom tags start at 0x20.
 
 #[cfg(test)]
 use test::Bencher;
 
-pub use self::EbmlEncoderTag::*;
-
-use std::char;
-use std::isize;
-use std::mem::transmute;
+use std::fmt;
 use std::str;
 
-use rustc_serialize as serialize;
-
-use rbml::Error;
-use rbml::Error::*;
-
 #[derive(Clone, Copy)]
 pub struct Doc<'a> {
     pub data: &'a [u8],
@@ -142,6 +68,17 @@ impl<'doc> Doc<'doc> {
         }
     }
 
+    pub fn at(data: &'doc [u8], start: usize) -> Doc<'doc> {
+        let elt_tag = tag_at(data, start).unwrap();
+        let elt_size = tag_len_at(data, elt_tag.next).unwrap();
+        let end = elt_size.next + elt_size.val;
+        Doc {
+            data: data,
+            start: elt_size.next,
+            end: end,
+        }
+    }
+
     pub fn get(&self, tag: usize) -> Doc<'doc> {
         get_doc(*self, tag)
     }
@@ -159,54 +96,19 @@ impl<'doc> Doc<'doc> {
     }
 }
 
-pub struct TaggedDoc<'a> {
-    tag: usize,
-    pub doc: Doc<'a>,
+#[derive(Debug)]
+pub enum Error {
+    IntTooBig(usize),
+    InvalidTag(usize)
 }
 
-pub type DecodeResult<T> = Result<T, Error>;
-
-#[derive(Copy, Clone, Debug)]
-pub enum EbmlEncoderTag {
-    // tags 00..1f are reserved for auto-serialization.
-    // first NUM_IMPLICIT_TAGS tags are implicitly sized and lengths are not encoded.
-    EsU8 = 0x00, // + 1 byte
-    EsU16 = 0x01, // + 2 bytes
-    EsU32 = 0x02, // + 4 bytes
-    EsU64 = 0x03, // + 8 bytes
-    EsI8 = 0x04, // + 1 byte
-    EsI16 = 0x05, // + 2 bytes
-    EsI32 = 0x06, // + 4 bytes
-    EsI64 = 0x07, // + 8 bytes
-    EsBool = 0x08, // + 1 byte
-    EsChar = 0x09, // + 4 bytes
-    EsF32 = 0x0a, // + 4 bytes
-    EsF64 = 0x0b, // + 8 bytes
-    EsSub8 = 0x0c, // + 1 byte
-    EsSub32 = 0x0d, // + 4 bytes
-    // 0x0e and 0x0f are reserved
-    EsStr = 0x10,
-    EsEnum = 0x11, // encodes the variant id as the first EsSub*
-    EsVec = 0x12, // encodes the # of elements as the first EsSub*
-    EsVecElt = 0x13,
-    EsMap = 0x14, // encodes the # of pairs as the first EsSub*
-    EsMapKey = 0x15,
-    EsMapVal = 0x16,
-    EsOpaque = 0x17,
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // FIXME: this should be a more useful display form
+        fmt::Debug::fmt(self, f)
+    }
 }
 
-pub const NUM_IMPLICIT_TAGS: usize = 0x0e;
-
-#[cfg_attr(rustfmt, rustfmt_skip)]
-static TAG_IMPLICIT_LEN: [i8; NUM_IMPLICIT_TAGS] = [
-    1, 2, 4, 8, // EsU*
-    1, 2, 4, 8, // ESI*
-    1, // EsBool
-    4, // EsChar
-    4, 8, // EsF*
-    1, 4, // EsSub*
-];
-
 // rbml reading
 
 macro_rules! try_or {
@@ -227,7 +129,7 @@ pub struct Res {
     pub next: usize,
 }
 
-pub fn tag_at(data: &[u8], start: usize) -> DecodeResult<Res> {
+pub fn tag_at(data: &[u8], start: usize) -> Result<Res, Error> {
     let v = data[start] as usize;
     if v < 0xf0 {
         Ok(Res {
@@ -241,12 +143,12 @@ pub fn tag_at(data: &[u8], start: usize) -> DecodeResult<Res> {
         })
     } else {
         // every tag starting with byte 0xf0 is an overlong form, which is prohibited.
-        Err(InvalidTag(v))
+        Err(Error::InvalidTag(v))
     }
 }
 
 #[inline(never)]
-fn vuint_at_slow(data: &[u8], start: usize) -> DecodeResult<Res> {
+fn vuint_at_slow(data: &[u8], start: usize) -> Result<Res, Error> {
     let a = data[start];
     if a & 0x80 != 0 {
         return Ok(Res {
@@ -275,10 +177,10 @@ fn vuint_at_slow(data: &[u8], start: usize) -> DecodeResult<Res> {
             next: start + 4,
         });
     }
-    Err(IntTooBig(a as usize))
+    Err(Error::IntTooBig(a as usize))
 }
 
-pub fn vuint_at(data: &[u8], start: usize) -> DecodeResult<Res> {
+pub fn vuint_at(data: &[u8], start: usize) -> Result<Res, Error> {
     if data.len() - start < 4 {
         return vuint_at_slow(data, start);
     }
@@ -332,36 +234,15 @@ pub fn vuint_at(data: &[u8], start: usize) -> DecodeResult<Res> {
     }
 }
 
-pub fn tag_len_at(data: &[u8], tag: Res) -> DecodeResult<Res> {
-    if tag.val < NUM_IMPLICIT_TAGS && TAG_IMPLICIT_LEN[tag.val] >= 0 {
-        Ok(Res {
-            val: TAG_IMPLICIT_LEN[tag.val] as usize,
-            next: tag.next,
-        })
-    } else {
-        vuint_at(data, tag.next)
-    }
-}
-
-pub fn doc_at<'a>(data: &'a [u8], start: usize) -> DecodeResult<TaggedDoc<'a>> {
-    let elt_tag = tag_at(data, start)?;
-    let elt_size = tag_len_at(data, elt_tag)?;
-    let end = elt_size.next + elt_size.val;
-    Ok(TaggedDoc {
-        tag: elt_tag.val,
-        doc: Doc {
-            data: data,
-            start: elt_size.next,
-            end: end,
-        },
-    })
+pub fn tag_len_at(data: &[u8], next: usize) -> Result<Res, Error> {
+    vuint_at(data, next)
 }
 
 pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: usize) -> Option<Doc<'a>> {
     let mut pos = d.start;
     while pos < d.end {
         let elt_tag = try_or!(tag_at(d.data, pos), None);
-        let elt_size = try_or!(tag_len_at(d.data, elt_tag), None);
+        let elt_size = try_or!(tag_len_at(d.data, elt_tag.next), None);
         pos = elt_size.next + elt_size.val;
         if elt_tag.val == tg {
             return Some(Doc {
@@ -378,8 +259,7 @@ pub fn get_doc<'a>(d: Doc<'a>, tg: usize) -> Doc<'a> {
     match maybe_get_doc(d, tg) {
         Some(d) => d,
         None => {
-            error!("failed to find block with tag {:?}", tg);
-            panic!();
+            bug!("failed to find block with tag {:?}", tg);
         }
     }
 }
@@ -404,7 +284,7 @@ impl<'a> Iterator for DocsIterator<'a> {
             self.d.start = self.d.end;
             None
         });
-        let elt_size = try_or!(tag_len_at(self.d.data, elt_tag), {
+        let elt_size = try_or!(tag_len_at(self.d.data, elt_tag.next), {
             self.d.start = self.d.end;
             None
         });
@@ -509,419 +389,6 @@ pub fn doc_as_i64(d: Doc) -> i64 {
     doc_as_u64(d) as i64
 }
 
-pub struct Decoder<'a> {
-    parent: Doc<'a>,
-    pos: usize,
-}
-
-impl<'doc> Decoder<'doc> {
-    pub fn new(d: Doc<'doc>) -> Decoder<'doc> {
-        Decoder {
-            parent: d,
-            pos: d.start,
-        }
-    }
-
-    fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<Doc<'doc>> {
-        debug!(". next_doc(exp_tag={:?})", exp_tag);
-        if self.pos >= self.parent.end {
-            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)?;
-        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 usize) {
-            return Err(Expected(format!("expected EBML doc with tag {:?} but found tag {:?}",
-                                        exp_tag,
-                                        r_tag)));
-        }
-        if 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;
-        Ok(r_doc)
-    }
-
-    fn _next_sub(&mut self) -> DecodeResult<usize> {
-        // empty vector/map optimization
-        if self.parent.is_empty() {
-            return Ok(0);
-        }
-
-        let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(self.parent.data, self.pos)?;
-        let r = if r_tag == (EsSub8 as usize) {
-            doc_as_u8(r_doc) as usize
-        } else if r_tag == (EsSub32 as usize) {
-            doc_as_u32(r_doc) as usize
-        } else {
-            return Err(Expected(format!("expected EBML doc with tag {:?} or {:?} but found \
-                                         tag {:?}",
-                                        EsSub8,
-                                        EsSub32,
-                                        r_tag)));
-        };
-        if 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;
-        debug!("_next_sub result={:?}", r);
-        Ok(r)
-    }
-
-    // variable-length unsigned integer with different tags.
-    // `last_tag` should be the largest allowed unsigned integer tag.
-    // all tags between them should be valid, in the order of u8, u16, u32 and u64.
-    fn next_uint(&mut self,
-                 last_tag: EbmlEncoderTag)
-                 -> DecodeResult<u64> {
-        if self.pos >= self.parent.end {
-            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)?;
-        let r = if EsU8 as usize <= r_tag && r_tag <= last_tag as usize {
-            match r_tag - EsU8 as usize {
-                0 => doc_as_u8(r_doc) as u64,
-                1 => doc_as_u16(r_doc) as u64,
-                2 => doc_as_u32(r_doc) as u64,
-                3 => doc_as_u64(r_doc),
-                _ => unreachable!(),
-            }
-        } else {
-            return Err(Expected(format!("expected EBML doc with tag EsU8 through {:?} but \
-                                         found tag {:?}",
-                                        last_tag,
-                                        r_tag)));
-        };
-        if 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;
-        debug!("next_uint({:?}) result={:?}", last_tag, r);
-        Ok(r)
-    }
-
-    // variable-length signed integer with different tags.
-    // `last_tag` should be the largest allowed signed integer tag.
-    // all tags between them should be valid, in the order of i8, i16, i32 and i64.
-    fn next_int(&mut self,
-                last_tag: EbmlEncoderTag)
-                -> DecodeResult<i64> {
-        if self.pos >= self.parent.end {
-            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)?;
-        let r = if EsI8 as usize <= r_tag && r_tag <= last_tag as usize {
-            match r_tag - EsI8 as usize {
-                0 => doc_as_i8(r_doc) as i64,
-                1 => doc_as_i16(r_doc) as i64,
-                2 => doc_as_i32(r_doc) as i64,
-                3 => doc_as_i64(r_doc),
-                _ => unreachable!(),
-            }
-        } else {
-            return Err(Expected(format!("expected EBML doc with tag EsI8 through {:?} but \
-                                         found tag {:?}",
-                                        last_tag,
-                                        r_tag)));
-        };
-        if 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;
-        debug!("next_int({:?}) result={:?}", last_tag, r);
-        Ok(r)
-    }
-
-    pub fn position(&self) -> usize {
-        self.pos
-    }
-
-    pub fn advance(&mut self, bytes: usize) {
-        self.pos += bytes;
-    }
-}
-
-impl<'doc, 'tcx> ::decoder::DecodeContext<'doc, 'tcx> {
-    pub fn read_opaque<R, F>(&mut self, op: F) -> DecodeResult<R>
-        where F: FnOnce(&mut Self, Doc) -> DecodeResult<R>
-    {
-        let doc = self.next_doc(EsOpaque)?;
-        op(self, doc)
-    }
-
-    fn push_doc<T, F>(&mut self, exp_tag: EbmlEncoderTag, f: F) -> DecodeResult<T>
-        where F: FnOnce(&mut Self) -> DecodeResult<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;
-        Ok(r)
-    }
-}
-
-impl<'doc, 'tcx> serialize::Decoder for ::decoder::DecodeContext<'doc, 'tcx> {
-    type Error = Error;
-    fn read_nil(&mut self) -> DecodeResult<()> {
-        Ok(())
-    }
-
-    fn read_u64(&mut self) -> DecodeResult<u64> {
-        self.next_uint(EsU64)
-    }
-    fn read_u32(&mut self) -> DecodeResult<u32> {
-        Ok(self.next_uint(EsU32)? as u32)
-    }
-    fn read_u16(&mut self) -> DecodeResult<u16> {
-        Ok(self.next_uint(EsU16)? as u16)
-    }
-    fn read_u8(&mut self) -> DecodeResult<u8> {
-        Ok(doc_as_u8(self.next_doc(EsU8)?))
-    }
-    fn read_usize(&mut self) -> DecodeResult<usize> {
-        let v = self.read_u64()?;
-        if v > (::std::usize::MAX as u64) {
-            Err(IntTooBig(v as usize))
-        } else {
-            Ok(v as usize)
-        }
-    }
-
-    fn read_i64(&mut self) -> DecodeResult<i64> {
-        Ok(self.next_int(EsI64)? as i64)
-    }
-    fn read_i32(&mut self) -> DecodeResult<i32> {
-        Ok(self.next_int(EsI32)? as i32)
-    }
-    fn read_i16(&mut self) -> DecodeResult<i16> {
-        Ok(self.next_int(EsI16)? as i16)
-    }
-    fn read_i8(&mut self) -> DecodeResult<i8> {
-        Ok(doc_as_u8(self.next_doc(EsI8)?) as i8)
-    }
-    fn read_isize(&mut self) -> DecodeResult<isize> {
-        let v = self.next_int(EsI64)? as i64;
-        if v > (isize::MAX as i64) || v < (isize::MIN as i64) {
-            debug!("FIXME \\#6122: Removing this makes this function miscompile");
-            Err(IntTooBig(v as usize))
-        } else {
-            Ok(v as isize)
-        }
-    }
-
-    fn read_bool(&mut self) -> DecodeResult<bool> {
-        Ok(doc_as_u8(self.next_doc(EsBool)?) != 0)
-    }
-
-    fn read_f64(&mut self) -> DecodeResult<f64> {
-        let bits = doc_as_u64(self.next_doc(EsF64)?);
-        Ok(unsafe { transmute(bits) })
-    }
-    fn read_f32(&mut self) -> DecodeResult<f32> {
-        let bits = doc_as_u32(self.next_doc(EsF32)?);
-        Ok(unsafe { transmute(bits) })
-    }
-    fn read_char(&mut self) -> DecodeResult<char> {
-        Ok(char::from_u32(doc_as_u32(self.next_doc(EsChar)?)).unwrap())
-    }
-    fn read_str(&mut self) -> DecodeResult<String> {
-        Ok(self.next_doc(EsStr)?.to_string())
-    }
-
-    // Compound types:
-    fn read_enum<T, F>(&mut self, name: &str, f: F) -> DecodeResult<T>
-        where F: FnOnce(&mut Self) -> DecodeResult<T>
-    {
-        debug!("read_enum({})", 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;
-        Ok(result)
-    }
-
-    fn read_enum_variant<T, F>(&mut self, _: &[&str], mut f: F) -> DecodeResult<T>
-        where F: FnMut(&mut Self, usize) -> DecodeResult<T>
-    {
-        debug!("read_enum_variant()");
-        let idx = self._next_sub()?;
-        debug!("  idx={}", idx);
-
-        f(self, idx)
-    }
-
-    fn read_enum_variant_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
-        where F: FnOnce(&mut Self) -> DecodeResult<T>
-    {
-        debug!("read_enum_variant_arg(idx={})", idx);
-        f(self)
-    }
-
-    fn read_enum_struct_variant<T, F>(&mut self, _: &[&str], mut f: F) -> DecodeResult<T>
-        where F: FnMut(&mut Self, usize) -> DecodeResult<T>
-    {
-        debug!("read_enum_struct_variant()");
-        let idx = self._next_sub()?;
-        debug!("  idx={}", idx);
-
-        f(self, idx)
-    }
-
-    fn read_enum_struct_variant_field<T, F>(&mut self,
-                                            name: &str,
-                                            idx: usize,
-                                            f: F)
-                                            -> DecodeResult<T>
-        where F: FnOnce(&mut Self) -> DecodeResult<T>
-    {
-        debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
-        f(self)
-    }
-
-    fn read_struct<T, F>(&mut self, name: &str, _: usize, f: F) -> DecodeResult<T>
-        where F: FnOnce(&mut Self) -> DecodeResult<T>
-    {
-        debug!("read_struct(name={})", name);
-        f(self)
-    }
-
-    fn read_struct_field<T, F>(&mut self, name: &str, idx: usize, f: F) -> DecodeResult<T>
-        where F: FnOnce(&mut Self) -> DecodeResult<T>
-    {
-        debug!("read_struct_field(name={}, idx={})", name, idx);
-        f(self)
-    }
-
-    fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F) -> DecodeResult<T>
-        where F: FnOnce(&mut Self) -> DecodeResult<T>
-    {
-        debug!("read_tuple()");
-        self.read_seq(move |d, len| {
-            if len == tuple_len {
-                f(d)
-            } else {
-                Err(Expected(format!("Expected tuple of length `{}`, found tuple of length \
-                                      `{}`",
-                                     tuple_len,
-                                     len)))
-            }
-        })
-    }
-
-    fn read_tuple_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
-        where F: FnOnce(&mut Self) -> DecodeResult<T>
-    {
-        debug!("read_tuple_arg(idx={})", idx);
-        self.read_seq_elt(idx, f)
-    }
-
-    fn read_tuple_struct<T, F>(&mut self, name: &str, len: usize, f: F) -> DecodeResult<T>
-        where F: FnOnce(&mut Self) -> DecodeResult<T>
-    {
-        debug!("read_tuple_struct(name={})", name);
-        self.read_tuple(len, f)
-    }
-
-    fn read_tuple_struct_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
-        where F: FnOnce(&mut Self) -> DecodeResult<T>
-    {
-        debug!("read_tuple_struct_arg(idx={})", idx);
-        self.read_tuple_arg(idx, f)
-    }
-
-    fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T>
-        where F: FnMut(&mut Self, bool) -> DecodeResult<T>
-    {
-        debug!("read_option()");
-        self.read_enum("Option", move |this| {
-            this.read_enum_variant(&["None", "Some"], move |this, idx| {
-                match idx {
-                    0 => f(this, false),
-                    1 => f(this, true),
-                    _ => Err(Expected(format!("Expected None or Some"))),
-                }
-            })
-        })
-    }
-
-    fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T>
-        where F: FnOnce(&mut Self, usize) -> DecodeResult<T>
-    {
-        debug!("read_seq()");
-        self.push_doc(EsVec, move |d| {
-            let len = d._next_sub()?;
-            debug!("  len={}", len);
-            f(d, len)
-        })
-    }
-
-    fn read_seq_elt<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
-        where F: FnOnce(&mut Self) -> DecodeResult<T>
-    {
-        debug!("read_seq_elt(idx={})", idx);
-        self.push_doc(EsVecElt, f)
-    }
-
-    fn read_map<T, F>(&mut self, f: F) -> DecodeResult<T>
-        where F: FnOnce(&mut Self, usize) -> DecodeResult<T>
-    {
-        debug!("read_map()");
-        self.push_doc(EsMap, move |d| {
-            let len = d._next_sub()?;
-            debug!("  len={}", len);
-            f(d, len)
-        })
-    }
-
-    fn read_map_elt_key<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
-        where F: FnOnce(&mut Self) -> DecodeResult<T>
-    {
-        debug!("read_map_elt_key(idx={})", idx);
-        self.push_doc(EsMapKey, f)
-    }
-
-    fn read_map_elt_val<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
-        where F: FnOnce(&mut Self) -> DecodeResult<T>
-    {
-        debug!("read_map_elt_val(idx={})", idx);
-        self.push_doc(EsMapVal, f)
-    }
-
-    fn error(&mut self, err: &str) -> Error {
-        ApplicationError(err.to_string())
-    }
-}
-
 #[test]
 fn test_vuint_at() {
     let data = &[
diff --git a/src/librustc_metadata/rbml/writer.rs b/src/librustc_metadata/rbml/writer.rs
index f22a9d1cd00..94e9b394f1f 100644
--- a/src/librustc_metadata/rbml/writer.rs
+++ b/src/librustc_metadata/rbml/writer.rs
@@ -12,19 +12,15 @@ use std::mem;
 use std::io::prelude::*;
 use std::io::{self, SeekFrom, Cursor};
 
-use rbml::opaque;
-use rbml::reader::EbmlEncoderTag::*;
-use rbml::reader::NUM_IMPLICIT_TAGS;
-
-use rustc_serialize as serialize;
+use rustc_serialize::opaque;
 
 pub type EncodeResult = io::Result<()>;
 
 // rbml writing
-pub struct Encoder {
-    pub writer: Cursor<Vec<u8>>,
-    size_positions: Vec<u64>,
-    relax_limit: u64, // do not move encoded bytes before this position
+pub struct Encoder<'a> {
+    pub opaque: opaque::Encoder<'a>,
+    size_positions: Vec<usize>,
+    relax_limit: usize, // do not move encoded bytes before this position
 }
 
 const NUM_TAGS: usize = 0x1000;
@@ -65,10 +61,10 @@ pub fn write_vuint<W: Write>(w: &mut W, n: usize) -> EncodeResult {
     Err(io::Error::new(io::ErrorKind::Other, &format!("isize too big: {}", n)[..]))
 }
 
-impl Encoder {
-    pub fn new() -> Encoder {
+impl<'a> Encoder<'a> {
+    pub fn new(cursor: &'a mut Cursor<Vec<u8>>) -> Encoder<'a> {
         Encoder {
-            writer: Cursor::new(vec![]),
+            opaque: opaque::Encoder::new(cursor),
             size_positions: vec![],
             relax_limit: 0,
         }
@@ -76,23 +72,21 @@ impl Encoder {
 
     pub fn start_tag(&mut self, tag_id: usize) -> EncodeResult {
         debug!("Start tag {:?}", tag_id);
-        assert!(tag_id >= NUM_IMPLICIT_TAGS);
 
         // Write the enum ID:
-        write_tag(&mut self.writer, tag_id)?;
+        write_tag(&mut self.opaque.cursor, tag_id)?;
 
         // Write a placeholder four-byte size.
-        let cur_pos = self.writer.seek(SeekFrom::Current(0))?;
+        let cur_pos = self.position();
         self.size_positions.push(cur_pos);
-        let zeroes: &[u8] = &[0, 0, 0, 0];
-        self.writer.write_all(zeroes)
+        self.opaque.cursor.write_all(&[0, 0, 0, 0])
     }
 
     pub fn end_tag(&mut self) -> EncodeResult {
         let last_size_pos = self.size_positions.pop().unwrap();
-        let cur_pos = self.writer.seek(SeekFrom::Current(0))?;
-        self.writer.seek(SeekFrom::Start(last_size_pos))?;
-        let size = (cur_pos - last_size_pos - 4) as usize;
+        let cur_pos = self.position();
+        self.opaque.cursor.seek(SeekFrom::Start(last_size_pos as u64))?;
+        let size = cur_pos - last_size_pos - 4;
 
         // relax the size encoding for small tags (bigger tags are costly to move).
         // we should never try to move the stable positions, however.
@@ -101,18 +95,17 @@ impl Encoder {
             // we can't alter the buffer in place, so have a temporary buffer
             let mut buf = [0u8; RELAX_MAX_SIZE];
             {
-                let last_size_pos = last_size_pos as usize;
-                let data = &self.writer.get_ref()[last_size_pos + 4..cur_pos as usize];
+                let data = &self.opaque.cursor.get_ref()[last_size_pos + 4..cur_pos];
                 buf[..size].copy_from_slice(data);
             }
 
             // overwrite the size and data and continue
-            write_vuint(&mut self.writer, size)?;
-            self.writer.write_all(&buf[..size])?;
+            write_vuint(&mut self.opaque.cursor, size)?;
+            self.opaque.cursor.write_all(&buf[..size])?;
         } else {
             // overwrite the size with an overlong encoding and skip past the data
-            write_sized_vuint(&mut self.writer, size, 4)?;
-            self.writer.seek(SeekFrom::Start(cur_pos))?;
+            write_sized_vuint(&mut self.opaque.cursor, size, 4)?;
+            self.opaque.cursor.seek(SeekFrom::Start(cur_pos as u64))?;
         }
 
         debug!("End tag (size = {:?})", size);
@@ -128,10 +121,9 @@ impl Encoder {
     }
 
     pub fn wr_tagged_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult {
-        assert!(tag_id >= NUM_IMPLICIT_TAGS);
-        write_tag(&mut self.writer, tag_id)?;
-        write_vuint(&mut self.writer, b.len())?;
-        self.writer.write_all(b)
+        write_tag(&mut self.opaque.cursor, tag_id)?;
+        write_vuint(&mut self.opaque.cursor, b.len())?;
+        self.opaque.cursor.write_all(b)
     }
 
     pub fn wr_tagged_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult {
@@ -148,343 +140,36 @@ impl Encoder {
     }
 
     #[inline]
-    pub fn wr_tagged_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult {
-        self.wr_tagged_u64(tag_id, v as u64)
-    }
-
-    #[inline]
     pub fn wr_tagged_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult {
         self.wr_tagged_bytes(tag_id, &[v])
     }
 
-    #[inline]
-    pub fn wr_tagged_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult {
-        self.wr_tagged_u64(tag_id, v as u64)
-    }
-
-    #[inline]
-    pub fn wr_tagged_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult {
-        self.wr_tagged_u32(tag_id, v as u32)
-    }
-
-    #[inline]
-    pub fn wr_tagged_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult {
-        self.wr_tagged_u16(tag_id, v as u16)
-    }
-
-    #[inline]
-    pub fn wr_tagged_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult {
-        self.wr_tagged_bytes(tag_id, &[v as u8])
-    }
-
     pub fn wr_tagged_str(&mut self, tag_id: usize, v: &str) -> EncodeResult {
         self.wr_tagged_bytes(tag_id, v.as_bytes())
     }
 
-    // for auto-serialization
-    fn wr_tagged_raw_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult {
-        write_tag(&mut self.writer, tag_id)?;
-        self.writer.write_all(b)
-    }
-
-    fn wr_tagged_raw_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult {
-        let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) };
-        self.wr_tagged_raw_bytes(tag_id, &bytes)
-    }
-
-    fn wr_tagged_raw_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult {
-        let bytes: [u8; 4] = unsafe { mem::transmute(v.to_be()) };
-        self.wr_tagged_raw_bytes(tag_id, &bytes)
-    }
-
-    fn wr_tagged_raw_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult {
-        let bytes: [u8; 2] = unsafe { mem::transmute(v.to_be()) };
-        self.wr_tagged_raw_bytes(tag_id, &bytes)
-    }
-
-    fn wr_tagged_raw_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult {
-        self.wr_tagged_raw_bytes(tag_id, &[v])
-    }
-
-    fn wr_tagged_raw_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult {
-        self.wr_tagged_raw_u64(tag_id, v as u64)
-    }
-
-    fn wr_tagged_raw_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult {
-        self.wr_tagged_raw_u32(tag_id, v as u32)
-    }
-
-    fn wr_tagged_raw_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult {
-        self.wr_tagged_raw_u16(tag_id, v as u16)
-    }
-
-    fn wr_tagged_raw_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult {
-        self.wr_tagged_raw_bytes(tag_id, &[v as u8])
-    }
-
     pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult {
         debug!("Write {:?} bytes", b.len());
-        self.writer.write_all(b)
+        self.opaque.cursor.write_all(b)
     }
 
     pub fn wr_str(&mut self, s: &str) -> EncodeResult {
         debug!("Write str: {:?}", s);
-        self.writer.write_all(s.as_bytes())
+        self.opaque.cursor.write_all(s.as_bytes())
+    }
+
+    pub fn position(&mut self) -> usize {
+        self.opaque.position() as usize
     }
 
     /// Returns the current position while marking it stable, i.e.
     /// generated bytes so far wouldn't be affected by relaxation.
-    pub fn mark_stable_position(&mut self) -> u64 {
-        let pos = self.writer.seek(SeekFrom::Current(0)).unwrap();
+    pub fn mark_stable_position(&mut self) -> usize {
+        let pos = self.position();
         if self.relax_limit < pos {
             self.relax_limit = pos;
         }
-        pos
-    }
-
-    // used internally to emit things like the vector length and so on
-    fn _emit_tagged_sub(&mut self, v: usize) -> EncodeResult {
-        if v as u8 as usize == v {
-            self.wr_tagged_raw_u8(EsSub8 as usize, v as u8)
-        } else if v as u32 as usize == v {
-            self.wr_tagged_raw_u32(EsSub32 as usize, v as u32)
-        } else {
-            Err(io::Error::new(io::ErrorKind::Other,
-                               &format!("length or variant id too big: {}", v)[..]))
-        }
-    }
-
-    pub fn emit_opaque<F>(&mut self, f: F) -> EncodeResult
-        where F: FnOnce(&mut opaque::Encoder) -> EncodeResult
-    {
-        self.start_tag(EsOpaque as usize)?;
-        f(&mut opaque::Encoder::new(&mut self.writer))?;
-        self.mark_stable_position();
-        self.end_tag()
-    }
-}
-
-impl<'a, 'tcx> serialize::Encoder for ::encoder::EncodeContext<'a, 'tcx> {
-    type Error = io::Error;
-
-    fn emit_nil(&mut self) -> EncodeResult {
-        Ok(())
-    }
-
-    fn emit_usize(&mut self, v: usize) -> EncodeResult {
-        self.emit_u64(v as u64)
-    }
-    fn emit_u64(&mut self, v: u64) -> EncodeResult {
-        if v as u32 as u64 == v {
-            self.emit_u32(v as u32)
-        } else {
-            self.wr_tagged_raw_u64(EsU64 as usize, v)
-        }
-    }
-    fn emit_u32(&mut self, v: u32) -> EncodeResult {
-        if v as u16 as u32 == v {
-            self.emit_u16(v as u16)
-        } else {
-            self.wr_tagged_raw_u32(EsU32 as usize, v)
-        }
-    }
-    fn emit_u16(&mut self, v: u16) -> EncodeResult {
-        if v as u8 as u16 == v {
-            self.emit_u8(v as u8)
-        } else {
-            self.wr_tagged_raw_u16(EsU16 as usize, v)
-        }
-    }
-    fn emit_u8(&mut self, v: u8) -> EncodeResult {
-        self.wr_tagged_raw_u8(EsU8 as usize, v)
-    }
-
-    fn emit_isize(&mut self, v: isize) -> EncodeResult {
-        self.emit_i64(v as i64)
-    }
-    fn emit_i64(&mut self, v: i64) -> EncodeResult {
-        if v as i32 as i64 == v {
-            self.emit_i32(v as i32)
-        } else {
-            self.wr_tagged_raw_i64(EsI64 as usize, v)
-        }
-    }
-    fn emit_i32(&mut self, v: i32) -> EncodeResult {
-        if v as i16 as i32 == v {
-            self.emit_i16(v as i16)
-        } else {
-            self.wr_tagged_raw_i32(EsI32 as usize, v)
-        }
-    }
-    fn emit_i16(&mut self, v: i16) -> EncodeResult {
-        if v as i8 as i16 == v {
-            self.emit_i8(v as i8)
-        } else {
-            self.wr_tagged_raw_i16(EsI16 as usize, v)
-        }
-    }
-    fn emit_i8(&mut self, v: i8) -> EncodeResult {
-        self.wr_tagged_raw_i8(EsI8 as usize, v)
-    }
-
-    fn emit_bool(&mut self, v: bool) -> EncodeResult {
-        self.wr_tagged_raw_u8(EsBool as usize, v as u8)
-    }
-
-    fn emit_f64(&mut self, v: f64) -> EncodeResult {
-        let bits = unsafe { mem::transmute(v) };
-        self.wr_tagged_raw_u64(EsF64 as usize, bits)
-    }
-    fn emit_f32(&mut self, v: f32) -> EncodeResult {
-        let bits = unsafe { mem::transmute(v) };
-        self.wr_tagged_raw_u32(EsF32 as usize, bits)
-    }
-    fn emit_char(&mut self, v: char) -> EncodeResult {
-        self.wr_tagged_raw_u32(EsChar as usize, v as u32)
-    }
-
-    fn emit_str(&mut self, v: &str) -> EncodeResult {
-        self.wr_tagged_str(EsStr as usize, v)
-    }
-
-    fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        self.start_tag(EsEnum as usize)?;
-        f(self)?;
-        self.end_tag()
-    }
-
-    fn emit_enum_variant<F>(&mut self, _: &str, v_id: usize, _: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        self._emit_tagged_sub(v_id)?;
-        f(self)
-    }
-
-    fn emit_enum_variant_arg<F>(&mut self, _: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        f(self)
-    }
-
-    fn emit_enum_struct_variant<F>(&mut self,
-                                   v_name: &str,
-                                   v_id: usize,
-                                   cnt: usize,
-                                   f: F)
-                                   -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        self.emit_enum_variant(v_name, v_id, cnt, f)
-    }
-
-    fn emit_enum_struct_variant_field<F>(&mut self, _: &str, idx: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        self.emit_enum_variant_arg(idx, f)
-    }
-
-    fn emit_struct<F>(&mut self, _: &str, _len: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        f(self)
-    }
-
-    fn emit_struct_field<F>(&mut self, _name: &str, _: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        f(self)
-    }
-
-    fn emit_tuple<F>(&mut self, len: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        self.emit_seq(len, f)
-    }
-    fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        self.emit_seq_elt(idx, f)
-    }
-
-    fn emit_tuple_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        self.emit_seq(len, f)
-    }
-    fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        self.emit_seq_elt(idx, f)
-    }
-
-    fn emit_option<F>(&mut self, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        self.emit_enum("Option", f)
-    }
-    fn emit_option_none(&mut self) -> EncodeResult {
-        self.emit_enum_variant("None", 0, 0, |_| Ok(()))
-    }
-    fn emit_option_some<F>(&mut self, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-
-        self.emit_enum_variant("Some", 1, 1, f)
-    }
-
-    fn emit_seq<F>(&mut self, len: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        if len == 0 {
-            // empty vector optimization
-            return self.wr_tagged_bytes(EsVec as usize, &[]);
-        }
-
-        self.start_tag(EsVec as usize)?;
-        self._emit_tagged_sub(len)?;
-        f(self)?;
-        self.end_tag()
-    }
-
-    fn emit_seq_elt<F>(&mut self, _idx: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-
-        self.start_tag(EsVecElt as usize)?;
-        f(self)?;
-        self.end_tag()
-    }
-
-    fn emit_map<F>(&mut self, len: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        if len == 0 {
-            // empty map optimization
-            return self.wr_tagged_bytes(EsMap as usize, &[]);
-        }
-
-        self.start_tag(EsMap as usize)?;
-        self._emit_tagged_sub(len)?;
-        f(self)?;
-        self.end_tag()
-    }
-
-    fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-
-        self.start_tag(EsMapKey as usize)?;
-        f(self)?;
-        self.end_tag()
-    }
-
-    fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        self.start_tag(EsMapVal as usize)?;
-        f(self)?;
-        self.end_tag()
+        let meta_start = 8 + ::common::metadata_encoding_version.len();
+        pos - meta_start
     }
 }
diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs
index 6d3b8571d3c..28e7b8852b3 100644
--- a/src/librustc_metadata/tydecode.rs
+++ b/src/librustc_metadata/tydecode.rs
@@ -24,7 +24,7 @@ use rustc::ty::subst::{Kind, Substs};
 use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
 
 use rbml;
-use rbml::leb128;
+use rustc_serialize::leb128;
 use std::str;
 use syntax::abi;
 use syntax::ast;
diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs
index 73996518a15..8cd18d1bfc7 100644
--- a/src/librustc_metadata/tyencode.rs
+++ b/src/librustc_metadata/tyencode.rs
@@ -28,7 +28,7 @@ use rustc::hir;
 use syntax::abi::Abi;
 use syntax::ast;
 
-use rbml::leb128;
+use rustc_serialize::leb128;
 use encoder;
 
 pub struct ctxt<'a, 'tcx: 'a> {
@@ -186,9 +186,10 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx
     abbrev.write_all(b"#");
     {
         let start_position = abbrev.position() as usize;
+        let meta_start = 8 + ::common::metadata_encoding_version.len() as u64;
         let bytes_written = leb128::write_unsigned_leb128(abbrev.get_mut(),
                                                           start_position,
-                                                          pos);
+                                                          pos - meta_start);
         abbrev.set_position((start_position + bytes_written) as u64);
     }
 
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index a6581ae605b..a10f8c77ac0 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -1346,8 +1346,7 @@ fn write_metadata(cx: &SharedCrateContext,
                                           cx.export_map(),
                                           cx.link_meta(),
                                           reachable_ids,
-                                          cx.mir_map(),
-                                          cx.tcx().map.krate());
+                                          cx.mir_map());
     let mut compressed = cstore.metadata_encoding_version().to_vec();
     compressed.extend_from_slice(&flate::deflate_bytes(&metadata));
 
diff --git a/src/librbml/leb128.rs b/src/libserialize/leb128.rs
index 0c5356c0222..0c5356c0222 100644
--- a/src/librbml/leb128.rs
+++ b/src/libserialize/leb128.rs
diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs
index 7082ee5d292..7cb02e2412c 100644
--- a/src/libserialize/lib.rs
+++ b/src/libserialize/lib.rs
@@ -56,6 +56,9 @@ mod collection_impls;
 pub mod hex;
 pub mod json;
 
+pub mod opaque;
+pub mod leb128;
+
 mod rustc_serialize {
     pub use serialize::*;
 }
diff --git a/src/librbml/opaque.rs b/src/libserialize/opaque.rs
index 55ab2afe445..e97834f63ce 100644
--- a/src/librbml/opaque.rs
+++ b/src/libserialize/opaque.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use Error as DecodeError;
 use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128, write_unsigned_leb128};
 use std::io::{self, Write};
 use serialize;
@@ -125,131 +124,6 @@ impl<'a> serialize::Encoder for Encoder<'a> {
         let _ = self.cursor.write_all(v.as_bytes());
         Ok(())
     }
-
-    fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        f(self)
-    }
-
-    fn emit_enum_variant<F>(&mut self,
-                            _v_name: &str,
-                            v_id: usize,
-                            _len: usize,
-                            f: F)
-                            -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult
-    {
-        self.emit_usize(v_id)?;
-        f(self)
-    }
-
-    fn emit_enum_variant_arg<F>(&mut self, _: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        f(self)
-    }
-
-    fn emit_enum_struct_variant<F>(&mut self,
-                                   v_name: &str,
-                                   v_id: usize,
-                                   cnt: usize,
-                                   f: F)
-                                   -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        self.emit_enum_variant(v_name, v_id, cnt, f)
-    }
-
-    fn emit_enum_struct_variant_field<F>(&mut self, _: &str, idx: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        self.emit_enum_variant_arg(idx, f)
-    }
-
-    fn emit_struct<F>(&mut self, _: &str, _len: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        f(self)
-    }
-
-    fn emit_struct_field<F>(&mut self, _name: &str, _: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        f(self)
-    }
-
-    fn emit_tuple<F>(&mut self, len: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        self.emit_seq(len, f)
-    }
-
-    fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        self.emit_seq_elt(idx, f)
-    }
-
-    fn emit_tuple_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        self.emit_seq(len, f)
-    }
-
-    fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        self.emit_seq_elt(idx, f)
-    }
-
-    fn emit_option<F>(&mut self, f: F) -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        self.emit_enum("Option", f)
-    }
-
-    fn emit_option_none(&mut self) -> EncodeResult {
-        self.emit_enum_variant("None", 0, 0, |_| Ok(()))
-    }
-
-    fn emit_option_some<F>(&mut self, f: F) -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        self.emit_enum_variant("Some", 1, 1, f)
-    }
-
-    fn emit_seq<F>(&mut self, len: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        self.emit_usize(len)?;
-        f(self)
-    }
-
-    fn emit_seq_elt<F>(&mut self, _idx: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        f(self)
-    }
-
-    fn emit_map<F>(&mut self, len: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        self.emit_usize(len)?;
-        f(self)
-    }
-
-    fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        f(self)
-    }
-
-    fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult
-        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
-    {
-        f(self)
-    }
 }
 
 impl<'a> Encoder<'a> {
@@ -302,7 +176,7 @@ macro_rules! read_sleb128 {
 
 
 impl<'a> serialize::Decoder for Decoder<'a> {
-    type Error = DecodeError;
+    type Error = String;
 
     fn read_nil(&mut self) -> Result<(), Self::Error> {
         Ok(())
@@ -379,138 +253,8 @@ impl<'a> serialize::Decoder for Decoder<'a> {
         Ok(s.to_string())
     }
 
-    fn read_enum<T, F>(&mut self, _name: &str, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
-    {
-        f(self)
-    }
-
-    fn read_enum_variant<T, F>(&mut self, _: &[&str], mut f: F) -> Result<T, Self::Error>
-        where F: FnMut(&mut Decoder<'a>, usize) -> Result<T, Self::Error>
-    {
-        let disr = self.read_usize()?;
-        f(self, disr)
-    }
-
-    fn read_enum_variant_arg<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
-    {
-        f(self)
-    }
-
-    fn read_enum_struct_variant<T, F>(&mut self, _: &[&str], mut f: F) -> Result<T, Self::Error>
-        where F: FnMut(&mut Decoder<'a>, usize) -> Result<T, Self::Error>
-    {
-        let disr = self.read_usize()?;
-        f(self, disr)
-    }
-
-    fn read_enum_struct_variant_field<T, F>(&mut self,
-                                            _name: &str,
-                                            _idx: usize,
-                                            f: F)
-                                            -> Result<T, Self::Error>
-        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
-    {
-        f(self)
-    }
-
-    fn read_struct<T, F>(&mut self, _name: &str, _: usize, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
-    {
-        f(self)
-    }
-
-    fn read_struct_field<T, F>(&mut self, _name: &str, _idx: usize, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
-    {
-        f(self)
-    }
-
-    fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
-    {
-        self.read_seq(move |d, len| {
-            if len == tuple_len {
-                f(d)
-            } else {
-                let err = format!("Invalid tuple length. Expected {}, found {}",
-                                  tuple_len,
-                                  len);
-                Err(DecodeError::Expected(err))
-            }
-        })
-    }
-
-    fn read_tuple_arg<T, F>(&mut self, idx: usize, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
-    {
-        self.read_seq_elt(idx, f)
-    }
-
-    fn read_tuple_struct<T, F>(&mut self, _name: &str, len: usize, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
-    {
-        self.read_tuple(len, f)
-    }
-
-    fn read_tuple_struct_arg<T, F>(&mut self, idx: usize, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
-    {
-        self.read_tuple_arg(idx, f)
-    }
-
-    fn read_option<T, F>(&mut self, mut f: F) -> Result<T, Self::Error>
-        where F: FnMut(&mut Decoder<'a>, bool) -> Result<T, Self::Error>
-    {
-        self.read_enum("Option", move |this| {
-            this.read_enum_variant(&["None", "Some"], move |this, idx| {
-                match idx {
-                    0 => f(this, false),
-                    1 => f(this, true),
-                    _ => {
-                        let msg = format!("Invalid Option index: {}", idx);
-                        Err(DecodeError::Expected(msg))
-                    }
-                }
-            })
-        })
-    }
-
-    fn read_seq<T, F>(&mut self, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Decoder<'a>, usize) -> Result<T, Self::Error>
-    {
-        let len = self.read_usize()?;
-        f(self, len)
-    }
-
-    fn read_seq_elt<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
-    {
-        f(self)
-    }
-
-    fn read_map<T, F>(&mut self, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Decoder<'a>, usize) -> Result<T, Self::Error>
-    {
-        let len = self.read_usize()?;
-        f(self, len)
-    }
-
-    fn read_map_elt_key<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
-    {
-        f(self)
-    }
-
-    fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
-    {
-        f(self)
-    }
-
     fn error(&mut self, err: &str) -> Self::Error {
-        DecodeError::ApplicationError(err.to_string())
+        err.to_string()
     }
 }
 
diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs
index ba6eefe82bb..88f6c12e980 100644
--- a/src/libserialize/serialize.rs
+++ b/src/libserialize/serialize.rs
@@ -42,66 +42,99 @@ pub trait Encoder {
     fn emit_str(&mut self, v: &str) -> Result<(), Self::Error>;
 
     // Compound types:
-    fn emit_enum<F>(&mut self, name: &str, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+    fn emit_enum<F>(&mut self, _name: &str, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
 
-    fn emit_enum_variant<F>(&mut self, v_name: &str,
+    fn emit_enum_variant<F>(&mut self, _v_name: &str,
                             v_id: usize,
-                            len: usize,
+                            _len: usize,
                             f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
-    fn emit_enum_variant_arg<F>(&mut self, a_idx: usize, f: F)
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        self.emit_usize(v_id)?;
+        f(self)
+    }
+    fn emit_enum_variant_arg<F>(&mut self, _a_idx: usize, f: F)
                                 -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
 
     fn emit_enum_struct_variant<F>(&mut self, v_name: &str,
                                    v_id: usize,
                                    len: usize,
                                    f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        self.emit_enum_variant(v_name, v_id, len, f)
+    }
     fn emit_enum_struct_variant_field<F>(&mut self,
-                                         f_name: &str,
+                                         _f_name: &str,
                                          f_idx: usize,
                                          f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        self.emit_enum_variant_arg(f_idx, f)
+    }
 
-    fn emit_struct<F>(&mut self, name: &str, len: usize, f: F)
+    fn emit_struct<F>(&mut self, _name: &str, _len: usize, f: F)
                       -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
-    fn emit_struct_field<F>(&mut self, f_name: &str, f_idx: usize, f: F)
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
+    fn emit_struct_field<F>(&mut self, _f_name: &str, _f_idx: usize, f: F)
                             -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
 
-    fn emit_tuple<F>(&mut self, len: usize, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
-    fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+    fn emit_tuple<F>(&mut self, _len: usize, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
+    fn emit_tuple_arg<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
 
-    fn emit_tuple_struct<F>(&mut self, name: &str, len: usize, f: F)
+    fn emit_tuple_struct<F>(&mut self, _name: &str, len: usize, f: F)
                             -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        self.emit_tuple(len, f)
+    }
     fn emit_tuple_struct_arg<F>(&mut self, f_idx: usize, f: F)
                                 -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        self.emit_tuple_arg(f_idx, f)
+    }
 
     // Specialized types:
     fn emit_option<F>(&mut self, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
-    fn emit_option_none(&mut self) -> Result<(), Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        self.emit_enum("Option", f)
+    }
+    fn emit_option_none(&mut self) -> Result<(), Self::Error> {
+        self.emit_enum_variant("None", 0, 0, |_| Ok(()))
+    }
     fn emit_option_some<F>(&mut self, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+
+        self.emit_enum_variant("Some", 1, 1, f)
+    }
 
     fn emit_seq<F>(&mut self, len: usize, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
-    fn emit_seq_elt<F>(&mut self, idx: usize, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        self.emit_usize(len)?;
+        f(self)
+    }
+    fn emit_seq_elt<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
 
     fn emit_map<F>(&mut self, len: usize, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
-    fn emit_map_elt_key<F>(&mut self, idx: usize, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
-    fn emit_map_elt_val<F>(&mut self, idx: usize, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        self.emit_usize(len)?;
+        f(self)
+    }
+    fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
+    fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
 }
 
 pub trait Decoder {
@@ -126,66 +159,101 @@ pub trait Decoder {
     fn read_str(&mut self) -> Result<String, Self::Error>;
 
     // Compound types:
-    fn read_enum<T, F>(&mut self, name: &str, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+    fn read_enum<T, F>(&mut self, _name: &str, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
 
-    fn read_enum_variant<T, F>(&mut self, names: &[&str], f: F)
+    fn read_enum_variant<T, F>(&mut self, _names: &[&str], mut f: F)
                                -> Result<T, Self::Error>
-        where F: FnMut(&mut Self, usize) -> Result<T, Self::Error>;
-    fn read_enum_variant_arg<T, F>(&mut self, a_idx: usize, f: F)
+        where F: FnMut(&mut Self, usize) -> Result<T, Self::Error>
+    {
+        let disr = self.read_usize()?;
+        f(self, disr)
+    }
+    fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, f: F)
                                    -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
 
     fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F)
                                       -> Result<T, Self::Error>
-        where F: FnMut(&mut Self, usize) -> Result<T, Self::Error>;
+        where F: FnMut(&mut Self, usize) -> Result<T, Self::Error>
+    {
+        self.read_enum_variant(names, f)
+    }
     fn read_enum_struct_variant_field<T, F>(&mut self,
-                                            &f_name: &str,
+                                            _f_name: &str,
                                             f_idx: usize,
                                             f: F)
                                             -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
+    {
+        self.read_enum_variant_arg(f_idx, f)
+    }
 
-    fn read_struct<T, F>(&mut self, s_name: &str, len: usize, f: F)
+    fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, f: F)
                          -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
     fn read_struct_field<T, F>(&mut self,
-                               f_name: &str,
-                               f_idx: usize,
+                               _f_name: &str,
+                               _f_idx: usize,
                                f: F)
                                -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
 
-    fn read_tuple<T, F>(&mut self, len: usize, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
-    fn read_tuple_arg<T, F>(&mut self, a_idx: usize, f: F)
+    fn read_tuple<T, F>(&mut self, _len: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
+    fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, f: F)
                             -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
 
-    fn read_tuple_struct<T, F>(&mut self, s_name: &str, len: usize, f: F)
+    fn read_tuple_struct<T, F>(&mut self, _s_name: &str, len: usize, f: F)
                                -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
+    {
+        self.read_tuple(len, f)
+    }
     fn read_tuple_struct_arg<T, F>(&mut self, a_idx: usize, f: F)
                                    -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
+    {
+        self.read_tuple_arg(a_idx, f)
+    }
 
     // Specialized types:
-    fn read_option<T, F>(&mut self, f: F) -> Result<T, Self::Error>
-        where F: FnMut(&mut Self, bool) -> Result<T, Self::Error>;
+    fn read_option<T, F>(&mut self, mut f: F) -> Result<T, Self::Error>
+        where F: FnMut(&mut Self, bool) -> Result<T, Self::Error>
+    {
+        self.read_enum("Option", move |this| {
+            this.read_enum_variant(&["None", "Some"], move |this, idx| {
+                match idx {
+                    0 => f(this, false),
+                    1 => f(this, true),
+                    _ => Err(this.error("read_option: expected 0 for None or 1 for Some")),
+                }
+            })
+        })
+    }
 
     fn read_seq<T, F>(&mut self, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self, usize) -> Result<T, Self::Error>;
-    fn read_seq_elt<T, F>(&mut self, idx: usize, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+        where F: FnOnce(&mut Self, usize) -> Result<T, Self::Error>
+    {
+        let len = self.read_usize()?;
+        f(self, len)
+    }
+    fn read_seq_elt<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
 
     fn read_map<T, F>(&mut self, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self, usize) -> Result<T, Self::Error>;
-    fn read_map_elt_key<T, F>(&mut self, idx: usize, f: F)
+        where F: FnOnce(&mut Self, usize) -> Result<T, Self::Error>
+    {
+        let len = self.read_usize()?;
+        f(self, len)
+    }
+    fn read_map_elt_key<T, F>(&mut self, _idx: usize, f: F)
                               -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
-    fn read_map_elt_val<T, F>(&mut self, idx: usize, f: F)
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
+    fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F)
                               -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
 
     // Failure
     fn error(&mut self, err: &str) -> Self::Error;
diff --git a/src/rustc/Cargo.lock b/src/rustc/Cargo.lock
index 3377fc43d8a..d8a02badcee 100644
--- a/src/rustc/Cargo.lock
+++ b/src/rustc/Cargo.lock
@@ -51,14 +51,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rbml"
-version = "0.0.0"
-dependencies = [
- "log 0.0.0",
- "serialize 0.0.0",
-]
-
-[[package]]
 name = "rustc"
 version = "0.0.0"
 dependencies = [
@@ -67,7 +59,6 @@ dependencies = [
  "fmt_macros 0.0.0",
  "graphviz 0.0.0",
  "log 0.0.0",
- "rbml 0.0.0",
  "rustc_back 0.0.0",
  "rustc_bitflags 0.0.0",
  "rustc_const_math 0.0.0",
@@ -185,7 +176,6 @@ version = "0.0.0"
 dependencies = [
  "graphviz 0.0.0",
  "log 0.0.0",
- "rbml 0.0.0",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "serialize 0.0.0",
@@ -227,7 +217,6 @@ version = "0.0.0"
 dependencies = [
  "flate 0.0.0",
  "log 0.0.0",
- "rbml 0.0.0",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_bitflags 0.0.0",
diff --git a/src/test/run-pass-fulldeps/issue-11881.rs b/src/test/run-pass-fulldeps/issue-11881.rs
index 9da04f72355..8369d08db36 100644
--- a/src/test/run-pass-fulldeps/issue-11881.rs
+++ b/src/test/run-pass-fulldeps/issue-11881.rs
@@ -11,7 +11,6 @@
 
 #![feature(rustc_private)]
 
-extern crate rbml;
 extern crate serialize;
 
 use std::io::Cursor;
@@ -21,8 +20,7 @@ use std::slice;
 
 use serialize::{Encodable, Encoder};
 use serialize::json;
-
-use rbml::writer;
+use serialize::opaque;
 
 #[derive(Encodable)]
 struct Foo {
@@ -44,7 +42,7 @@ fn encode_json<T: Encodable>(val: &T, wr: &mut Cursor<Vec<u8>>) {
     write!(wr, "{}", json::as_json(val));
 }
 fn encode_rbml<T: Encodable>(val: &T, wr: &mut Cursor<Vec<u8>>) {
-    let mut encoder = writer::Encoder::new(wr);
+    let mut encoder = opaque::Encoder::new(wr);
     val.encode(&mut encoder);
 }