Remove librbml and the RBML-tagged auto-encoder/decoder.

This commit is contained in:
Eduard Burtescu 2016-09-01 16:55:33 +03:00
parent 2ce0e6d4e7
commit 0863012fb9
32 changed files with 411 additions and 1516 deletions

View File

@ -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_plugin rustc_metadata rustc_passes rustc_save_analysis \
rustc_const_eval rustc_const_math rustc_incremental rustc_macro rustc_const_eval rustc_const_math rustc_incremental rustc_macro
HOST_CRATES := syntax syntax_ext proc_macro syntax_pos $(RUSTC_CRATES) rustdoc fmt_macros \ 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 TOOLS := compiletest rustdoc rustc rustbook error_index_generator
DEPS_core := DEPS_core :=
@ -96,7 +96,6 @@ DEPS_getopts := std
DEPS_graphviz := std DEPS_graphviz := std
DEPS_log := std DEPS_log := std
DEPS_num := std DEPS_num := std
DEPS_rbml := std log serialize
DEPS_serialize := std log DEPS_serialize := std log
DEPS_term := std DEPS_term := std
DEPS_test := std getopts term native:rust_test_helpers 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 \ DEPS_rustc_const_eval := rustc_const_math rustc syntax log serialize \
rustc_back graphviz syntax_pos 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\ log graphviz rustc_llvm rustc_back rustc_data_structures\
rustc_const_math syntax_pos rustc_errors rustc_const_math syntax_pos rustc_errors
DEPS_rustc_back := std syntax flate log libc 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_lint := rustc log syntax syntax_pos rustc_const_eval
DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
DEPS_rustc_macro := std syntax 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 rustc_macro syntax_ext
DEPS_rustc_passes := syntax syntax_pos rustc core rustc_const_eval rustc_errors 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 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 \ DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
log syntax serialize rustc_llvm rustc_platform_intrinsics \ log syntax serialize rustc_llvm rustc_platform_intrinsics \
rustc_const_math rustc_const_eval rustc_incremental rustc_errors syntax_pos 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_save_analysis := rustc log syntax syntax_pos serialize
DEPS_rustc_typeck := rustc syntax syntax_pos rustc_platform_intrinsics rustc_const_math \ DEPS_rustc_typeck := rustc syntax syntax_pos rustc_platform_intrinsics rustc_const_math \
rustc_const_eval rustc_errors rustc_const_eval rustc_errors

View File

@ -27,7 +27,7 @@ TEST_TARGET_CRATES = $(filter-out core rustc_unicode alloc_system libc \
panic_abort,$(TARGET_CRATES)) \ panic_abort,$(TARGET_CRATES)) \
collectionstest coretest collectionstest coretest
TEST_DOC_CRATES = $(DOC_CRATES) arena flate fmt_macros getopts graphviz \ 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 \ TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve \
rustc_trans rustc_lint,\ rustc_trans rustc_lint,\
$(HOST_CRATES)) $(HOST_CRATES))

View File

@ -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" }

View File

@ -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)
}
}

View File

@ -14,7 +14,6 @@ flate = { path = "../libflate" }
fmt_macros = { path = "../libfmt_macros" } fmt_macros = { path = "../libfmt_macros" }
graphviz = { path = "../libgraphviz" } graphviz = { path = "../libgraphviz" }
log = { path = "../liblog" } log = { path = "../liblog" }
rbml = { path = "../librbml" }
rustc_back = { path = "../librustc_back" } rustc_back = { path = "../librustc_back" }
rustc_bitflags = { path = "../librustc_bitflags" } rustc_bitflags = { path = "../librustc_bitflags" }
rustc_const_math = { path = "../librustc_const_math" } rustc_const_math = { path = "../librustc_const_math" }

View File

@ -50,7 +50,6 @@ extern crate fmt_macros;
extern crate getopts; extern crate getopts;
extern crate graphviz; extern crate graphviz;
extern crate libc; extern crate libc;
extern crate rbml;
extern crate rustc_llvm as llvm; extern crate rustc_llvm as llvm;
extern crate rustc_back; extern crate rustc_back;
extern crate rustc_data_structures; extern crate rustc_data_structures;

View File

@ -265,8 +265,7 @@ pub trait CrateStore<'tcx> {
reexports: &def::ExportMap, reexports: &def::ExportMap,
link_meta: &LinkMeta, link_meta: &LinkMeta,
reachable: &NodeSet, reachable: &NodeSet,
mir_map: &MirMap<'tcx>, mir_map: &MirMap<'tcx>) -> Vec<u8>;
krate: &hir::Crate) -> Vec<u8>;
fn metadata_encoding_version(&self) -> &[u8]; fn metadata_encoding_version(&self) -> &[u8];
} }
@ -472,8 +471,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
reexports: &def::ExportMap, reexports: &def::ExportMap,
link_meta: &LinkMeta, link_meta: &LinkMeta,
reachable: &NodeSet, reachable: &NodeSet,
mir_map: &MirMap<'tcx>, mir_map: &MirMap<'tcx>) -> Vec<u8> { vec![] }
krate: &hir::Crate) -> Vec<u8> { vec![] }
fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") } fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
} }

View File

@ -10,7 +10,6 @@ crate-type = ["dylib"]
[dependencies] [dependencies]
graphviz = { path = "../libgraphviz" } graphviz = { path = "../libgraphviz" }
rbml = { path = "../librbml" }
rustc = { path = "../librustc" } rustc = { path = "../librustc" }
rustc_data_structures = { path = "../librustc_data_structures" } rustc_data_structures = { path = "../librustc_data_structures" }
serialize = { path = "../libserialize" } serialize = { path = "../libserialize" }

View File

@ -27,7 +27,6 @@
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
extern crate graphviz; extern crate graphviz;
extern crate rbml;
#[macro_use] extern crate rustc; #[macro_use] extern crate rustc;
extern crate rustc_data_structures; extern crate rustc_data_structures;
extern crate serialize as rustc_serialize; extern crate serialize as rustc_serialize;

