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