View File

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use rbml::Error;
use rbml::opaque::Decoder;
use rustc::dep_graph::DepNode; use rustc::dep_graph::DepNode;
use rustc::hir::def_id::{CrateNum, DefId}; use rustc::hir::def_id::{CrateNum, DefId};
use rustc::hir::svh::Svh; use rustc::hir::svh::Svh;
@ -17,6 +15,7 @@ use rustc::ty::TyCtxt;
use rustc_data_structures::fnv::FnvHashMap; use rustc_data_structures::fnv::FnvHashMap;
use rustc_data_structures::flock; use rustc_data_structures::flock;
use rustc_serialize::Decodable; use rustc_serialize::Decodable;
use rustc_serialize::opaque::Decoder;
use std::io::{ErrorKind, Read}; use std::io::{ErrorKind, Read};
use std::fs::File; use std::fs::File;
@ -188,7 +187,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
fn load_from_data(&mut self, fn load_from_data(&mut self,
cnum: CrateNum, cnum: CrateNum,
data: &[u8], data: &[u8],
expected_svh: Svh) -> Result<(), Error> { expected_svh: Svh) -> Result<(), String> {
debug!("load_from_data(cnum={})", cnum); debug!("load_from_data(cnum={})", cnum);
// Load up the hashes for the def-ids from this crate. // Load up the hashes for the def-ids from this crate.

View File

@ -10,14 +10,13 @@
//! Code to save/load the dep-graph from files. //! Code to save/load the dep-graph from files.
use rbml::Error;
use rbml::opaque::Decoder;
use rustc::dep_graph::DepNode; use rustc::dep_graph::DepNode;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::session::Session; use rustc::session::Session;
use rustc::ty::TyCtxt; use rustc::ty::TyCtxt;
use rustc_data_structures::fnv::FnvHashSet; use rustc_data_structures::fnv::FnvHashSet;
use rustc_serialize::Decodable as RustcDecodable; use rustc_serialize::Decodable as RustcDecodable;
use rustc_serialize::opaque::Decoder;
use std::io::Read; use std::io::Read;
use std::fs::{self, File}; use std::fs::{self, File};
use std::path::{Path}; use std::path::{Path};
@ -121,7 +120,7 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
incremental_hashes_map: &IncrementalHashesMap, incremental_hashes_map: &IncrementalHashesMap,
dep_graph_data: &[u8], dep_graph_data: &[u8],
work_products_data: &[u8]) work_products_data: &[u8])
-> Result<(), Error> -> Result<(), String>
{ {
// Decode the list of work_products // Decode the list of work_products
let mut work_product_decoder = Decoder::new(work_products_data, 0); let mut work_product_decoder = Decoder::new(work_products_data, 0);

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use rbml::opaque::Encoder;
use rustc::dep_graph::DepNode; use rustc::dep_graph::DepNode;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::hir::svh::Svh; use rustc::hir::svh::Svh;
@ -16,6 +15,7 @@ use rustc::session::Session;
use rustc::ty::TyCtxt; use rustc::ty::TyCtxt;
use rustc_data_structures::fnv::FnvHashMap; use rustc_data_structures::fnv::FnvHashMap;
use rustc_serialize::Encodable as RustcEncodable; use rustc_serialize::Encodable as RustcEncodable;
use rustc_serialize::opaque::Encoder;
use std::hash::{Hash, Hasher, SipHasher}; use std::hash::{Hash, Hasher, SipHasher};
use std::io::{self, Cursor, Write}; use std::io::{self, Cursor, Write};
use std::fs::{self, File}; use std::fs::{self, File};

View File

@ -11,7 +11,6 @@ crate-type = ["dylib"]
[dependencies] [dependencies]
flate = { path = "../libflate" } flate = { path = "../libflate" }
log = { path = "../liblog" } log = { path = "../liblog" }
rbml = { path = "../librbml" }
rustc = { path = "../librustc" } rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" } rustc_back = { path = "../librustc_back" }
rustc_bitflags = { path = "../librustc_bitflags" } rustc_bitflags = { path = "../librustc_bitflags" }

View File

@ -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) { 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 table = Decodable::decode(dcx).unwrap();
let id = Decodable::decode(dcx).unwrap(); let id = Decodable::decode(dcx).unwrap();
debug!("decode_side_tables: entry for id={}, table={:?}", id, table); debug!("decode_side_tables: entry for id={}, table={:?}", id, table);

View File

@ -10,12 +10,9 @@
#![allow(non_camel_case_types, non_upper_case_globals)] #![allow(non_camel_case_types, non_upper_case_globals)]
// RBML enum definitions and utils shared by the encoder and decoder pub const tag_opaque: usize = 0x00;
//
// 0x00..0x1f: reserved for RBML generic type tags // GAP 0x01...0x19
// 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_items: usize = 0x100; // top-level only pub const tag_items: usize = 0x100; // top-level only

View File

@ -13,7 +13,6 @@ use common;
use decoder; use decoder;
use encoder; use encoder;
use loader; use loader;
use rbml;
use middle::cstore::{InlinedItem, CrateStore, CrateSource, ChildItem, ExternCrate, DefLike}; use middle::cstore::{InlinedItem, CrateStore, CrateSource, ChildItem, ExternCrate, DefLike};
use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference}; 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::util::nodemap::{FnvHashMap, NodeSet, DefIdMap};
use rustc::session::config::PanicStrategy; use rustc::session::config::PanicStrategy;
use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use std::path::PathBuf; use std::path::PathBuf;
use syntax::ast; use syntax::ast;
@ -697,22 +695,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
reexports: &def::ExportMap, reexports: &def::ExportMap,
link_meta: &LinkMeta, link_meta: &LinkMeta,
reachable: &NodeSet, reachable: &NodeSet,
mir_map: &MirMap<'tcx>, mir_map: &MirMap<'tcx>) -> Vec<u8>
krate: &hir::Crate) -> Vec<u8>
{ {
let type_abbrevs = RefCell::new(FnvHashMap()); encoder::encode_metadata(tcx, self, reexports, link_meta, reachable, mir_map)
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)
} }
fn metadata_encoding_version(&self) -> &[u8] fn metadata_encoding_version(&self) -> &[u8]

View File

@ -45,14 +45,14 @@ use rustc_const_math::ConstInt;
use rustc::mir::repr::Mir; use rustc::mir::repr::Mir;
use std::io; use std::io;
use std::ops::{Deref, DerefMut};
use std::rc::Rc; use std::rc::Rc;
use std::str; use std::str;
use std::u32; use std::u32;
use rbml::reader; use rbml::reader;
use rbml; use rbml;
use rustc_serialize::{Decodable, SpecializedDecoder}; use rustc_serialize::{Decodable, SpecializedDecoder, opaque};
use rustc_serialize as serialize;
use syntax::attr; use syntax::attr;
use syntax::parse::token; use syntax::parse::token;
use syntax::ast::{self, NodeId}; use syntax::ast::{self, NodeId};
@ -60,7 +60,7 @@ use syntax::print::pprust;
use syntax_pos::{self, Span, BytePos, NO_EXPANSION}; use syntax_pos::{self, Span, BytePos, NO_EXPANSION};
pub struct DecodeContext<'a, 'tcx: 'a> { 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 tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
pub cdata: Option<&'a cstore::CrateMetadata>, pub cdata: Option<&'a cstore::CrateMetadata>,
pub from_id_range: IdRange, pub from_id_range: IdRange,
@ -76,7 +76,7 @@ impl<'doc> rbml::Doc<'doc> {
max: NodeId::from_u32(u32::MAX) max: NodeId::from_u32(u32::MAX)
}; };
DecodeContext { DecodeContext {
rbml_r: reader::Decoder::new(self), opaque: opaque::Decoder::new(self.data, self.start),
cdata: None, cdata: None,
tcx: None, tcx: None,
from_id_range: id_range, 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 fn read_ty_encoded<F, R>(&mut self, op: F) -> R
where F: for<'x> FnOnce(&mut TyDecoder<'x,'tcx>) -> R where F: for<'x> FnOnce(&mut TyDecoder<'x,'tcx>) -> R
{ {
self.read_opaque(|this, doc| { let pos = self.opaque.position();
Ok(op(&mut TyDecoder::with_doc( let doc = rbml::Doc::at(self.opaque.data, pos);
this.tcx(), this.cdata().cnum, doc, self.opaque.advance(doc.end - pos);
&mut |d| translate_def_id(this.cdata(), d)))) op(&mut TyDecoder::with_doc(self.tcx(), self.cdata().cnum, doc,
}).unwrap() &mut |d| translate_def_id(self.cdata(), d)))
} }
} }
impl<'a, 'tcx> Deref for DecodeContext<'a, 'tcx> { macro_rules! decoder_methods {
type Target = rbml::reader::Decoder<'a>; ($($name:ident -> $ty:ty;)*) => {
fn deref(&self) -> &Self::Target { $(fn $name(&mut self) -> Result<$ty, Self::Error> {
&self.rbml_r self.opaque.$name()
})*
} }
} }
impl<'a, 'tcx> DerefMut for DecodeContext<'a, 'tcx> { impl<'doc, 'tcx> serialize::Decoder for ::decoder::DecodeContext<'doc, 'tcx> {
fn deref_mut(&mut self) -> &mut Self::Target { type Error = <opaque::Decoder<'doc> as serialize::Decoder>::Error;
&mut self.rbml_r
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 { impl CrateMetadata {
fn get_item(&self, item_id: DefIndex) -> Option<rbml::Doc> { fn get_item(&self, item_id: DefIndex) -> Option<rbml::Doc> {
self.index.lookup_item(self.data(), item_id).map(|pos| { 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)
}) })
} }

View File

@ -35,9 +35,10 @@ use rustc::mir::mir_map::MirMap;
use rustc::session::config::{self, PanicStrategy, CrateTypeRustcMacro}; use rustc::session::config::{self, PanicStrategy, CrateTypeRustcMacro};
use rustc::util::nodemap::{FnvHashMap, NodeSet}; 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::prelude::*;
use std::io::SeekFrom; use std::io::Cursor;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::rc::Rc; use std::rc::Rc;
use std::u32; use std::u32;
@ -55,7 +56,7 @@ use rustc::hir::map::DefKey;
use super::index_builder::{FromId, IndexBuilder, ItemContentBuilder, Untracked, XRef}; use super::index_builder::{FromId, IndexBuilder, ItemContentBuilder, Untracked, XRef};
pub struct EncodeContext<'a, 'tcx: 'a> { 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 tcx: TyCtxt<'a, 'tcx, 'tcx>,
pub reexports: &'a def::ExportMap, pub reexports: &'a def::ExportMap,
pub link_meta: &'a LinkMeta, pub link_meta: &'a LinkMeta,
@ -66,7 +67,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
} }
impl<'a, 'tcx> Deref for EncodeContext<'a, 'tcx> { impl<'a, 'tcx> Deref for EncodeContext<'a, 'tcx> {
type Target = rbml::writer::Encoder; type Target = rbml::writer::Encoder<'a>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.rbml_w &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> { impl<'a, 'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'a, 'tcx> {
fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> { fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
let cx = self.ty_str_ctxt(); 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> { impl<'a, 'tcx> SpecializedEncoder<&'tcx Substs<'tcx>> for EncodeContext<'a, 'tcx> {
fn specialized_encode(&mut self, substs: &&'tcx Substs<'tcx>) -> Result<(), Self::Error> { fn specialized_encode(&mut self, substs: &&'tcx Substs<'tcx>) -> Result<(), Self::Error> {
let cx = self.ty_str_ctxt(); 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) { tag: usize) {
let cx = ecx.ty_str_ctxt(); let cx = ecx.ty_str_ctxt();
ecx.start_tag(tag); 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.mark_stable_position();
ecx.end_tag(); 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>, fn write_closure_type<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>,
closure_type: &ty::ClosureTy<'tcx>) { closure_type: &ty::ClosureTy<'tcx>) {
let cx = ecx.ty_str_ctxt(); 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(); ecx.mark_stable_position();
} }
@ -181,7 +222,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> {
fn encode_type(&mut self, typ: Ty<'tcx>) { fn encode_type(&mut self, typ: Ty<'tcx>) {
let cx = self.ty_str_ctxt(); let cx = self.ty_str_ctxt();
self.start_tag(tag_items_data_item_type); 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.mark_stable_position();
self.end_tag(); self.end_tag();
} }
@ -480,7 +521,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> {
{ {
let cx = self.ty_str_ctxt(); let cx = self.ty_str_ctxt();
self.start_tag(tag_item_generics); 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.mark_stable_position();
self.end_tag(); self.end_tag();
self.encode_predicates(predicates, tag_item_predicates); 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; xref_positions[id as usize] = ecx.mark_stable_position() as u32;
match xref { match xref {
XRef::Predicate(p) => { 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.end_tag();
ecx.start_tag(tag_xref_index); 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(); 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) { fn encode_item_index(ecx: &mut EncodeContext, index: IndexData) {
ecx.start_tag(tag_index); ecx.start_tag(tag_index);
index.write_index(&mut ecx.writer); index.write_index(&mut ecx.opaque.cursor);
ecx.end_tag(); 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> { pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
encode_metadata_inner(&mut ecx, krate); 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, // RBML compacts the encoded bytes whenever appropriate,
// so there are some garbages left after the end of the data. // 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 meta_len = cursor.position() as usize;
let mut v = ecx.rbml_w.writer.into_inner(); cursor.get_mut().truncate(meta_len);
v.truncate(metalen);
assert_eq!(v.len(), metalen);
// And here we run into yet another obscure archive bug: in which metadata // 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 // 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 // this metadata, there are 4 zero bytes at the start, which are
// treated as a length of 0 by old compilers. // treated as a length of 0 by old compilers.
let len = v.len(); let meta_start = 8 + ::common::metadata_encoding_version.len();
let mut result = vec![]; let len = meta_len - meta_start;
result.push(0); let mut result = cursor.into_inner();
result.push(0); result[meta_start - 4] = (len >> 24) as u8;
result.push(0); result[meta_start - 3] = (len >> 16) as u8;
result.push(0); result[meta_start - 2] = (len >> 8) as u8;
result.extend(metadata_encoding_version.iter().cloned()); result[meta_start - 1] = (len >> 0) as u8;
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);
result result
} }
fn encode_metadata_inner(ecx: &mut EncodeContext, krate: &hir::Crate) { fn encode_metadata_inner(ecx: &mut EncodeContext) {
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,
};
encode_rustc_version(ecx); encode_rustc_version(ecx);
let tcx = ecx.tcx; let tcx = ecx.tcx;
@ -1804,89 +1825,92 @@ fn encode_metadata_inner(ecx: &mut EncodeContext, krate: &hir::Crate) {
encode_dylib_dependency_formats(ecx); encode_dylib_dependency_formats(ecx);
encode_panic_strategy(ecx); encode_panic_strategy(ecx);
let mut i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); let krate = tcx.map.krate();
encode_attributes(ecx, &krate.attrs);
stats.attr_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i;
i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); let mut i = ecx.position();
encode_attributes(ecx, &krate.attrs);
let attr_bytes = ecx.position() - i;
i = ecx.position();
encode_crate_deps(ecx, ecx.cstore); 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. // Encode the language items.
i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); i = ecx.position();
encode_lang_items(ecx); 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 // Encode the native libraries used
i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); i = ecx.position();
encode_native_libraries(ecx); 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 // Encode the plugin registrar function
i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); i = ecx.position();
encode_plugin_registrar_fn(ecx); 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 // Encode codemap
i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); i = ecx.position();
encode_codemap(ecx); encode_codemap(ecx);
stats.codemap_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; let codemap_bytes = ecx.position() - i;
// Encode macro definitions // Encode macro definitions
i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); i = ecx.position();
encode_macro_defs(ecx, krate); 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. // Encode the def IDs of impls, for coherence checking.
i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); i = ecx.position();
encode_impls(ecx, krate); encode_impls(ecx, krate);
stats.impl_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; let impl_bytes = ecx.position() - i;
// Encode reachability info. // Encode reachability info.
i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); i = ecx.position();
encode_reachable(ecx); 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. // Encode and index the items.
ecx.start_tag(tag_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); 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(); ecx.end_tag();
i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); i = ecx.position();
encode_item_index(ecx, items); 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); 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); 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() { 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 { if *e == 0 {
stats.zero_bytes += 1; zero_bytes += 1;
} }
} }
println!("metadata stats:"); println!("metadata stats:");
println!(" attribute bytes: {}", stats.attr_bytes); println!(" attribute bytes: {}", attr_bytes);
println!(" dep bytes: {}", stats.dep_bytes); println!(" dep bytes: {}", dep_bytes);
println!(" lang item bytes: {}", stats.lang_item_bytes); println!(" lang item bytes: {}", lang_item_bytes);
println!(" native bytes: {}", stats.native_lib_bytes); println!(" native bytes: {}", native_lib_bytes);
println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes); println!("plugin registrar bytes: {}", plugin_registrar_fn_bytes);
println!(" codemap bytes: {}", stats.codemap_bytes); println!(" codemap bytes: {}", codemap_bytes);
println!(" macro def bytes: {}", stats.macro_defs_bytes); println!(" macro def bytes: {}", macro_defs_bytes);
println!(" impl bytes: {}", stats.impl_bytes); println!(" impl bytes: {}", impl_bytes);
println!(" reachable bytes: {}", stats.reachable_bytes); println!(" reachable bytes: {}", reachable_bytes);
println!(" item bytes: {}", stats.item_bytes); println!(" item bytes: {}", item_bytes);
println!(" index bytes: {}", stats.index_bytes); println!(" index bytes: {}", index_bytes);
println!(" xref bytes: {}", stats.xref_bytes); println!(" xref bytes: {}", xref_bytes);
println!(" zero bytes: {}", stats.zero_bytes); println!(" zero bytes: {}", zero_bytes);
println!(" total bytes: {}", stats.total_bytes); println!(" total bytes: {}", total_bytes);
} }
} }

View File

@ -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()); assert!(def_id.is_local());
self.record_index(def_id.index, position); 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(); let item = item.as_usize();
assert!(position < (u32::MAX as u64)); assert!(position < (u32::MAX as usize));
let position = position as u32; let position = position as u32;
assert!(self.positions[item] == u32::MAX, assert!(self.positions[item] == u32::MAX,

View File

@ -28,10 +28,9 @@
//! incremental compilation purposes. //! incremental compilation purposes.
//! //!
//! The `IndexBuilder` facilitates both of these. It is created //! The `IndexBuilder` facilitates both of these. It is created
//! with an RBML encoder isntance (`rbml_w`) along with an //! with an `EncodingContext` (`ecx`), which it encapsulates.
//! `EncodingContext` (`ecx`), which it encapsulates. It has one main //! It has one main method, `record()`. You invoke `record`
//! method, `record()`. You invoke `record` like so to create a new //! like so to create a new `data_item` element in the list:
//! `data_item` element in the list:
//! //!
//! ``` //! ```
//! index.record(some_def_id, callback_fn, data) //! index.record(some_def_id, callback_fn, data)
@ -43,9 +42,9 @@
//! returns, the `common::data_item` tag will be closed. //! returns, the `common::data_item` tag will be closed.
//! //!
//! The `ItemContentBuilder` is another type that just offers access //! The `ItemContentBuilder` is another type that just offers access
//! to the `ecx` and `rbml_w` that were given in, as well as //! to the `ecx` that was given in, as well as maintaining a list of
//! maintaining a list of `xref` instances, which are used to extract //! `xref` instances, which are used to extract common data so it is
//! common data so it is not re-serialized. //! not re-serialized.
//! //!
//! `ItemContentBuilder` is a distinct type which does not offer the //! `ItemContentBuilder` is a distinct type which does not offer the
//! `record` method, so that we can ensure that `common::data_item` elements //! `record` method, so that we can ensure that `common::data_item` elements

View File

@ -51,9 +51,6 @@ extern crate rustc_const_math;
extern crate test; extern crate test;
pub mod rbml { pub mod rbml {
pub extern crate rbml as rbml_crate;
pub use self::rbml_crate::{Error, leb128, opaque};
pub mod writer; pub mod writer;
pub mod reader; pub mod reader;
pub use self::reader::Doc; pub use self::reader::Doc;

View File

@ -45,87 +45,13 @@
//! **Data** can be either binary bytes or zero or more nested RBML documents. //! **Data** can be either binary bytes or zero or more nested RBML documents.
//! Nested documents cannot overflow, and should be entirely contained //! Nested documents cannot overflow, and should be entirely contained
//! within a parent document. //! 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)] #[cfg(test)]
use test::Bencher; use test::Bencher;
pub use self::EbmlEncoderTag::*; use std::fmt;
use std::char;
use std::isize;
use std::mem::transmute;
use std::str; use std::str;
use rustc_serialize as serialize;
use rbml::Error;
use rbml::Error::*;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Doc<'a> { pub struct Doc<'a> {
pub data: &'a [u8], 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> { pub fn get(&self, tag: usize) -> Doc<'doc> {
get_doc(*self, tag) get_doc(*self, tag)
} }
@ -159,53 +96,18 @@ impl<'doc> Doc<'doc> {
} }
} }
pub struct TaggedDoc<'a> { #[derive(Debug)]
tag: usize, pub enum Error {
pub doc: Doc<'a>, IntTooBig(usize),
InvalidTag(usize)
} }
pub type DecodeResult<T> = Result<T, Error>; impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[derive(Copy, Clone, Debug)] // FIXME: this should be a more useful display form
pub enum EbmlEncoderTag { fmt::Debug::fmt(self, f)
// 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,
} }
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 // rbml reading
@ -227,7 +129,7 @@ pub struct Res {
pub next: usize, 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; let v = data[start] as usize;
if v < 0xf0 { if v < 0xf0 {
Ok(Res { Ok(Res {
@ -241,12 +143,12 @@ pub fn tag_at(data: &[u8], start: usize) -> DecodeResult<Res> {
}) })
} else { } else {
// every tag starting with byte 0xf0 is an overlong form, which is prohibited. // every tag starting with byte 0xf0 is an overlong form, which is prohibited.
Err(InvalidTag(v)) Err(Error::InvalidTag(v))
} }
} }
#[inline(never)] #[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]; let a = data[start];
if a & 0x80 != 0 { if a & 0x80 != 0 {
return Ok(Res { return Ok(Res {
@ -275,10 +177,10 @@ fn vuint_at_slow(data: &[u8], start: usize) -> DecodeResult<Res> {
next: start + 4, 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 { if data.len() - start < 4 {
return vuint_at_slow(data, start); 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> { pub fn tag_len_at(data: &[u8], next: usize) -> Result<Res, Error> {
if tag.val < NUM_IMPLICIT_TAGS && TAG_IMPLICIT_LEN[tag.val] >= 0 { vuint_at(data, next)
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 maybe_get_doc<'a>(d: Doc<'a>, tg: usize) -> Option<Doc<'a>> { pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: usize) -> Option<Doc<'a>> {
let mut pos = d.start; let mut pos = d.start;
while pos < d.end { while pos < d.end {
let elt_tag = try_or!(tag_at(d.data, pos), None); 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; pos = elt_size.next + elt_size.val;
if elt_tag.val == tg { if elt_tag.val == tg {
return Some(Doc { 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) { match maybe_get_doc(d, tg) {
Some(d) => d, Some(d) => d,
None => { None => {
error!("failed to find block with tag {:?}", tg); bug!("failed to find block with tag {:?}", tg);
panic!();
} }
} }
} }
@ -404,7 +284,7 @@ impl<'a> Iterator for DocsIterator<'a> {
self.d.start = self.d.end; self.d.start = self.d.end;
None 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; self.d.start = self.d.end;
None None
}); });
@ -509,419 +389,6 @@ pub fn doc_as_i64(d: Doc) -> i64 {
doc_as_u64(d) as 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] #[test]
fn test_vuint_at() { fn test_vuint_at() {
let data = &[ let data = &[

View File

@ -12,19 +12,15 @@ use std::mem;
use std::io::prelude::*; use std::io::prelude::*;
use std::io::{self, SeekFrom, Cursor}; use std::io::{self, SeekFrom, Cursor};
use rbml::opaque; use rustc_serialize::opaque;
use rbml::reader::EbmlEncoderTag::*;
use rbml::reader::NUM_IMPLICIT_TAGS;
use rustc_serialize as serialize;
pub type EncodeResult = io::Result<()>; pub type EncodeResult = io::Result<()>;
// rbml writing // rbml writing
pub struct Encoder { pub struct Encoder<'a> {
pub writer: Cursor<Vec<u8>>, pub opaque: opaque::Encoder<'a>,
size_positions: Vec<u64>, size_positions: Vec<usize>,
relax_limit: u64, // do not move encoded bytes before this position relax_limit: usize, // do not move encoded bytes before this position
} }
const NUM_TAGS: usize = 0x1000; 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)[..])) Err(io::Error::new(io::ErrorKind::Other, &format!("isize too big: {}", n)[..]))
} }
impl Encoder { impl<'a> Encoder<'a> {
pub fn new() -> Encoder { pub fn new(cursor: &'a mut Cursor<Vec<u8>>) -> Encoder<'a> {
Encoder { Encoder {
writer: Cursor::new(vec![]), opaque: opaque::Encoder::new(cursor),
size_positions: vec![], size_positions: vec![],
relax_limit: 0, relax_limit: 0,
} }
@ -76,23 +72,21 @@ impl Encoder {
pub fn start_tag(&mut self, tag_id: usize) -> EncodeResult { pub fn start_tag(&mut self, tag_id: usize) -> EncodeResult {
debug!("Start tag {:?}", tag_id); debug!("Start tag {:?}", tag_id);
assert!(tag_id >= NUM_IMPLICIT_TAGS);
// Write the enum ID: // 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. // 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); self.size_positions.push(cur_pos);
let zeroes: &[u8] = &[0, 0, 0, 0]; self.opaque.cursor.write_all(&[0, 0, 0, 0])
self.writer.write_all(zeroes)
} }
pub fn end_tag(&mut self) -> EncodeResult { pub fn end_tag(&mut self) -> EncodeResult {
let last_size_pos = self.size_positions.pop().unwrap(); let last_size_pos = self.size_positions.pop().unwrap();
let cur_pos = self.writer.seek(SeekFrom::Current(0))?; let cur_pos = self.position();
self.writer.seek(SeekFrom::Start(last_size_pos))?; self.opaque.cursor.seek(SeekFrom::Start(last_size_pos as u64))?;
let size = (cur_pos - last_size_pos - 4) as usize; let size = cur_pos - last_size_pos - 4;
// relax the size encoding for small tags (bigger tags are costly to move). // relax the size encoding for small tags (bigger tags are costly to move).
// we should never try to move the stable positions, however. // 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 // we can't alter the buffer in place, so have a temporary buffer
let mut buf = [0u8; RELAX_MAX_SIZE]; let mut buf = [0u8; RELAX_MAX_SIZE];
{ {
let last_size_pos = last_size_pos as usize; let data = &self.opaque.cursor.get_ref()[last_size_pos + 4..cur_pos];
let data = &self.writer.get_ref()[last_size_pos + 4..cur_pos as usize];
buf[..size].copy_from_slice(data); buf[..size].copy_from_slice(data);
} }
// overwrite the size and data and continue // overwrite the size and data and continue
write_vuint(&mut self.writer, size)?; write_vuint(&mut self.opaque.cursor, size)?;
self.writer.write_all(&buf[..size])?; self.opaque.cursor.write_all(&buf[..size])?;
} else { } else {
// overwrite the size with an overlong encoding and skip past the data // overwrite the size with an overlong encoding and skip past the data
write_sized_vuint(&mut self.writer, size, 4)?; write_sized_vuint(&mut self.opaque.cursor, size, 4)?;
self.writer.seek(SeekFrom::Start(cur_pos))?; self.opaque.cursor.seek(SeekFrom::Start(cur_pos as u64))?;
} }
debug!("End tag (size = {:?})", size); debug!("End tag (size = {:?})", size);
@ -128,10 +121,9 @@ impl Encoder {
} }
pub fn wr_tagged_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult { pub fn wr_tagged_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult {
assert!(tag_id >= NUM_IMPLICIT_TAGS); write_tag(&mut self.opaque.cursor, tag_id)?;
write_tag(&mut self.writer, tag_id)?; write_vuint(&mut self.opaque.cursor, b.len())?;
write_vuint(&mut self.writer, b.len())?; self.opaque.cursor.write_all(b)
self.writer.write_all(b)
} }
pub fn wr_tagged_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult { pub fn wr_tagged_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult {
@ -147,344 +139,37 @@ impl Encoder {
self.wr_tagged_u64(tag_id, v as u64) self.wr_tagged_u64(tag_id, v as u64)
} }
#[inline]
pub fn wr_tagged_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult {
self.wr_tagged_u64(tag_id, v as u64)
}
#[inline] #[inline]
pub fn wr_tagged_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult { pub fn wr_tagged_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult {
self.wr_tagged_bytes(tag_id, &[v]) 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 { pub fn wr_tagged_str(&mut self, tag_id: usize, v: &str) -> EncodeResult {
self.wr_tagged_bytes(tag_id, v.as_bytes()) 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 { pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult {
debug!("Write {:?} bytes", b.len()); 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 { pub fn wr_str(&mut self, s: &str) -> EncodeResult {
debug!("Write str: {:?}", s); 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. /// Returns the current position while marking it stable, i.e.
/// generated bytes so far wouldn't be affected by relaxation. /// generated bytes so far wouldn't be affected by relaxation.
pub fn mark_stable_position(&mut self) -> u64 { pub fn mark_stable_position(&mut self) -> usize {
let pos = self.writer.seek(SeekFrom::Current(0)).unwrap(); let pos = self.position();
if self.relax_limit < pos { if self.relax_limit < pos {
self.relax_limit = pos; self.relax_limit = pos;
} }
pos let meta_start = 8 + ::common::metadata_encoding_version.len();
} pos - meta_start
// 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()
} }
} }

View File

@ -24,7 +24,7 @@ use rustc::ty::subst::{Kind, Substs};
use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rbml; use rbml;
use rbml::leb128; use rustc_serialize::leb128;
use std::str; use std::str;
use syntax::abi; use syntax::abi;
use syntax::ast; use syntax::ast;

View File

@ -28,7 +28,7 @@ use rustc::hir;
use syntax::abi::Abi; use syntax::abi::Abi;
use syntax::ast; use syntax::ast;
use rbml::leb128; use rustc_serialize::leb128;
use encoder; use encoder;
pub struct ctxt<'a, 'tcx: 'a> { 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"#"); abbrev.write_all(b"#");
{ {
let start_position = abbrev.position() as usize; 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(), let bytes_written = leb128::write_unsigned_leb128(abbrev.get_mut(),
start_position, start_position,
pos); pos - meta_start);
abbrev.set_position((start_position + bytes_written) as u64); abbrev.set_position((start_position + bytes_written) as u64);
} }

View File

@ -1346,8 +1346,7 @@ fn write_metadata(cx: &SharedCrateContext,
cx.export_map(), cx.export_map(),
cx.link_meta(), cx.link_meta(),
reachable_ids, reachable_ids,
cx.mir_map(), cx.mir_map());
cx.tcx().map.krate());
let mut compressed = cstore.metadata_encoding_version().to_vec(); let mut compressed = cstore.metadata_encoding_version().to_vec();
compressed.extend_from_slice(&flate::deflate_bytes(&metadata)); compressed.extend_from_slice(&flate::deflate_bytes(&metadata));

View File

@ -56,6 +56,9 @@ mod collection_impls;
pub mod hex; pub mod hex;
pub mod json; pub mod json;
pub mod opaque;
pub mod leb128;
mod rustc_serialize { mod rustc_serialize {
pub use serialize::*; pub use serialize::*;
} }

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use Error as DecodeError;
use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128, write_unsigned_leb128}; use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128, write_unsigned_leb128};
use std::io::{self, Write}; use std::io::{self, Write};
use serialize; use serialize;
@ -125,131 +124,6 @@ impl<'a> serialize::Encoder for Encoder<'a> {
let _ = self.cursor.write_all(v.as_bytes()); let _ = self.cursor.write_all(v.as_bytes());
Ok(()) 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> { impl<'a> Encoder<'a> {
@ -302,7 +176,7 @@ macro_rules! read_sleb128 {
impl<'a> serialize::Decoder for Decoder<'a> { impl<'a> serialize::Decoder for Decoder<'a> {
type Error = DecodeError; type Error = String;
fn read_nil(&mut self) -> Result<(), Self::Error> { fn read_nil(&mut self) -> Result<(), Self::Error> {
Ok(()) Ok(())
@ -379,138 +253,8 @@ impl<'a> serialize::Decoder for Decoder<'a> {
Ok(s.to_string()) 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 { fn error(&mut self, err: &str) -> Self::Error {
DecodeError::ApplicationError(err.to_string()) err.to_string()
} }
} }

View File

@ -42,66 +42,99 @@ pub trait Encoder {
fn emit_str(&mut self, v: &str) -> Result<(), Self::Error>; fn emit_str(&mut self, v: &str) -> Result<(), Self::Error>;
// Compound types: // Compound types:
fn emit_enum<F>(&mut self, name: &str, f: F) -> Result<(), Self::Error> fn emit_enum<F>(&mut self, _name: &str, 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_variant<F>(&mut self, v_name: &str, fn emit_enum_variant<F>(&mut self, _v_name: &str,
v_id: usize, v_id: usize,
len: usize, _len: usize,
f: F) -> Result<(), Self::Error> f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>; where F: FnOnce(&mut Self) -> Result<(), Self::Error>
fn emit_enum_variant_arg<F>(&mut self, a_idx: usize, f: F) {
self.emit_usize(v_id)?;
f(self)
}
fn emit_enum_variant_arg<F>(&mut self, _a_idx: usize, f: F)
-> Result<(), Self::Error> -> 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, fn emit_enum_struct_variant<F>(&mut self, v_name: &str,
v_id: usize, v_id: usize,
len: usize, len: usize,
f: F) -> Result<(), Self::Error> 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, fn emit_enum_struct_variant_field<F>(&mut self,
f_name: &str, _f_name: &str,
f_idx: usize, f_idx: usize,
f: F) -> Result<(), Self::Error> 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> -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>; 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) fn emit_struct_field<F>(&mut self, _f_name: &str, _f_idx: usize, f: F)
-> Result<(), Self::Error> -> 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> fn emit_tuple<F>(&mut self, _len: 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_arg<F>(&mut self, idx: usize, f: F) -> 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>; 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> -> 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) fn emit_tuple_struct_arg<F>(&mut self, f_idx: usize, f: F)
-> Result<(), Self::Error> -> 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: // Specialized types:
fn emit_option<F>(&mut self, f: F) -> Result<(), Self::Error> fn emit_option<F>(&mut self, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>; where F: FnOnce(&mut Self) -> Result<(), Self::Error>
fn emit_option_none(&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> 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> fn emit_seq<F>(&mut self, len: usize, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> 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>; 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> fn emit_map<F>(&mut self, len: usize, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> 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>; self.emit_usize(len)?;
fn emit_map_elt_val<F>(&mut self, idx: usize, f: F) -> Result<(), Self::Error> f(self)
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> { 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 { pub trait Decoder {
@ -126,66 +159,101 @@ pub trait Decoder {
fn read_str(&mut self) -> Result<String, Self::Error>; fn read_str(&mut self) -> Result<String, Self::Error>;
// Compound types: // Compound types:
fn read_enum<T, F>(&mut self, name: &str, f: F) -> 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>; 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> -> Result<T, Self::Error>
where F: FnMut(&mut Self, usize) -> 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) {
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> -> 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) fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F)
-> Result<T, Self::Error> -> 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, fn read_enum_struct_variant_field<T, F>(&mut self,
&f_name: &str, _f_name: &str,
f_idx: usize, f_idx: usize,
f: F) f: F)
-> Result<T, Self::Error> -> 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> -> 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, fn read_struct_field<T, F>(&mut self,
f_name: &str, _f_name: &str,
f_idx: usize, _f_idx: usize,
f: F) f: F)
-> Result<T, Self::Error> -> 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> fn read_tuple<T, F>(&mut self, _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_tuple_arg<T, F>(&mut self, a_idx: usize, f: F) fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, f: F)
-> Result<T, Self::Error> -> 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> -> 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) fn read_tuple_struct_arg<T, F>(&mut self, a_idx: usize, f: F)
-> Result<T, Self::Error> -> 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: // Specialized types:
fn read_option<T, F>(&mut self, f: F) -> 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>; 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> fn read_seq<T, F>(&mut self, f: F) -> Result<T, Self::Error>
where F: FnOnce(&mut Self, usize) -> 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>; 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> fn read_map<T, F>(&mut self, f: F) -> Result<T, Self::Error>
where F: FnOnce(&mut Self, usize) -> 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) {
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> -> 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_map_elt_val<T, F>(&mut self, idx: usize, f: F) fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F)
-> Result<T, Self::Error> -> 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 // Failure
fn error(&mut self, err: &str) -> Self::Error; fn error(&mut self, err: &str) -> Self::Error;

11
src/rustc/Cargo.lock generated
View File

@ -50,14 +50,6 @@ dependencies = [
"syntax_pos 0.0.0", "syntax_pos 0.0.0",
] ]
[[package]]
name = "rbml"
version = "0.0.0"
dependencies = [
"log 0.0.0",
"serialize 0.0.0",
]
[[package]] [[package]]
name = "rustc" name = "rustc"
version = "0.0.0" version = "0.0.0"
@ -67,7 +59,6 @@ dependencies = [
"fmt_macros 0.0.0", "fmt_macros 0.0.0",
"graphviz 0.0.0", "graphviz 0.0.0",
"log 0.0.0", "log 0.0.0",
"rbml 0.0.0",
"rustc_back 0.0.0", "rustc_back 0.0.0",
"rustc_bitflags 0.0.0", "rustc_bitflags 0.0.0",
"rustc_const_math 0.0.0", "rustc_const_math 0.0.0",
@ -185,7 +176,6 @@ version = "0.0.0"
dependencies = [ dependencies = [
"graphviz 0.0.0", "graphviz 0.0.0",
"log 0.0.0", "log 0.0.0",
"rbml 0.0.0",
"rustc 0.0.0", "rustc 0.0.0",
"rustc_data_structures 0.0.0", "rustc_data_structures 0.0.0",
"serialize 0.0.0", "serialize 0.0.0",
@ -227,7 +217,6 @@ version = "0.0.0"
dependencies = [ dependencies = [
"flate 0.0.0", "flate 0.0.0",
"log 0.0.0", "log 0.0.0",
"rbml 0.0.0",
"rustc 0.0.0", "rustc 0.0.0",
"rustc_back 0.0.0", "rustc_back 0.0.0",
"rustc_bitflags 0.0.0", "rustc_bitflags 0.0.0",

View File

@ -11,7 +11,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
extern crate rbml;
extern crate serialize; extern crate serialize;
use std::io::Cursor; use std::io::Cursor;
@ -21,8 +20,7 @@ use std::slice;
use serialize::{Encodable, Encoder}; use serialize::{Encodable, Encoder};
use serialize::json; use serialize::json;
use serialize::opaque;
use rbml::writer;
#[derive(Encodable)] #[derive(Encodable)]
struct Foo { struct Foo {
@ -44,7 +42,7 @@ fn encode_json<T: Encodable>(val: &T, wr: &mut Cursor<Vec<u8>>) {
write!(wr, "{}", json::as_json(val)); write!(wr, "{}", json::as_json(val));
} }
fn encode_rbml<T: Encodable>(val: &T, wr: &mut Cursor<Vec<u8>>) { 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); val.encode(&mut encoder);
} }