Auto merge of #22971 - lifthrasiir:metadata-reform, r=huonw

This is a series of individual but correlated changes to the metadata format. The changes are significant enough that it (finally) bumps the metadata encoding version. In brief, they altogether reduce the total size of stage1 binaries by 27% (!!!!). Almost every low-hanging fruit has been considered and fixed; see the individual commits for details.

Detailed library (not just metadata) size changes for x86_64-unknown-linux-gnu stage1 binaries (baseline being 3a96d6a981):

````
   before     after  delta path
--------- --------- ------ --------------------------------
  1706146   1050412  38.4% liballoc-4e7c5e5c.rlib
   398576    152454  61.8% libarena-4e7c5e5c.rlib
    71441     56892  20.4% libarena-4e7c5e5c.so
 14424754   5084102  64.8% libcollections-4e7c5e5c.rlib
 39143186  14743118  62.3% libcore-4e7c5e5c.rlib
   195574    188150   3.8% libflate-4e7c5e5c.rlib
   153123    152603   0.3% libflate-4e7c5e5c.so
   477152    215262  54.9% libfmt_macros-4e7c5e5c.rlib
    77728     66601  14.3% libfmt_macros-4e7c5e5c.so
  1216936    684104  43.8% libgetopts-4e7c5e5c.rlib
   207846    181116  12.9% libgetopts-4e7c5e5c.so
   349722    147530  57.8% libgraphviz-4e7c5e5c.rlib
    60196     49197  18.3% libgraphviz-4e7c5e5c.so
   729842    259906  64.4% liblibc-4e7c5e5c.rlib
   349358    247014  29.3% liblog-4e7c5e5c.rlib
    88878     83163   6.4% liblog-4e7c5e5c.so
  1968508    732840  62.8% librand-4e7c5e5c.rlib
  1968204    696326  64.6% librbml-4e7c5e5c.rlib
   283207    206589  27.1% librbml-4e7c5e5c.so
 72369394  46401230  35.9% librustc-4e7c5e5c.rlib
 11941372  10498483  12.1% librustc-4e7c5e5c.so
  2717894   1983272  27.0% librustc_back-4e7c5e5c.rlib
   501900    464176   7.5% librustc_back-4e7c5e5c.so
    15058     12588  16.4% librustc_bitflags-4e7c5e5c.rlib
  4008268   2961912  26.1% librustc_borrowck-4e7c5e5c.rlib
   837550    785633   6.2% librustc_borrowck-4e7c5e5c.so
  6473348   6095470   5.8% librustc_driver-4e7c5e5c.rlib
  1448785   1433945   1.0% librustc_driver-4e7c5e5c.so
 95483688  94779704   0.7% librustc_llvm-4e7c5e5c.rlib
 43516815  43487809   0.1% librustc_llvm-4e7c5e5c.so
   938140    817236  12.9% librustc_privacy-4e7c5e5c.rlib
   182653    176563   3.3% librustc_privacy-4e7c5e5c.so
  4390288   3543284  19.3% librustc_resolve-4e7c5e5c.rlib
   872981    831824   4.7% librustc_resolve-4e7c5e5c.so
 18176426  14795426  18.6% librustc_trans-4e7c5e5c.rlib
  3657354   3480026   4.8% librustc_trans-4e7c5e5c.so
 16815076  13868862  17.5% librustc_typeck-4e7c5e5c.rlib
  3274439   3123898   4.6% librustc_typeck-4e7c5e5c.so
 21372308  14890582  30.3% librustdoc-4e7c5e5c.rlib
  4501971   4172202   7.3% librustdoc-4e7c5e5c.so
  8055028   2951044  63.4% libserialize-4e7c5e5c.rlib
   958101    710016  25.9% libserialize-4e7c5e5c.so
 30810208  15160648  50.8% libstd-4e7c5e5c.rlib
  6819003   5967485  12.5% libstd-4e7c5e5c.so
 58850950  31949594  45.7% libsyntax-4e7c5e5c.rlib
  9060154   7882423  13.0% libsyntax-4e7c5e5c.so
  1474310   1062102  28.0% libterm-4e7c5e5c.rlib
   345577    323952   6.3% libterm-4e7c5e5c.so
  2827854   1643056  41.9% libtest-4e7c5e5c.rlib
   517811    452519  12.6% libtest-4e7c5e5c.so
  2274106   1761240  22.6% libunicode-4e7c5e5c.rlib
--------- --------- ------ --------------------------------
499359187 363465583  27.2% total
````

Some notes:

* Uncompressed metadata compacts very well. It is less visible for compressed metadata but still it achieves about 5~10% reduction.
* *Every* commit is designed to reduce the metadata in one way. There is absolutely no negative impact associated to changes (that's why the table above doesn't contain a minus delta).
* I've confirmed that this compiles through `make all`, making it almost correct. Other platforms have to be tested though.
* Oh, I'll rebase this as soon as I have spare time, but I guess this needs an extensive review anyway.
* I haven't rigorously checked the encoder and decoder performance. I tried to minimize the impact (some encodings are actually simpler than the original), but I'm not sure.

Fixes #2743, #9303 (partially) and #21482.
This commit is contained in:
bors 2015-03-03 08:06:59 +00:00
commit 24a840d489
5 changed files with 752 additions and 618 deletions

View file

@ -1,4 +1,4 @@
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// 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.
//
@ -8,12 +8,108 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Really Bad Markup Language (rbml) is a temporary measure until we migrate
//! the rust object metadata to a better serialization format. It is not
//! intended to be used by users.
//! Really Bad Markup Language (rbml) is an internal serialization format of rustc.
//! This is not intended to be used by users.
//!
//! It is loosely based on the Extensible Binary Markup Language (ebml):
//! http://www.matroska.org/technical/specs/rfc/index.html
//! Originally based on the Extensible Binary Markup Language
//! (ebml; http://www.matroska.org/technical/specs/rfc/index.html),
//! it is now a separate format tuned for the rust object metadata.
//!
//! # Encoding
//!
//! RBML document consists of the tag, length and data.
//! The encoded data can contain multiple RBML documents concatenated.
//!
//! **Tags** are a hint for the following data.
//! Tags are a number from 0x000 to 0xfff, where 0xf0 through 0xff is reserved.
//! Tags less than 0xf0 are encoded in one literal byte.
//! Tags greater than 0xff are encoded in two big-endian bytes,
//! where the tag number is ORed with 0xf000. (E.g. tag 0x123 = `f1 23`)
//!
//! **Lengths** encode the length of the following data.
//! It is a variable-length unsigned int, and one of the following forms:
//!
//! - `80` through `fe` for lengths up to 0x7e;
//! - `40 ff` through `7f ff` for lengths up to 0x3fff;
//! - `20 40 00` through `3f ff ff` for lengths up to 0x1fffff;
//! - `10 20 00 00` through `1f ff ff ff` for lengths up to 0xfffffff.
//!
//! The "overlong" form is allowed so that the length can be encoded
//! without the prior knowledge of the encoded data.
//! For example, the length 0 can be represented either by `80`, `40 00`,
//! `20 00 00` or `10 00 00 00`.
//! The encoder tries to minimize the length if possible.
//! Also, some predefined tags listed below are so commonly used that
//! their lengths are omitted ("implicit length").
//!
//! **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 interchangably.
//!
//! 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 informations.
//!
//! First 0x20 tags are reserved by RBML; custom tags start at 0x20.
#![crate_name = "rbml"]
#![unstable(feature = "rustc_private")]
@ -64,6 +160,10 @@ impl<'doc> Doc<'doc> {
reader::get_doc(*self, tag)
}
pub fn is_empty(&self) -> bool {
self.start == self.end
}
pub fn as_str_slice<'a>(&'a self) -> &'a str {
str::from_utf8(&self.data[self.start..self.end]).unwrap()
}
@ -80,41 +180,51 @@ pub struct TaggedDoc<'a> {
#[derive(Copy, Debug)]
pub enum EbmlEncoderTag {
EsUint, // 0
EsU64, // 1
EsU32, // 2
EsU16, // 3
EsU8, // 4
EsInt, // 5
EsI64, // 6
EsI32, // 7
EsI16, // 8
EsI8, // 9
EsBool, // 10
EsChar, // 11
EsStr, // 12
EsF64, // 13
EsF32, // 14
EsFloat, // 15
EsEnum, // 16
EsEnumVid, // 17
EsEnumBody, // 18
EsVec, // 19
EsVecLen, // 20
EsVecElt, // 21
EsMap, // 22
EsMapLen, // 23
EsMapKey, // 24
EsMapVal, // 25
// tags 00..1f are reserved for auto-serialization.
// first NUM_IMPLICIT_TAGS tags are implicitly sized and lengths are not encoded.
EsOpaque,
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
EsLabel, // Used only when debugging
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,
}
const NUM_TAGS: uint = 0x1000;
const NUM_IMPLICIT_TAGS: uint = 0x0e;
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*
];
#[derive(Debug)]
pub enum Error {
IntTooBig(uint),
InvalidTag(uint),
Expected(String),
IoError(std::old_io::IoError),
ApplicationError(String)
@ -138,11 +248,11 @@ pub mod reader {
use serialize;
use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsVecLen, EsVecElt,
EsMapLen, EsMapKey, EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64,
use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsSub8, EsSub32,
EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsI64,
EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
EsEnumBody, EsUint, EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc,
Error, IntTooBig, Expected };
EsOpaque, EbmlEncoderTag, Doc, TaggedDoc,
Error, IntTooBig, InvalidTag, Expected, NUM_IMPLICIT_TAGS, TAG_IMPLICIT_LEN };
pub type DecodeResult<T> = Result<T, Error>;
// rbml reading
@ -165,6 +275,18 @@ pub mod reader {
pub next: uint
}
pub fn tag_at(data: &[u8], start: uint) -> DecodeResult<Res> {
let v = data[start] as uint;
if v < 0xf0 {
Ok(Res { val: v, next: start + 1 })
} else if v > 0xf0 {
Ok(Res { val: ((v & 0xf) << 8) | data[start + 1] as uint, next: start + 2 })
} else {
// every tag starting with byte 0xf0 is an overlong form, which is prohibited.
Err(InvalidTag(v))
}
}
#[inline(never)]
fn vuint_at_slow(data: &[u8], start: uint) -> DecodeResult<Res> {
let a = data[start];
@ -237,9 +359,17 @@ pub mod reader {
}
}
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 uint, next: tag.next })
} else {
vuint_at(data, tag.next)
}
}
pub fn doc_at<'a>(data: &'a [u8], start: uint) -> DecodeResult<TaggedDoc<'a>> {
let elt_tag = try!(vuint_at(data, start));
let elt_size = try!(vuint_at(data, elt_tag.next));
let elt_tag = try!(tag_at(data, start));
let elt_size = try!(tag_len_at(data, elt_tag));
let end = elt_size.next + elt_size.val;
Ok(TaggedDoc {
tag: elt_tag.val,
@ -250,8 +380,8 @@ pub mod reader {
pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: uint) -> Option<Doc<'a>> {
let mut pos = d.start;
while pos < d.end {
let elt_tag = try_or!(vuint_at(d.data, pos), None);
let elt_size = try_or!(vuint_at(d.data, elt_tag.next), None);
let elt_tag = try_or!(tag_at(d.data, pos), None);
let elt_size = try_or!(tag_len_at(d.data, elt_tag), None);
pos = elt_size.next + elt_size.val;
if elt_tag.val == tg {
return Some(Doc { data: d.data, start: elt_size.next,
@ -276,8 +406,8 @@ pub mod reader {
{
let mut pos = d.start;
while pos < d.end {
let elt_tag = try_or!(vuint_at(d.data, pos), false);
let elt_size = try_or!(vuint_at(d.data, elt_tag.next), false);
let elt_tag = try_or!(tag_at(d.data, pos), false);
let elt_size = try_or!(tag_len_at(d.data, elt_tag), false);
pos = elt_size.next + elt_size.val;
let doc = Doc { data: d.data, start: elt_size.next, end: pos };
if !it(elt_tag.val, doc) {
@ -292,8 +422,8 @@ pub mod reader {
{
let mut pos = d.start;
while pos < d.end {
let elt_tag = try_or!(vuint_at(d.data, pos), false);
let elt_size = try_or!(vuint_at(d.data, elt_tag.next), false);
let elt_tag = try_or!(tag_at(d.data, pos), false);
let elt_size = try_or!(tag_len_at(d.data, elt_tag), false);
pos = elt_size.next + elt_size.val;
if elt_tag.val == tg {
let doc = Doc { data: d.data, start: elt_size.next,
@ -357,23 +487,6 @@ pub mod reader {
}
}
fn _check_label(&mut self, lbl: &str) -> DecodeResult<()> {
if self.pos < self.parent.end {
let TaggedDoc { tag: r_tag, doc: r_doc } =
try!(doc_at(self.parent.data, self.pos));
if r_tag == (EsLabel as uint) {
self.pos = r_doc.end;
let str = r_doc.as_str_slice();
if lbl != str {
return Err(Expected(format!("Expected label {:?} but \
found {:?}", lbl, str)));
}
}
}
Ok(())
}
fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<Doc<'doc>> {
debug!(". next_doc(exp_tag={:?})", exp_tag);
if self.pos >= self.parent.end {
@ -416,10 +529,66 @@ pub mod reader {
Ok(r)
}
fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<uint> {
let r = doc_as_u32(try!(self.next_doc(exp_tag)));
debug!("_next_uint exp_tag={:?} result={:?}", exp_tag, r);
Ok(r as uint)
fn _next_sub(&mut self) -> DecodeResult<uint> {
// empty vector/map optimization
if self.parent.is_empty() {
return Ok(0);
}
let TaggedDoc { tag: r_tag, doc: r_doc } =
try!(doc_at(self.parent.data, self.pos));
let r = if r_tag == (EsSub8 as uint) {
doc_as_u8(r_doc) as uint
} else if r_tag == (EsSub32 as uint) {
doc_as_u32(r_doc) as uint
} 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.
// `first_tag` should be a tag for u8 or i8.
// `last_tag` should be the largest allowed integer tag with the matching signedness.
// all tags between them should be valid, in the order of u8, u16, u32 and u64.
fn _next_int(&mut self,
first_tag: EbmlEncoderTag,
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 } =
try!(doc_at(self.parent.data, self.pos));
let r = if first_tag as uint <= r_tag && r_tag <= last_tag as uint {
match r_tag - first_tag as uint {
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) as u64,
_ => unreachable!(),
}
} else {
return Err(Expected(format!("expected EBML doc with tag {:?} through {:?} but \
found tag {:?}", first_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={:?}", first_tag, last_tag, r);
Ok(r)
}
pub fn read_opaque<R, F>(&mut self, op: F) -> DecodeResult<R> where
@ -443,12 +612,12 @@ pub mod reader {
type Error = Error;
fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) }
fn read_u64(&mut self) -> DecodeResult<u64> { Ok(doc_as_u64(try!(self.next_doc(EsU64)))) }
fn read_u32(&mut self) -> DecodeResult<u32> { Ok(doc_as_u32(try!(self.next_doc(EsU32)))) }
fn read_u16(&mut self) -> DecodeResult<u16> { Ok(doc_as_u16(try!(self.next_doc(EsU16)))) }
fn read_u8 (&mut self) -> DecodeResult<u8 > { Ok(doc_as_u8 (try!(self.next_doc(EsU8 )))) }
fn read_u64(&mut self) -> DecodeResult<u64> { self._next_int(EsU8, EsU64) }
fn read_u32(&mut self) -> DecodeResult<u32> { Ok(try!(self._next_int(EsU8, EsU32)) as u32) }
fn read_u16(&mut self) -> DecodeResult<u16> { Ok(try!(self._next_int(EsU8, EsU16)) as u16) }
fn read_u8(&mut self) -> DecodeResult<u8> { Ok(doc_as_u8(try!(self.next_doc(EsU8)))) }
fn read_uint(&mut self) -> DecodeResult<uint> {
let v = doc_as_u64(try!(self.next_doc(EsUint)));
let v = try!(self._next_int(EsU8, EsU64));
if v > (::std::usize::MAX as u64) {
Err(IntTooBig(v as uint))
} else {
@ -456,20 +625,12 @@ pub mod reader {
}
}
fn read_i64(&mut self) -> DecodeResult<i64> {
Ok(doc_as_u64(try!(self.next_doc(EsI64))) as i64)
}
fn read_i32(&mut self) -> DecodeResult<i32> {
Ok(doc_as_u32(try!(self.next_doc(EsI32))) as i32)
}
fn read_i16(&mut self) -> DecodeResult<i16> {
Ok(doc_as_u16(try!(self.next_doc(EsI16))) as i16)
}
fn read_i8 (&mut self) -> DecodeResult<i8> {
Ok(doc_as_u8(try!(self.next_doc(EsI8 ))) as i8)
}
fn read_i64(&mut self) -> DecodeResult<i64> { Ok(try!(self._next_int(EsI8, EsI64)) as i64) }
fn read_i32(&mut self) -> DecodeResult<i32> { Ok(try!(self._next_int(EsI8, EsI32)) as i32) }
fn read_i16(&mut self) -> DecodeResult<i16> { Ok(try!(self._next_int(EsI8, EsI16)) as i16) }
fn read_i8(&mut self) -> DecodeResult<i8> { Ok(doc_as_u8(try!(self.next_doc(EsI8))) as i8) }
fn read_int(&mut self) -> DecodeResult<int> {
let v = doc_as_u64(try!(self.next_doc(EsInt))) as i64;
let v = try!(self._next_int(EsI8, 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 uint))
@ -502,7 +663,6 @@ pub mod reader {
F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
{
debug!("read_enum({})", name);
try!(self._check_label(name));
let doc = try!(self.next_doc(EsEnum));
@ -522,20 +682,10 @@ pub mod reader {
where F: FnMut(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
{
debug!("read_enum_variant()");
let idx = try!(self._next_uint(EsEnumVid));
let idx = try!(self._next_sub());
debug!(" idx={}", idx);
let doc = try!(self.next_doc(EsEnumBody));
let (old_parent, old_pos) = (self.parent, self.pos);
self.parent = doc;
self.pos = self.parent.start;
let result = try!(f(self, idx));
self.parent = old_parent;
self.pos = old_pos;
Ok(result)
f(self, idx)
}
fn read_enum_variant_arg<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
@ -550,20 +700,10 @@ pub mod reader {
where F: FnMut(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
{
debug!("read_enum_struct_variant()");
let idx = try!(self._next_uint(EsEnumVid));
let idx = try!(self._next_sub());
debug!(" idx={}", idx);
let doc = try!(self.next_doc(EsEnumBody));
let (old_parent, old_pos) = (self.parent, self.pos);
self.parent = doc;
self.pos = self.parent.start;
let result = try!(f(self, idx));
self.parent = old_parent;
self.pos = old_pos;
Ok(result)
f(self, idx)
}
fn read_enum_struct_variant_field<T, F>(&mut self,
@ -588,7 +728,6 @@ pub mod reader {
F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
{
debug!("read_struct_field(name={}, idx={})", name, idx);
try!(self._check_label(name));
f(self)
}
@ -652,7 +791,7 @@ pub mod reader {
{
debug!("read_seq()");
self.push_doc(EsVec, move |d| {
let len = try!(d._next_uint(EsVecLen));
let len = try!(d._next_sub());
debug!(" len={}", len);
f(d, len)
})
@ -670,7 +809,7 @@ pub mod reader {
{
debug!("read_map()");
self.push_doc(EsMap, move |d| {
let len = try!(d._next_uint(EsMapLen));
let len = try!(d._next_sub());
debug!(" len={}", len);
f(d, len)
})
@ -701,11 +840,14 @@ pub mod writer {
use std::num::Int;
use std::old_io::{Writer, Seek};
use std::old_io;
use std::slice::bytes;
use std::num::ToPrimitive;
use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey,
EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8,
EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint,
EsOpaque, EsLabel, EbmlEncoderTag };
use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey,
EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8,
EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
EsOpaque, NUM_IMPLICIT_TAGS, NUM_TAGS };
use super::io::SeekableMemWriter;
use serialize;
@ -713,9 +855,24 @@ pub mod writer {
pub type EncodeResult = old_io::IoResult<()>;
// rbml writing
pub struct Encoder<'a, W:'a> {
pub writer: &'a mut W,
pub struct Encoder<'a> {
pub writer: &'a mut SeekableMemWriter,
size_positions: Vec<uint>,
relax_limit: u64, // do not move encoded bytes before this position
}
fn write_tag<W: Writer>(w: &mut W, n: uint) -> EncodeResult {
if n < 0xf0 {
w.write_all(&[n as u8])
} else if 0x100 <= n && n < NUM_TAGS {
w.write_all(&[0xf0 | (n >> 8) as u8, n as u8])
} else {
Err(old_io::IoError {
kind: old_io::OtherIoError,
desc: "invalid tag",
detail: Some(format!("{}", n))
})
}
}
fn write_sized_vuint<W: Writer>(w: &mut W, n: uint, size: uint) -> EncodeResult {
@ -746,27 +903,30 @@ pub mod writer {
})
}
impl<'a, W: Writer + Seek> Encoder<'a, W> {
pub fn new(w: &'a mut W) -> Encoder<'a, W> {
impl<'a> Encoder<'a> {
pub fn new(w: &'a mut SeekableMemWriter) -> Encoder<'a> {
Encoder {
writer: w,
size_positions: vec!(),
relax_limit: 0,
}
}
/// FIXME(pcwalton): Workaround for badness in trans. DO NOT USE ME.
pub unsafe fn unsafe_clone(&self) -> Encoder<'a, W> {
pub unsafe fn unsafe_clone(&self) -> Encoder<'a> {
Encoder {
writer: mem::transmute_copy(&self.writer),
size_positions: self.size_positions.clone(),
relax_limit: self.relax_limit,
}
}
pub fn start_tag(&mut self, tag_id: uint) -> EncodeResult {
debug!("Start tag {:?}", tag_id);
assert!(tag_id >= NUM_IMPLICIT_TAGS);
// Write the enum ID:
try!(write_vuint(self.writer, tag_id));
try!(write_tag(self.writer, tag_id));
// Write a placeholder four-byte size.
self.size_positions.push(try!(self.writer.tell()) as uint);
@ -779,11 +939,29 @@ pub mod writer {
let cur_pos = try!(self.writer.tell());
try!(self.writer.seek(last_size_pos as i64, old_io::SeekSet));
let size = cur_pos as uint - last_size_pos - 4;
try!(write_sized_vuint(self.writer, size, 4));
let r = try!(self.writer.seek(cur_pos as i64, old_io::SeekSet));
// relax the size encoding for small tags (bigger tags are costly to move).
// we should never try to move the stable positions, however.
const RELAX_MAX_SIZE: uint = 0x100;
if size <= RELAX_MAX_SIZE && last_size_pos >= self.relax_limit as uint {
// we can't alter the buffer in place, so have a temporary buffer
let mut buf = [0u8; RELAX_MAX_SIZE];
{
let data = &self.writer.get_ref()[last_size_pos+4..cur_pos as uint];
bytes::copy_memory(&mut buf, data);
}
// overwrite the size and data and continue
try!(write_vuint(self.writer, size));
try!(self.writer.write_all(&buf[..size]));
} else {
// overwrite the size with an overlong encoding and skip past the data
try!(write_sized_vuint(self.writer, size, 4));
try!(self.writer.seek(cur_pos as i64, old_io::SeekSet));
}
debug!("End tag (size = {:?})", size);
Ok(r)
Ok(())
}
pub fn wr_tag<F>(&mut self, tag_id: uint, blk: F) -> EncodeResult where
@ -795,7 +973,8 @@ pub mod writer {
}
pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) -> EncodeResult {
try!(write_vuint(self.writer, tag_id));
assert!(tag_id >= NUM_IMPLICIT_TAGS);
try!(write_tag(self.writer, tag_id));
try!(write_vuint(self.writer, b.len()));
self.writer.write_all(b)
}
@ -839,6 +1018,47 @@ pub mod writer {
self.wr_tagged_bytes(tag_id, v.as_bytes())
}
// for auto-serialization
fn wr_tagged_raw_bytes(&mut self, tag_id: uint, b: &[u8]) -> EncodeResult {
try!(write_tag(self.writer, tag_id));
self.writer.write_all(b)
}
fn wr_tagged_raw_u64(&mut self, tag_id: uint, 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: uint, 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: uint, 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: uint, v: u8) -> EncodeResult {
self.wr_tagged_raw_bytes(tag_id, &[v])
}
fn wr_tagged_raw_i64(&mut self, tag_id: uint, v: i64) -> EncodeResult {
self.wr_tagged_raw_u64(tag_id, v as u64)
}
fn wr_tagged_raw_i32(&mut self, tag_id: uint, v: i32) -> EncodeResult {
self.wr_tagged_raw_u32(tag_id, v as u32)
}
fn wr_tagged_raw_i16(&mut self, tag_id: uint, v: i16) -> EncodeResult {
self.wr_tagged_raw_u16(tag_id, v as u16)
}
fn wr_tagged_raw_i8(&mut self, tag_id: uint, 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)
@ -848,38 +1068,36 @@ pub mod writer {
debug!("Write str: {:?}", s);
self.writer.write_all(s.as_bytes())
}
/// Returns the current position while marking it stable, i.e.
/// generated bytes so far woundn't be affected by relaxation.
pub fn mark_stable_position(&mut self) -> u64 {
let pos = self.writer.tell().unwrap();
if self.relax_limit < pos {
self.relax_limit = pos;
}
pos
}
}
// FIXME (#2743): optionally perform "relaxations" on end_tag to more
// efficiently encode sizes; this is a fixed point iteration
// Set to true to generate more debugging in EBML code.
// Totally lame approach.
#[cfg(not(ndebug))]
static DEBUG: bool = true;
#[cfg(ndebug)]
static DEBUG: bool = false;
impl<'a, W: Writer + Seek> Encoder<'a, W> {
impl<'a> Encoder<'a> {
// used internally to emit things like the vector length and so on
fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) -> EncodeResult {
assert!(v <= 0xFFFF_FFFF);
self.wr_tagged_u32(t as uint, v as u32)
}
fn _emit_label(&mut self, label: &str) -> EncodeResult {
// There are various strings that we have access to, such as
// the name of a record field, which do not actually appear in
// the encoded EBML (normally). This is just for
// efficiency. When debugging, though, we can emit such
// labels and then they will be checked by decoder to
// try and check panics more quickly.
if DEBUG { self.wr_tagged_str(EsLabel as uint, label) }
else { Ok(()) }
fn _emit_tagged_sub(&mut self, v: uint) -> EncodeResult {
if let Some(v) = v.to_u8() {
self.wr_tagged_raw_u8(EsSub8 as uint, v)
} else if let Some(v) = v.to_u32() {
self.wr_tagged_raw_u32(EsSub32 as uint, v)
} else {
Err(old_io::IoError {
kind: old_io::OtherIoError,
desc: "length or variant id too big",
detail: Some(format!("{}", v))
})
}
}
pub fn emit_opaque<F>(&mut self, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<W>) -> EncodeResult,
F: FnOnce(&mut Encoder) -> EncodeResult,
{
try!(self.start_tag(EsOpaque as uint));
try!(f(self));
@ -887,7 +1105,7 @@ pub mod writer {
}
}
impl<'a, W: Writer + Seek> serialize::Encoder for Encoder<'a, W> {
impl<'a> serialize::Encoder for Encoder<'a> {
type Error = old_io::IoError;
fn emit_nil(&mut self) -> EncodeResult {
@ -895,61 +1113,78 @@ pub mod writer {
}
fn emit_uint(&mut self, v: uint) -> EncodeResult {
self.wr_tagged_u64(EsUint as uint, v as u64)
self.emit_u64(v as u64)
}
fn emit_u64(&mut self, v: u64) -> EncodeResult {
self.wr_tagged_u64(EsU64 as uint, v)
match v.to_u32() {
Some(v) => self.emit_u32(v),
None => self.wr_tagged_raw_u64(EsU64 as uint, v)
}
}
fn emit_u32(&mut self, v: u32) -> EncodeResult {
self.wr_tagged_u32(EsU32 as uint, v)
match v.to_u16() {
Some(v) => self.emit_u16(v),
None => self.wr_tagged_raw_u32(EsU32 as uint, v)
}
}
fn emit_u16(&mut self, v: u16) -> EncodeResult {
self.wr_tagged_u16(EsU16 as uint, v)
match v.to_u8() {
Some(v) => self.emit_u8(v),
None => self.wr_tagged_raw_u16(EsU16 as uint, v)
}
}
fn emit_u8(&mut self, v: u8) -> EncodeResult {
self.wr_tagged_u8(EsU8 as uint, v)
self.wr_tagged_raw_u8(EsU8 as uint, v)
}
fn emit_int(&mut self, v: int) -> EncodeResult {
self.wr_tagged_i64(EsInt as uint, v as i64)
self.emit_i64(v as i64)
}
fn emit_i64(&mut self, v: i64) -> EncodeResult {
self.wr_tagged_i64(EsI64 as uint, v)
match v.to_i32() {
Some(v) => self.emit_i32(v),
None => self.wr_tagged_raw_i64(EsI64 as uint, v)
}
}
fn emit_i32(&mut self, v: i32) -> EncodeResult {
self.wr_tagged_i32(EsI32 as uint, v)
match v.to_i16() {
Some(v) => self.emit_i16(v),
None => self.wr_tagged_raw_i32(EsI32 as uint, v)
}
}
fn emit_i16(&mut self, v: i16) -> EncodeResult {
self.wr_tagged_i16(EsI16 as uint, v)
match v.to_i8() {
Some(v) => self.emit_i8(v),
None => self.wr_tagged_raw_i16(EsI16 as uint, v)
}
}
fn emit_i8(&mut self, v: i8) -> EncodeResult {
self.wr_tagged_i8(EsI8 as uint, v)
self.wr_tagged_raw_i8(EsI8 as uint, v)
}
fn emit_bool(&mut self, v: bool) -> EncodeResult {
self.wr_tagged_u8(EsBool as uint, v as u8)
self.wr_tagged_raw_u8(EsBool as uint, v as u8)
}
fn emit_f64(&mut self, v: f64) -> EncodeResult {
let bits = unsafe { mem::transmute(v) };
self.wr_tagged_u64(EsF64 as uint, bits)
self.wr_tagged_raw_u64(EsF64 as uint, bits)
}
fn emit_f32(&mut self, v: f32) -> EncodeResult {
let bits = unsafe { mem::transmute(v) };
self.wr_tagged_u32(EsF32 as uint, bits)
self.wr_tagged_raw_u32(EsF32 as uint, bits)
}
fn emit_char(&mut self, v: char) -> EncodeResult {
self.wr_tagged_u32(EsChar as uint, v as u32)
self.wr_tagged_raw_u32(EsChar as uint, v as u32)
}
fn emit_str(&mut self, v: &str) -> EncodeResult {
self.wr_tagged_str(EsStr as uint, v)
}
fn emit_enum<F>(&mut self, name: &str, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
try!(self._emit_label(name));
try!(self.start_tag(EsEnum as uint));
try!(f(self));
self.end_tag()
@ -960,16 +1195,14 @@ pub mod writer {
v_id: uint,
_: uint,
f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
try!(self._emit_tagged_uint(EsEnumVid, v_id));
try!(self.start_tag(EsEnumBody as uint));
try!(f(self));
self.end_tag()
try!(self._emit_tagged_sub(v_id));
f(self)
}
fn emit_enum_variant_arg<F>(&mut self, _: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
f(self)
}
@ -979,7 +1212,7 @@ pub mod writer {
v_id: uint,
cnt: uint,
f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
self.emit_enum_variant(v_name, v_id, cnt, f)
}
@ -988,48 +1221,47 @@ pub mod writer {
_: &str,
idx: uint,
f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
self.emit_enum_variant_arg(idx, f)
}
fn emit_struct<F>(&mut self, _: &str, _len: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
f(self)
}
fn emit_struct_field<F>(&mut self, name: &str, _: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
fn emit_struct_field<F>(&mut self, _name: &str, _: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
try!(self._emit_label(name));
f(self)
}
fn emit_tuple<F>(&mut self, len: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
self.emit_seq(len, f)
}
fn emit_tuple_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
self.emit_seq_elt(idx, f)
}
fn emit_tuple_struct<F>(&mut self, _: &str, len: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
self.emit_seq(len, f)
}
fn emit_tuple_struct_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
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, W>) -> EncodeResult,
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
self.emit_enum("Option", f)
}
@ -1037,24 +1269,28 @@ pub mod writer {
self.emit_enum_variant("None", 0, 0, |_| Ok(()))
}
fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
self.emit_enum_variant("Some", 1, 1, f)
}
fn emit_seq<F>(&mut self, len: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
if len == 0 {
// empty vector optimization
return self.wr_tagged_bytes(EsVec as uint, &[]);
}
try!(self.start_tag(EsVec as uint));
try!(self._emit_tagged_uint(EsVecLen, len));
try!(self._emit_tagged_sub(len));
try!(f(self));
self.end_tag()
}
fn emit_seq_elt<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
try!(self.start_tag(EsVecElt as uint));
@ -1063,17 +1299,21 @@ pub mod writer {
}
fn emit_map<F>(&mut self, len: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
if len == 0 {
// empty map optimization
return self.wr_tagged_bytes(EsMap as uint, &[]);
}
try!(self.start_tag(EsMap as uint));
try!(self._emit_tagged_uint(EsMapLen, len));
try!(self._emit_tagged_sub(len));
try!(f(self));
self.end_tag()
}
fn emit_map_elt_key<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
try!(self.start_tag(EsMapKey as uint));
@ -1082,7 +1322,7 @@ pub mod writer {
}
fn emit_map_elt_val<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
{
try!(self.start_tag(EsMapVal as uint));
try!(f(self));

View file

@ -1,4 +1,4 @@
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// 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.
//
@ -14,85 +14,90 @@ pub use self::astencode_tag::*;
use back::svh::Svh;
// EBML enum definitions and utils shared by the encoder and decoder
// 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_items: uint = 0x00;
pub const tag_items: uint = 0x100; // top-level only
pub const tag_paths_data_name: uint = 0x01;
pub const tag_paths_data_name: uint = 0x20;
pub const tag_def_id: uint = 0x02;
pub const tag_def_id: uint = 0x21;
pub const tag_items_data: uint = 0x03;
pub const tag_items_data: uint = 0x22;
pub const tag_items_data_item: uint = 0x04;
pub const tag_items_data_item: uint = 0x23;
pub const tag_items_data_item_family: uint = 0x05;
pub const tag_items_data_item_family: uint = 0x24;
pub const tag_items_data_item_type: uint = 0x07;
pub const tag_items_data_item_type: uint = 0x25;
pub const tag_items_data_item_symbol: uint = 0x08;
pub const tag_items_data_item_symbol: uint = 0x26;
pub const tag_items_data_item_variant: uint = 0x09;
pub const tag_items_data_item_variant: uint = 0x27;
pub const tag_items_data_parent_item: uint = 0x0a;
pub const tag_items_data_parent_item: uint = 0x28;
pub const tag_items_data_item_is_tuple_struct_ctor: uint = 0x0b;
pub const tag_items_data_item_is_tuple_struct_ctor: uint = 0x29;
pub const tag_index: uint = 0x0c;
pub const tag_index: uint = 0x2a;
pub const tag_index_buckets: uint = 0x0d;
pub const tag_index_buckets: uint = 0x2b;
pub const tag_index_buckets_bucket: uint = 0x0e;
pub const tag_index_buckets_bucket: uint = 0x2c;
pub const tag_index_buckets_bucket_elt: uint = 0x0f;
pub const tag_index_buckets_bucket_elt: uint = 0x2d;
pub const tag_index_table: uint = 0x10;
pub const tag_index_table: uint = 0x2e;
pub const tag_meta_item_name_value: uint = 0x11;
pub const tag_meta_item_name_value: uint = 0x2f;
pub const tag_meta_item_name: uint = 0x12;
pub const tag_meta_item_name: uint = 0x30;
pub const tag_meta_item_value: uint = 0x13;
pub const tag_meta_item_value: uint = 0x31;
pub const tag_attributes: uint = 0x14;
pub const tag_attributes: uint = 0x101; // top-level only
pub const tag_attribute: uint = 0x15;
pub const tag_attribute: uint = 0x32;
pub const tag_meta_item_word: uint = 0x16;
pub const tag_meta_item_word: uint = 0x33;
pub const tag_meta_item_list: uint = 0x17;
pub const tag_meta_item_list: uint = 0x34;
// The list of crates that this crate depends on
pub const tag_crate_deps: uint = 0x18;
pub const tag_crate_deps: uint = 0x102; // top-level only
// A single crate dependency
pub const tag_crate_dep: uint = 0x19;
pub const tag_crate_dep: uint = 0x35;
pub const tag_crate_hash: uint = 0x1a;
pub const tag_crate_crate_name: uint = 0x1b;
pub const tag_crate_hash: uint = 0x103; // top-level only
pub const tag_crate_crate_name: uint = 0x104; // top-level only
pub const tag_crate_dep_crate_name: uint = 0x1d;
pub const tag_crate_dep_hash: uint = 0x1e;
pub const tag_crate_dep_crate_name: uint = 0x36;
pub const tag_crate_dep_hash: uint = 0x37;
pub const tag_mod_impl: uint = 0x1f;
pub const tag_mod_impl: uint = 0x38;
pub const tag_item_trait_item: uint = 0x20;
pub const tag_item_trait_item: uint = 0x39;
pub const tag_item_trait_ref: uint = 0x21;
pub const tag_item_super_trait_ref: uint = 0x22;
pub const tag_item_trait_ref: uint = 0x3a;
pub const tag_item_super_trait_ref: uint = 0x3b;
// discriminator value for variants
pub const tag_disr_val: uint = 0x23;
pub const tag_disr_val: uint = 0x3c;
// used to encode ast_map::PathElem
pub const tag_path: uint = 0x24;
pub const tag_path_len: uint = 0x25;
pub const tag_path_elem_mod: uint = 0x26;
pub const tag_path_elem_name: uint = 0x27;
pub const tag_item_field: uint = 0x28;
pub const tag_item_field_origin: uint = 0x29;
pub const tag_path: uint = 0x3d;
pub const tag_path_len: uint = 0x3e;
pub const tag_path_elem_mod: uint = 0x3f;
pub const tag_path_elem_name: uint = 0x40;
pub const tag_item_field: uint = 0x41;
pub const tag_item_field_origin: uint = 0x42;
pub const tag_item_variances: uint = 0x2a;
pub const tag_item_variances: uint = 0x43;
/*
trait items contain tag_item_trait_item elements,
impl items contain tag_item_impl_item elements, and classes
@ -101,60 +106,59 @@ pub const tag_item_variances: uint = 0x2a;
both, tag_item_trait_item and tag_item_impl_item have to be two
different tags.
*/
pub const tag_item_impl_item: uint = 0x30;
pub const tag_item_trait_method_explicit_self: uint = 0x31;
pub const tag_item_impl_item: uint = 0x44;
pub const tag_item_trait_method_explicit_self: uint = 0x45;
// Reexports are found within module tags. Each reexport contains def_ids
// and names.
pub const tag_items_data_item_reexport: uint = 0x38;
pub const tag_items_data_item_reexport_def_id: uint = 0x39;
pub const tag_items_data_item_reexport_name: uint = 0x3a;
pub const tag_items_data_item_reexport: uint = 0x46;
pub const tag_items_data_item_reexport_def_id: uint = 0x47;
pub const tag_items_data_item_reexport_name: uint = 0x48;
// used to encode crate_ctxt side tables
#[derive(Copy, PartialEq, FromPrimitive)]
#[repr(uint)]
pub enum astencode_tag { // Reserves 0x40 -- 0x5f
tag_ast = 0x40,
pub enum astencode_tag { // Reserves 0x50 -- 0x6f
tag_ast = 0x50,
tag_tree = 0x41,
tag_tree = 0x51,
tag_id_range = 0x42,
tag_id_range = 0x52,
tag_table = 0x43,
tag_table_id = 0x44,
tag_table_val = 0x45,
tag_table_def = 0x46,
tag_table_node_type = 0x47,
tag_table_item_subst = 0x48,
tag_table_freevars = 0x49,
tag_table_tcache = 0x4a,
tag_table_param_defs = 0x4b,
tag_table_mutbl = 0x4c,
tag_table_last_use = 0x4d,
tag_table_spill = 0x4e,
tag_table_method_map = 0x4f,
tag_table_vtable_map = 0x50,
tag_table_adjustments = 0x51,
tag_table_moves_map = 0x52,
tag_table_capture_map = 0x53,
tag_table_closure_tys = 0x54,
tag_table_closure_kinds = 0x55,
tag_table_upvar_capture_map = 0x56,
tag_table_capture_modes = 0x57,
tag_table_object_cast_map = 0x58,
tag_table_const_qualif = 0x59,
tag_table = 0x53,
// GAP 0x54, 0x55
tag_table_def = 0x56,
tag_table_node_type = 0x57,
tag_table_item_subst = 0x58,
tag_table_freevars = 0x59,
tag_table_tcache = 0x5a,
tag_table_param_defs = 0x5b,
tag_table_mutbl = 0x5c,
tag_table_last_use = 0x5d,
tag_table_spill = 0x5e,
tag_table_method_map = 0x5f,
tag_table_vtable_map = 0x60,
tag_table_adjustments = 0x61,
tag_table_moves_map = 0x62,
tag_table_capture_map = 0x63,
tag_table_closure_tys = 0x64,
tag_table_closure_kinds = 0x65,
tag_table_upvar_capture_map = 0x66,
tag_table_capture_modes = 0x67,
tag_table_object_cast_map = 0x68,
tag_table_const_qualif = 0x69,
}
pub const tag_item_trait_item_sort: uint = 0x60;
pub const tag_item_trait_item_sort: uint = 0x70;
pub const tag_item_trait_parent_sort: uint = 0x61;
pub const tag_item_trait_parent_sort: uint = 0x71;
pub const tag_item_impl_type_basename: uint = 0x62;
pub const tag_item_impl_type_basename: uint = 0x72;
pub const tag_crate_triple: uint = 0x66;
pub const tag_crate_triple: uint = 0x105; // top-level only
pub const tag_dylib_dependency_formats: uint = 0x67;
pub const tag_dylib_dependency_formats: uint = 0x106; // top-level only
// Language items are a top-level directory (for speed). Hierarchy:
//
@ -163,51 +167,47 @@ pub const tag_dylib_dependency_formats: uint = 0x67;
// - tag_lang_items_item_id: u32
// - tag_lang_items_item_node_id: u32
pub const tag_lang_items: uint = 0x70;
pub const tag_lang_items_item: uint = 0x71;
pub const tag_lang_items_item_id: uint = 0x72;
pub const tag_lang_items_item_node_id: uint = 0x73;
pub const tag_lang_items_missing: uint = 0x74;
pub const tag_lang_items: uint = 0x107; // top-level only
pub const tag_lang_items_item: uint = 0x73;
pub const tag_lang_items_item_id: uint = 0x74;
pub const tag_lang_items_item_node_id: uint = 0x75;
pub const tag_lang_items_missing: uint = 0x76;
pub const tag_item_unnamed_field: uint = 0x75;
pub const tag_items_data_item_visibility: uint = 0x76;
pub const tag_item_unnamed_field: uint = 0x77;
pub const tag_items_data_item_visibility: uint = 0x78;
pub const tag_item_method_tps: uint = 0x79;
pub const tag_item_method_fty: uint = 0x7a;
pub const tag_mod_child: uint = 0x7b;
pub const tag_misc_info: uint = 0x7c;
pub const tag_misc_info_crate_items: uint = 0x7d;
pub const tag_misc_info: uint = 0x108; // top-level only
pub const tag_misc_info_crate_items: uint = 0x7c;
pub const tag_item_method_provided_source: uint = 0x7e;
pub const tag_item_impl_vtables: uint = 0x7f;
pub const tag_item_method_provided_source: uint = 0x7d;
pub const tag_item_impl_vtables: uint = 0x7e;
pub const tag_impls: uint = 0x80;
pub const tag_impls_impl: uint = 0x81;
pub const tag_impls: uint = 0x109; // top-level only
pub const tag_impls_impl: uint = 0x7f;
pub const tag_items_data_item_inherent_impl: uint = 0x82;
pub const tag_items_data_item_extension_impl: uint = 0x83;
pub const tag_items_data_item_inherent_impl: uint = 0x80;
pub const tag_items_data_item_extension_impl: uint = 0x81;
// GAP 0x84, 0x85, 0x86
pub const tag_native_libraries: uint = 0x10a; // top-level only
pub const tag_native_libraries_lib: uint = 0x82;
pub const tag_native_libraries_name: uint = 0x83;
pub const tag_native_libraries_kind: uint = 0x84;
pub const tag_native_libraries: uint = 0x87;
pub const tag_native_libraries_lib: uint = 0x88;
pub const tag_native_libraries_name: uint = 0x89;
pub const tag_native_libraries_kind: uint = 0x8a;
pub const tag_plugin_registrar_fn: uint = 0x10b; // top-level only
pub const tag_plugin_registrar_fn: uint = 0x8b;
pub const tag_method_argument_names: uint = 0x85;
pub const tag_method_argument_name: uint = 0x86;
// GAP 0x8c, 0x8d
pub const tag_reachable_extern_fns: uint = 0x10c; // top-level only
pub const tag_reachable_extern_fn_id: uint = 0x87;
pub const tag_method_argument_names: uint = 0x8e;
pub const tag_method_argument_name: uint = 0x8f;
pub const tag_items_data_item_stability: uint = 0x88;
pub const tag_reachable_extern_fns: uint = 0x90;
pub const tag_reachable_extern_fn_id: uint = 0x91;
pub const tag_items_data_item_stability: uint = 0x92;
pub const tag_items_data_item_repr: uint = 0x93;
pub const tag_items_data_item_repr: uint = 0x89;
#[derive(Clone, Debug)]
pub struct LinkMeta {
@ -215,42 +215,40 @@ pub struct LinkMeta {
pub crate_hash: Svh,
}
// GAP 0x94...0x98
pub const tag_struct_fields: uint = 0x10d; // top-level only
pub const tag_struct_field: uint = 0x8a;
pub const tag_struct_field_id: uint = 0x8b;
pub const tag_struct_fields: uint = 0x99;
pub const tag_struct_field: uint = 0x9a;
pub const tag_struct_field_id: uint = 0x9b;
pub const tag_attribute_is_sugared_doc: uint = 0x8c;
pub const tag_attribute_is_sugared_doc: uint = 0x9c;
pub const tag_trait_def_bounds: uint = 0x8d;
pub const tag_trait_def_bounds: uint = 0x9d;
pub const tag_items_data_region: uint = 0x8e;
pub const tag_items_data_region: uint = 0x9e;
pub const tag_region_param_def: uint = 0x8f;
pub const tag_region_param_def_ident: uint = 0x90;
pub const tag_region_param_def_def_id: uint = 0x91;
pub const tag_region_param_def_space: uint = 0x92;
pub const tag_region_param_def_index: uint = 0x93;
pub const tag_region_param_def: uint = 0xa0;
pub const tag_region_param_def_ident: uint = 0xa1;
pub const tag_region_param_def_def_id: uint = 0xa2;
pub const tag_region_param_def_space: uint = 0xa3;
pub const tag_region_param_def_index: uint = 0xa4;
pub const tag_type_param_def: uint = 0x94;
pub const tag_type_param_def: uint = 0xa5;
pub const tag_item_generics: uint = 0x95;
pub const tag_method_ty_generics: uint = 0x96;
pub const tag_item_generics: uint = 0xa6;
pub const tag_method_ty_generics: uint = 0xa7;
pub const tag_predicate: uint = 0x97;
pub const tag_predicate_space: uint = 0x98;
pub const tag_predicate_data: uint = 0x99;
pub const tag_predicate: uint = 0xa8;
pub const tag_predicate_space: uint = 0xa9;
pub const tag_predicate_data: uint = 0xb0;
pub const tag_unsafety: uint = 0x9a;
pub const tag_unsafety: uint = 0xb1;
pub const tag_associated_type_names: uint = 0x9b;
pub const tag_associated_type_name: uint = 0x9c;
pub const tag_associated_type_names: uint = 0xb2;
pub const tag_associated_type_name: uint = 0xb3;
pub const tag_polarity: uint = 0x9d;
pub const tag_polarity: uint = 0xb4;
pub const tag_macro_defs: uint = 0x10e; // top-level only
pub const tag_macro_def: uint = 0x9e;
pub const tag_macro_def_body: uint = 0x9f;
pub const tag_macro_defs: uint = 0xb5;
pub const tag_macro_def: uint = 0xb6;
pub const tag_macro_def_body: uint = 0xb7;
pub const tag_paren_sugar: uint = 0xb8;
pub const tag_paren_sugar: uint = 0xa0;

View file

@ -1,4 +1,4 @@
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// 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.
//
@ -46,7 +46,7 @@ use syntax::ptr::P;
use syntax::visit::Visitor;
use syntax::visit;
use syntax;
use rbml::writer;
use rbml::writer::Encoder;
use rbml::io::SeekableMemWriter;
/// A borrowed version of `ast::InlinedItem`.
@ -57,8 +57,6 @@ pub enum InlinedItemRef<'a> {
IIForeignRef(&'a ast::ForeignItem)
}
pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
pub type EncodeInlinedItem<'a> =
Box<FnMut(&EncodeContext, &mut Encoder, InlinedItemRef) + 'a>;
@ -115,15 +113,13 @@ fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder,
};
rbml_w.start_tag(tag);
tyencode::enc_trait_ref(rbml_w.writer, ty_str_ctxt, trait_ref);
tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, trait_ref);
rbml_w.end_tag();
}
// Item info table encoding
fn encode_family(rbml_w: &mut Encoder, c: char) {
rbml_w.start_tag(tag_items_data_item_family);
rbml_w.writer.write_all(&[c as u8]);
rbml_w.end_tag();
rbml_w.wr_tagged_u8(tag_items_data_item_family, c as u8);
}
pub fn def_to_string(did: DefId) -> String {
@ -157,14 +153,9 @@ fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
}
fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) {
rbml_w.start_tag(tag_items_data_item_variant);
let s = def_to_string(vid);
rbml_w.writer.write_all(s.as_bytes());
rbml_w.end_tag();
rbml_w.start_tag(tag_mod_child);
rbml_w.wr_str(&s[..]);
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_items_data_item_variant, &s[..]);
rbml_w.wr_tagged_str(tag_mod_child, &s[..]);
}
pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
@ -176,7 +167,7 @@ pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
tyencode::enc_closure_ty(rbml_w.writer, ty_str_ctxt, closure_type);
tyencode::enc_closure_ty(rbml_w, ty_str_ctxt, closure_type);
}
pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
@ -188,7 +179,7 @@ pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
tyencode::enc_ty(rbml_w.writer, ty_str_ctxt, typ);
tyencode::enc_ty(rbml_w, ty_str_ctxt, typ);
}
pub fn write_trait_ref<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
@ -200,7 +191,7 @@ pub fn write_trait_ref<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
tyencode::enc_trait_ref(rbml_w.writer, ty_str_ctxt, trait_ref);
tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, trait_ref);
}
pub fn write_region(ecx: &EncodeContext,
@ -212,7 +203,7 @@ pub fn write_region(ecx: &EncodeContext,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
tyencode::enc_region(rbml_w.writer, ty_str_ctxt, r);
tyencode::enc_region(rbml_w, ty_str_ctxt, r);
}
fn encode_bounds<'a, 'tcx>(rbml_w: &mut Encoder,
@ -225,7 +216,7 @@ fn encode_bounds<'a, 'tcx>(rbml_w: &mut Encoder,
ds: def_to_string,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs };
tyencode::enc_bounds(rbml_w.writer, ty_str_ctxt, bounds);
tyencode::enc_bounds(rbml_w, ty_str_ctxt, bounds);
rbml_w.end_tag();
}
@ -257,7 +248,7 @@ fn encode_method_fty<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
tyencode::enc_bare_fn_ty(rbml_w.writer, ty_str_ctxt, typ);
tyencode::enc_bare_fn_ty(rbml_w, ty_str_ctxt, typ);
rbml_w.end_tag();
}
@ -265,34 +256,26 @@ fn encode_method_fty<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
fn encode_symbol(ecx: &EncodeContext,
rbml_w: &mut Encoder,
id: NodeId) {
rbml_w.start_tag(tag_items_data_item_symbol);
match ecx.item_symbols.borrow().get(&id) {
Some(x) => {
debug!("encode_symbol(id={}, str={})", id, *x);
rbml_w.writer.write_all(x.as_bytes());
rbml_w.wr_tagged_str(tag_items_data_item_symbol, x);
}
None => {
ecx.diag.handler().bug(
&format!("encode_symbol: id not found {}", id));
}
}
rbml_w.end_tag();
}
fn encode_disr_val(_: &EncodeContext,
rbml_w: &mut Encoder,
disr_val: ty::Disr) {
rbml_w.start_tag(tag_disr_val);
let s = disr_val.to_string();
rbml_w.writer.write_all(s.as_bytes());
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_disr_val, &disr_val.to_string());
}
fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
rbml_w.start_tag(tag_items_data_parent_item);
let s = def_to_string(id);
rbml_w.writer.write_all(s.as_bytes());
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_items_data_parent_item, &def_to_string(id));
}
fn encode_struct_fields(rbml_w: &mut Encoder,
@ -307,10 +290,7 @@ fn encode_struct_fields(rbml_w: &mut Encoder,
}
encode_struct_field_family(rbml_w, f.vis);
encode_def_id(rbml_w, f.id);
rbml_w.start_tag(tag_item_field_origin);
let s = def_to_string(origin);
rbml_w.writer.write_all(s.as_bytes());
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_item_field_origin, &def_to_string(origin));
rbml_w.end_tag();
}
}
@ -330,7 +310,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
let def_id = local_def(variant.node.id);
index.push(entry {
val: variant.node.id as i64,
pos: rbml_w.writer.tell().unwrap(),
pos: rbml_w.mark_stable_position(),
});
rbml_w.start_tag(tag_items_data_item);
encode_def_id(rbml_w, def_id);
@ -393,14 +373,11 @@ fn encode_reexported_static_method(rbml_w: &mut Encoder,
debug!("(encode reexported static method) {}::{}",
exp.name, token::get_name(method_name));
rbml_w.start_tag(tag_items_data_item_reexport);
rbml_w.start_tag(tag_items_data_item_reexport_def_id);
rbml_w.wr_str(&def_to_string(method_def_id));
rbml_w.end_tag();
rbml_w.start_tag(tag_items_data_item_reexport_name);
rbml_w.wr_str(&format!("{}::{}",
exp.name,
token::get_name(method_name)));
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_items_data_item_reexport_def_id,
&def_to_string(method_def_id));
rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
&format!("{}::{}", exp.name,
token::get_name(method_name)));
rbml_w.end_tag();
}
@ -536,12 +513,10 @@ fn encode_reexports(ecx: &EncodeContext,
exp.def_id.node,
id);
rbml_w.start_tag(tag_items_data_item_reexport);
rbml_w.start_tag(tag_items_data_item_reexport_def_id);
rbml_w.wr_str(&def_to_string(exp.def_id));
rbml_w.end_tag();
rbml_w.start_tag(tag_items_data_item_reexport_name);
rbml_w.wr_str(exp.name.as_str());
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_items_data_item_reexport_def_id,
&def_to_string(exp.def_id));
rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
exp.name.as_str());
rbml_w.end_tag();
encode_reexported_static_methods(ecx, rbml_w, path.clone(), exp);
}
@ -569,15 +544,12 @@ fn encode_info_for_mod(ecx: &EncodeContext,
// Encode info about all the module children.
for item in &md.items {
rbml_w.start_tag(tag_mod_child);
rbml_w.wr_str(&def_to_string(local_def(item.id)));
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(local_def(item.id)));
each_auxiliary_node_id(&**item, |auxiliary_node_id| {
rbml_w.start_tag(tag_mod_child);
rbml_w.wr_str(&def_to_string(local_def(
auxiliary_node_id)));
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(local_def(auxiliary_node_id)));
true
});
@ -587,9 +559,8 @@ fn encode_info_for_mod(ecx: &EncodeContext,
token::get_ident(ident),
did, ecx.tcx.map.node_to_string(did));
rbml_w.start_tag(tag_mod_impl);
rbml_w.wr_str(&def_to_string(local_def(did)));
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_mod_impl,
&def_to_string(local_def(did)));
}
}
@ -618,67 +589,56 @@ fn encode_struct_field_family(rbml_w: &mut Encoder,
}
fn encode_visibility(rbml_w: &mut Encoder, visibility: ast::Visibility) {
rbml_w.start_tag(tag_items_data_item_visibility);
let ch = match visibility {
ast::Public => 'y',
ast::Inherited => 'i',
};
rbml_w.wr_str(&ch.to_string());
rbml_w.end_tag();
rbml_w.wr_tagged_u8(tag_items_data_item_visibility, ch as u8);
}
fn encode_explicit_self(rbml_w: &mut Encoder,
explicit_self: &ty::ExplicitSelfCategory) {
rbml_w.start_tag(tag_item_trait_method_explicit_self);
let tag = tag_item_trait_method_explicit_self;
// Encode the base self type.
match *explicit_self {
ty::StaticExplicitSelfCategory => {
rbml_w.writer.write_all(&[ 's' as u8 ]);
rbml_w.wr_tagged_bytes(tag, &['s' as u8]);
}
ty::ByValueExplicitSelfCategory => {
rbml_w.writer.write_all(&[ 'v' as u8 ]);
rbml_w.wr_tagged_bytes(tag, &['v' as u8]);
}
ty::ByBoxExplicitSelfCategory => {
rbml_w.writer.write_all(&[ '~' as u8 ]);
rbml_w.wr_tagged_bytes(tag, &['~' as u8]);
}
ty::ByReferenceExplicitSelfCategory(_, m) => {
// FIXME(#4846) encode custom lifetime
rbml_w.writer.write_all(&['&' as u8]);
encode_mutability(rbml_w, m);
let ch = encode_mutability(m);
rbml_w.wr_tagged_bytes(tag, &['&' as u8, ch]);
}
}
rbml_w.end_tag();
fn encode_mutability(rbml_w: &mut Encoder,
m: ast::Mutability) {
fn encode_mutability(m: ast::Mutability) -> u8 {
match m {
ast::MutImmutable => { rbml_w.writer.write_all(&[ 'i' as u8 ]); }
ast::MutMutable => { rbml_w.writer.write_all(&[ 'm' as u8 ]); }
ast::MutImmutable => 'i' as u8,
ast::MutMutable => 'm' as u8,
}
}
}
fn encode_item_sort(rbml_w: &mut Encoder, sort: char) {
rbml_w.start_tag(tag_item_trait_item_sort);
rbml_w.writer.write_all(&[ sort as u8 ]);
rbml_w.end_tag();
rbml_w.wr_tagged_u8(tag_item_trait_item_sort, sort as u8);
}
fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) {
rbml_w.start_tag(tag_item_trait_parent_sort);
rbml_w.writer.write_all(&[ sort as u8 ]);
rbml_w.end_tag();
rbml_w.wr_tagged_u8(tag_item_trait_parent_sort, sort as u8);
}
fn encode_provided_source(rbml_w: &mut Encoder,
source_opt: Option<DefId>) {
if let Some(source) = source_opt {
rbml_w.start_tag(tag_item_method_provided_source);
let s = def_to_string(source);
rbml_w.writer.write_all(s.as_bytes());
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_item_method_provided_source,
&def_to_string(source));
}
}
@ -697,10 +657,11 @@ fn encode_info_for_struct(ecx: &EncodeContext,
let nm = field.name;
let id = field.id.node;
index.push(entry {val: id as i64, pos: rbml_w.writer.tell().unwrap()});
let pos = rbml_w.mark_stable_position();
index.push(entry {val: id as i64, pos: pos});
global_index.push(entry {
val: id as i64,
pos: rbml_w.writer.tell().unwrap(),
pos: pos,
});
rbml_w.start_tag(tag_items_data_item);
debug!("encode_info_for_struct: doing {} {}",
@ -726,7 +687,7 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext,
struct_id: NodeId) {
index.push(entry {
val: ctor_id as i64,
pos: rbml_w.writer.tell().unwrap(),
pos: rbml_w.mark_stable_position(),
});
rbml_w.start_tag(tag_items_data_item);
@ -747,8 +708,7 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext,
// indicate that this is a tuple struct ctor, because downstream users will normally want
// the tuple struct definition, but without this there is no way for them to tell that
// they actually have a ctor rather than a normal function
rbml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
rbml_w.end_tag();
rbml_w.wr_tagged_bytes(tag_items_data_item_is_tuple_struct_ctor, &[]);
rbml_w.end_tag();
}
@ -770,7 +730,7 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
};
for param in generics.types.iter() {
rbml_w.start_tag(tag_type_param_def);
tyencode::enc_type_param_def(rbml_w.writer, ty_str_ctxt, param);
tyencode::enc_type_param_def(rbml_w, ty_str_ctxt, param);
rbml_w.end_tag();
}
@ -804,7 +764,7 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
rbml_w.wr_tagged_u8(tag_predicate_space, space as u8);
rbml_w.start_tag(tag_predicate_data);
tyencode::enc_predicate(rbml_w.writer, ty_str_ctxt, predicate);
tyencode::enc_predicate(rbml_w, ty_str_ctxt, predicate);
rbml_w.end_tag();
rbml_w.end_tag();
@ -919,12 +879,13 @@ fn encode_method_argument_names(rbml_w: &mut Encoder,
decl: &ast::FnDecl) {
rbml_w.start_tag(tag_method_argument_names);
for arg in &decl.inputs {
rbml_w.start_tag(tag_method_argument_name);
let tag = tag_method_argument_name;
if let ast::PatIdent(_, ref path1, _) = arg.pat.node {
let name = token::get_ident(path1.node);
rbml_w.writer.write_all(name.as_bytes());
rbml_w.wr_tagged_bytes(tag, name.as_bytes());
} else {
rbml_w.wr_tagged_bytes(tag, &[]);
}
rbml_w.end_tag();
}
rbml_w.end_tag();
}
@ -1002,11 +963,11 @@ fn encode_info_for_item(ecx: &EncodeContext,
vis: ast::Visibility) {
let tcx = ecx.tcx;
fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder,
index: &mut Vec<entry<i64>>) {
index.push(entry {
val: item.id as i64,
pos: rbml_w.writer.tell().unwrap(),
pos: rbml_w.mark_stable_position(),
});
}
@ -1091,9 +1052,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
// Encode all the items in this module.
for foreign_item in &fm.items {
rbml_w.start_tag(tag_mod_child);
rbml_w.wr_str(&def_to_string(local_def(foreign_item.id)));
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(local_def(foreign_item.id)));
}
encode_visibility(rbml_w, vis);
encode_stability(rbml_w, stab);
@ -1263,7 +1223,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
index.push(entry {
val: trait_item_def_id.def_id().node as i64,
pos: rbml_w.writer.tell().unwrap(),
pos: rbml_w.mark_stable_position(),
});
let trait_item_type =
@ -1339,9 +1299,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
}
rbml_w.end_tag();
rbml_w.start_tag(tag_mod_child);
rbml_w.wr_str(&def_to_string(method_def_id.def_id()));
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(method_def_id.def_id()));
}
encode_path(rbml_w, path.clone());
@ -1362,7 +1321,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
index.push(entry {
val: item_def_id.def_id().node as i64,
pos: rbml_w.writer.tell().unwrap(),
pos: rbml_w.mark_stable_position(),
});
rbml_w.start_tag(tag_items_data_item);
@ -1467,7 +1426,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
abi: abi::Abi) {
index.push(entry {
val: nitem.id as i64,
pos: rbml_w.writer.tell().unwrap(),
pos: rbml_w.mark_stable_position(),
});
rbml_w.start_tag(tag_items_data_item);
@ -1567,7 +1526,7 @@ fn encode_info_for_items(ecx: &EncodeContext,
rbml_w.start_tag(tag_items_data);
index.push(entry {
val: ast::CRATE_NODE_ID as i64,
pos: rbml_w.writer.tell().unwrap(),
pos: rbml_w.mark_stable_position(),
});
encode_info_for_mod(ecx,
rbml_w,
@ -1607,7 +1566,7 @@ fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn:
let mut bucket_locs = Vec::new();
rbml_w.start_tag(tag_index_buckets);
for bucket in &buckets {
bucket_locs.push(rbml_w.writer.tell().unwrap());
bucket_locs.push(rbml_w.mark_stable_position());
rbml_w.start_tag(tag_index_buckets_bucket);
for elt in bucket {
rbml_w.start_tag(tag_index_buckets_bucket_elt);
@ -1642,21 +1601,15 @@ fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
match mi.node {
ast::MetaWord(ref name) => {
rbml_w.start_tag(tag_meta_item_word);
rbml_w.start_tag(tag_meta_item_name);
rbml_w.writer.write_all(name.as_bytes());
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_meta_item_name, name);
rbml_w.end_tag();
}
ast::MetaNameValue(ref name, ref value) => {
match value.node {
ast::LitStr(ref value, _) => {
rbml_w.start_tag(tag_meta_item_name_value);
rbml_w.start_tag(tag_meta_item_name);
rbml_w.writer.write_all(name.as_bytes());
rbml_w.end_tag();
rbml_w.start_tag(tag_meta_item_value);
rbml_w.writer.write_all(value.as_bytes());
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_meta_item_name, name);
rbml_w.wr_tagged_str(tag_meta_item_value, value);
rbml_w.end_tag();
}
_ => {/* FIXME (#623): encode other variants */ }
@ -1664,9 +1617,7 @@ fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
}
ast::MetaList(ref name, ref items) => {
rbml_w.start_tag(tag_meta_item_list);
rbml_w.start_tag(tag_meta_item_name);
rbml_w.writer.write_all(name.as_bytes());
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_meta_item_name, name);
for inner_item in items {
encode_meta_item(rbml_w, &**inner_item);
}
@ -1760,22 +1711,9 @@ fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) {
if let Some(id) = def_id {
if id.krate == ast::LOCAL_CRATE {
rbml_w.start_tag(tag_lang_items_item);
rbml_w.start_tag(tag_lang_items_item_id);
{
let wr: &mut SeekableMemWriter = rbml_w.writer;
wr.write_be_u32(i as u32);
}
rbml_w.end_tag(); // tag_lang_items_item_id
rbml_w.start_tag(tag_lang_items_item_node_id);
{
let wr: &mut SeekableMemWriter = rbml_w.writer;
wr.write_be_u32(id.node as u32);
}
rbml_w.end_tag(); // tag_lang_items_item_node_id
rbml_w.end_tag(); // tag_lang_items_item
rbml_w.wr_tagged_u32(tag_lang_items_item_id, i as u32);
rbml_w.wr_tagged_u32(tag_lang_items_item_node_id, id.node as u32);
rbml_w.end_tag();
}
}
}
@ -1796,15 +1734,8 @@ fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) {
cstore::NativeStatic => {} // these libraries are not propagated
cstore::NativeFramework | cstore::NativeUnknown => {
rbml_w.start_tag(tag_native_libraries_lib);
rbml_w.start_tag(tag_native_libraries_kind);
rbml_w.writer.write_be_u32(kind as u32);
rbml_w.end_tag();
rbml_w.start_tag(tag_native_libraries_name);
rbml_w.writer.write_all(lib.as_bytes());
rbml_w.end_tag();
rbml_w.wr_tagged_u32(tag_native_libraries_kind, kind as u32);
rbml_w.wr_tagged_str(tag_native_libraries_name, lib);
rbml_w.end_tag();
}
}
@ -1830,9 +1761,8 @@ fn encode_macro_defs(rbml_w: &mut Encoder,
encode_name(rbml_w, def.ident.name);
encode_attributes(rbml_w, &def.attrs);
rbml_w.start_tag(tag_macro_def_body);
rbml_w.wr_str(&pprust::tts_to_string(&def.body));
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_macro_def_body,
&pprust::tts_to_string(&def.body));
rbml_w.end_tag();
}
@ -1917,15 +1847,12 @@ fn encode_misc_info(ecx: &EncodeContext,
rbml_w.start_tag(tag_misc_info);
rbml_w.start_tag(tag_misc_info_crate_items);
for item in &krate.module.items {
rbml_w.start_tag(tag_mod_child);
rbml_w.wr_str(&def_to_string(local_def(item.id)));
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(local_def(item.id)));
each_auxiliary_node_id(&**item, |auxiliary_node_id| {
rbml_w.start_tag(tag_mod_child);
rbml_w.wr_str(&def_to_string(local_def(
auxiliary_node_id)));
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(local_def(auxiliary_node_id)));
true
});
}
@ -1956,35 +1883,25 @@ fn encode_reachable_extern_fns(ecx: &EncodeContext, rbml_w: &mut Encoder) {
fn encode_crate_dep(rbml_w: &mut Encoder,
dep: decoder::CrateDep) {
rbml_w.start_tag(tag_crate_dep);
rbml_w.start_tag(tag_crate_dep_crate_name);
rbml_w.writer.write_all(dep.name.as_bytes());
rbml_w.end_tag();
rbml_w.start_tag(tag_crate_dep_hash);
rbml_w.writer.write_all(dep.hash.as_str().as_bytes());
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_crate_dep_crate_name, &dep.name);
rbml_w.wr_tagged_str(tag_crate_dep_hash, dep.hash.as_str());
rbml_w.end_tag();
}
fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
rbml_w.start_tag(tag_crate_hash);
rbml_w.writer.write_all(hash.as_str().as_bytes());
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_crate_hash, hash.as_str());
}
fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
rbml_w.start_tag(tag_crate_crate_name);
rbml_w.writer.write_all(crate_name.as_bytes());
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name);
}
fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) {
rbml_w.start_tag(tag_crate_triple);
rbml_w.writer.write_all(triple.as_bytes());
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_crate_triple, triple);
}
fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) {
rbml_w.start_tag(tag_dylib_dependency_formats);
let tag = tag_dylib_dependency_formats;
match ecx.tcx.dependency_formats.borrow().get(&config::CrateTypeDylib) {
Some(arr) => {
let s = arr.iter().enumerate().filter_map(|(i, slot)| {
@ -1993,21 +1910,28 @@ fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) {
cstore::RequireStatic => "s",
})).to_string())
}).collect::<Vec<String>>();
rbml_w.writer.write_all(s.connect(",").as_bytes());
rbml_w.wr_tagged_str(tag, &s.connect(","));
}
None => {
rbml_w.wr_tagged_str(tag, "");
}
None => {}
}
rbml_w.end_tag();
}
// NB: Increment this as you change the metadata encoding version.
#[allow(non_upper_case_globals)]
pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 1 ];
pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2 ];
pub fn encode_metadata(parms: EncodeParams, krate: &ast::Crate) -> Vec<u8> {
let mut wr = SeekableMemWriter::new();
encode_metadata_inner(&mut wr, parms, krate);
// RBML compacts the encoded bytes whenever appropriate,
// so there are some garbages left after the end of the data.
let metalen = wr.tell().unwrap() as uint;
let mut v = wr.unwrap();
v.truncate(metalen);
assert_eq!(v.len(), metalen);
// 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
@ -2089,7 +2013,7 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter,
reachable: reachable,
};
let mut rbml_w = writer::Encoder::new(wr);
let mut rbml_w = Encoder::new(wr);
encode_crate_name(&mut rbml_w, &ecx.link_meta.crate_name);
encode_crate_triple(&mut rbml_w,
@ -2180,7 +2104,7 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter,
// Get the encoded string for a type
pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> String {
let mut wr = SeekableMemWriter::new();
tyencode::enc_ty(&mut wr, &tyencode::ctxt {
tyencode::enc_ty(&mut Encoder::new(&mut wr), &tyencode::ctxt {
diag: tcx.sess.diagnostic(),
ds: def_to_string,
tcx: tcx,

View file

@ -1,4 +1,4 @@
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// 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.
//
@ -27,9 +27,9 @@ use syntax::ast;
use syntax::diagnostic::SpanHandler;
use syntax::parse::token;
use rbml::io::SeekableMemWriter;
use rbml::writer::Encoder;
macro_rules! mywrite { ($($arg:tt)*) => ({ write!($($arg)*); }) }
macro_rules! mywrite { ($w:expr, $($arg:tt)*) => ({ write!($w.writer, $($arg)*); }) }
pub struct ctxt<'a, 'tcx: 'a> {
pub diag: &'a SpanHandler,
@ -49,12 +49,14 @@ pub struct ty_abbrev {
pub type abbrev_map<'tcx> = RefCell<FnvHashMap<Ty<'tcx>, ty_abbrev>>;
pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
match cx.abbrevs.borrow_mut().get(&t) {
Some(a) => { w.write_all(a.s.as_bytes()); return; }
Some(a) => { w.writer.write_all(a.s.as_bytes()); return; }
None => {}
}
let pos = w.tell().unwrap();
// type abbreviations needs a stable position
let pos = w.mark_stable_position();
match t.sty {
ty::ty_bool => mywrite!(w, "b"),
@ -154,7 +156,7 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t
}
}
let end = w.tell().unwrap();
let end = w.mark_stable_position();
let len = end - pos;
fn estimate_sz(u: u64) -> u64 {
let mut n = u;
@ -171,21 +173,21 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t
}
}
fn enc_mutability(w: &mut SeekableMemWriter, mt: ast::Mutability) {
fn enc_mutability(w: &mut Encoder, mt: ast::Mutability) {
match mt {
ast::MutImmutable => (),
ast::MutMutable => mywrite!(w, "m"),
}
}
fn enc_mt<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
fn enc_mt<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
mt: ty::mt<'tcx>) {
enc_mutability(w, mt.mutbl);
enc_ty(w, cx, mt.ty);
}
fn enc_opt<T, F>(w: &mut SeekableMemWriter, t: Option<T>, enc_f: F) where
F: FnOnce(&mut SeekableMemWriter, T),
fn enc_opt<T, F>(w: &mut Encoder, t: Option<T>, enc_f: F) where
F: FnOnce(&mut Encoder, T),
{
match t {
None => mywrite!(w, "n"),
@ -196,11 +198,11 @@ fn enc_opt<T, F>(w: &mut SeekableMemWriter, t: Option<T>, enc_f: F) where
}
}
fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut SeekableMemWriter,
fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut Encoder,
cx: &ctxt<'a, 'tcx>,
v: &VecPerParamSpace<T>,
mut op: F) where
F: FnMut(&mut SeekableMemWriter, &ctxt<'a, 'tcx>, &T),
F: FnMut(&mut Encoder, &ctxt<'a, 'tcx>, &T),
{
for &space in &subst::ParamSpace::all() {
mywrite!(w, "[");
@ -211,14 +213,14 @@ fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut SeekableMemWriter,
}
}
pub fn enc_substs<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
pub fn enc_substs<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
substs: &subst::Substs<'tcx>) {
enc_region_substs(w, cx, &substs.regions);
enc_vec_per_param_space(w, cx, &substs.types,
|w, cx, &ty| enc_ty(w, cx, ty));
}
fn enc_region_substs(w: &mut SeekableMemWriter, cx: &ctxt, substs: &subst::RegionSubsts) {
fn enc_region_substs(w: &mut Encoder, cx: &ctxt, substs: &subst::RegionSubsts) {
match *substs {
subst::ErasedRegions => {
mywrite!(w, "e");
@ -231,7 +233,7 @@ fn enc_region_substs(w: &mut SeekableMemWriter, cx: &ctxt, substs: &subst::Regio
}
}
pub fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) {
pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) {
match r {
ty::ReLateBound(id, br) => {
mywrite!(w, "b[{}|", id.depth);
@ -270,7 +272,7 @@ pub fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) {
}
}
fn enc_scope(w: &mut SeekableMemWriter, _cx: &ctxt, scope: region::CodeExtent) {
fn enc_scope(w: &mut Encoder, _cx: &ctxt, scope: region::CodeExtent) {
match scope {
region::CodeExtent::Misc(node_id) => mywrite!(w, "M{}", node_id),
region::CodeExtent::Remainder(region::BlockRemainder {
@ -279,12 +281,12 @@ fn enc_scope(w: &mut SeekableMemWriter, _cx: &ctxt, scope: region::CodeExtent) {
}
}
fn enc_destruction_scope_data(w: &mut SeekableMemWriter,
fn enc_destruction_scope_data(w: &mut Encoder,
d: region::DestructionScopeData) {
mywrite!(w, "{}", d.node_id);
}
fn enc_bound_region(w: &mut SeekableMemWriter, cx: &ctxt, br: ty::BoundRegion) {
fn enc_bound_region(w: &mut Encoder, cx: &ctxt, br: ty::BoundRegion) {
match br {
ty::BrAnon(idx) => {
mywrite!(w, "a{}|", idx);
@ -303,40 +305,40 @@ fn enc_bound_region(w: &mut SeekableMemWriter, cx: &ctxt, br: ty::BoundRegion) {
}
}
pub fn enc_trait_ref<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
pub fn enc_trait_ref<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
s: &ty::TraitRef<'tcx>) {
mywrite!(w, "{}|", (cx.ds)(s.def_id));
enc_substs(w, cx, s.substs);
}
fn enc_unsafety(w: &mut SeekableMemWriter, p: ast::Unsafety) {
fn enc_unsafety(w: &mut Encoder, p: ast::Unsafety) {
match p {
ast::Unsafety::Normal => mywrite!(w, "n"),
ast::Unsafety::Unsafe => mywrite!(w, "u"),
}
}
fn enc_abi(w: &mut SeekableMemWriter, abi: Abi) {
fn enc_abi(w: &mut Encoder, abi: Abi) {
mywrite!(w, "[");
mywrite!(w, "{}", abi.name());
mywrite!(w, "]")
}
pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
ft: &ty::BareFnTy<'tcx>) {
enc_unsafety(w, ft.unsafety);
enc_abi(w, ft.abi);
enc_fn_sig(w, cx, &ft.sig);
}
pub fn enc_closure_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
pub fn enc_closure_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
ft: &ty::ClosureTy<'tcx>) {
enc_unsafety(w, ft.unsafety);
enc_fn_sig(w, cx, &ft.sig);
enc_abi(w, ft.abi);
}
fn enc_fn_sig<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
fn enc_fn_sig<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
fsig: &ty::PolyFnSig<'tcx>) {
mywrite!(w, "[");
for ty in &fsig.0.inputs {
@ -358,7 +360,7 @@ fn enc_fn_sig<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
}
}
pub fn enc_builtin_bounds(w: &mut SeekableMemWriter, _cx: &ctxt, bs: &ty::BuiltinBounds) {
pub fn enc_builtin_bounds(w: &mut Encoder, _cx: &ctxt, bs: &ty::BuiltinBounds) {
for bound in bs {
match bound {
ty::BoundSend => mywrite!(w, "S"),
@ -371,7 +373,7 @@ pub fn enc_builtin_bounds(w: &mut SeekableMemWriter, _cx: &ctxt, bs: &ty::Builti
mywrite!(w, ".");
}
pub fn enc_existential_bounds<'a,'tcx>(w: &mut SeekableMemWriter,
pub fn enc_existential_bounds<'a,'tcx>(w: &mut Encoder,
cx: &ctxt<'a,'tcx>,
bs: &ty::ExistentialBounds<'tcx>) {
let param_bounds = ty::ParamBounds { trait_bounds: vec!(),
@ -381,7 +383,7 @@ pub fn enc_existential_bounds<'a,'tcx>(w: &mut SeekableMemWriter,
enc_bounds(w, cx, &param_bounds);
}
pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
pub fn enc_bounds<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
bs: &ty::ParamBounds<'tcx>) {
enc_builtin_bounds(w, cx, &bs.builtin_bounds);
@ -400,7 +402,7 @@ pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
mywrite!(w, ".");
}
pub fn enc_region_bounds<'a, 'tcx>(w: &mut SeekableMemWriter,
pub fn enc_region_bounds<'a, 'tcx>(w: &mut Encoder,
cx: &ctxt<'a, 'tcx>,
rs: &[ty::Region]) {
for &r in rs {
@ -411,7 +413,7 @@ pub fn enc_region_bounds<'a, 'tcx>(w: &mut SeekableMemWriter,
mywrite!(w, ".");
}
pub fn enc_type_param_def<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
pub fn enc_type_param_def<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
v: &ty::TypeParameterDef<'tcx>) {
mywrite!(w, "{}:{}|{}|{}|",
token::get_name(v.name), (cx.ds)(v.def_id),
@ -420,7 +422,7 @@ pub fn enc_type_param_def<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tc
enc_object_lifetime_default(w, cx, v.object_lifetime_default);
}
fn enc_object_lifetime_default<'a, 'tcx>(w: &mut SeekableMemWriter,
fn enc_object_lifetime_default<'a, 'tcx>(w: &mut Encoder,
cx: &ctxt<'a, 'tcx>,
default: Option<ty::ObjectLifetimeDefault>)
{
@ -434,7 +436,7 @@ fn enc_object_lifetime_default<'a, 'tcx>(w: &mut SeekableMemWriter,
}
}
pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter,
pub fn enc_predicate<'a, 'tcx>(w: &mut Encoder,
cx: &ctxt<'a, 'tcx>,
p: &ty::Predicate<'tcx>)
{
@ -465,7 +467,7 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter,
}
}
fn enc_projection_predicate<'a, 'tcx>(w: &mut SeekableMemWriter,
fn enc_projection_predicate<'a, 'tcx>(w: &mut Encoder,
cx: &ctxt<'a, 'tcx>,
data: &ty::ProjectionPredicate<'tcx>) {
enc_trait_ref(w, cx, &*data.projection_ty.trait_ref);

View file

@ -1,4 +1,4 @@
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// 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.
//
@ -43,13 +43,14 @@ use std::old_io::Seek;
use std::num::FromPrimitive;
use std::rc::Rc;
use rbml::io::SeekableMemWriter;
use rbml::{reader, writer};
use rbml::reader;
use rbml::writer::Encoder;
use rbml;
use serialize;
use serialize::{Decodable, Decoder, DecoderHelpers, Encodable};
use serialize::{EncoderHelpers};
#[cfg(test)] use rbml::io::SeekableMemWriter;
#[cfg(test)] use syntax::parse;
#[cfg(test)] use syntax::print::pprust;
@ -68,8 +69,6 @@ trait tr_intern {
fn tr_intern(&self, dcx: &DecodeContext) -> ast::DefId;
}
pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
// ______________________________________________________________________
// Top-level methods.
@ -414,9 +413,8 @@ fn decode_ast(par_doc: rbml::Doc) -> ast::InlinedItem {
// ______________________________________________________________________
// Encoding and decoding of ast::def
fn decode_def(dcx: &DecodeContext, doc: rbml::Doc) -> def::Def {
let mut dsr = reader::Decoder::new(doc);
let def: def::Def = Decodable::decode(&mut dsr).unwrap();
fn decode_def(dcx: &DecodeContext, dsr: &mut reader::Decoder) -> def::Def {
let def: def::Def = Decodable::decode(dsr).unwrap();
def.tr(dcx)
}
@ -911,7 +909,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
fn emit_type_param_def<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
type_param_def: &ty::TypeParameterDef<'tcx>) {
self.emit_opaque(|this| {
Ok(tyencode::enc_type_param_def(this.writer,
Ok(tyencode::enc_type_param_def(this,
&ecx.ty_str_ctxt(),
type_param_def))
});
@ -920,7 +918,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
fn emit_predicate<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
predicate: &ty::Predicate<'tcx>) {
self.emit_opaque(|this| {
Ok(tyencode::enc_predicate(this.writer,
Ok(tyencode::enc_predicate(this,
&ecx.ty_str_ctxt(),
predicate))
});
@ -954,20 +952,20 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
bounds: &ty::ExistentialBounds<'tcx>) {
self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(this.writer,
self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(this,
&ecx.ty_str_ctxt(),
bounds)));
}
fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds) {
self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(this.writer,
self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(this,
&ecx.ty_str_ctxt(),
bounds)));
}
fn emit_substs<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
substs: &subst::Substs<'tcx>) {
self.emit_opaque(|this| Ok(tyencode::enc_substs(this.writer,
self.emit_opaque(|this| Ok(tyencode::enc_substs(this,
&ecx.ty_str_ctxt(),
substs)));
}
@ -1115,7 +1113,7 @@ impl<'a> write_tag_and_id for Encoder<'a> {
}
fn id(&mut self, id: ast::NodeId) {
self.wr_tagged_u64(c::tag_table_id as uint, id as u64);
id.encode(self).unwrap();
}
}
@ -1152,51 +1150,44 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
if let Some(def) = tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
rbml_w.tag(c::tag_table_def, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| def.encode(rbml_w).unwrap());
def.encode(rbml_w).unwrap();
})
}
if let Some(ty) = tcx.node_types.borrow().get(&id) {
rbml_w.tag(c::tag_table_node_type, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
rbml_w.emit_ty(ecx, *ty);
})
rbml_w.emit_ty(ecx, *ty);
})
}
if let Some(item_substs) = tcx.item_substs.borrow().get(&id) {
rbml_w.tag(c::tag_table_item_subst, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
rbml_w.emit_substs(ecx, &item_substs.substs);
})
rbml_w.emit_substs(ecx, &item_substs.substs);
})
}
if let Some(fv) = tcx.freevars.borrow().get(&id) {
rbml_w.tag(c::tag_table_freevars, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
rbml_w.emit_from_vec(fv, |rbml_w, fv_entry| {
Ok(encode_freevar_entry(rbml_w, fv_entry))
});
})
rbml_w.emit_from_vec(fv, |rbml_w, fv_entry| {
Ok(encode_freevar_entry(rbml_w, fv_entry))
});
});
for freevar in fv {
rbml_w.tag(c::tag_table_upvar_capture_map, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
let var_id = freevar.def.def_id().node;
let upvar_id = ty::UpvarId {
var_id: var_id,
closure_expr_id: id
};
let upvar_capture = tcx.upvar_capture_map.borrow()[upvar_id].clone();
var_id.encode(rbml_w);
upvar_capture.encode(rbml_w);
})
let var_id = freevar.def.def_id().node;
let upvar_id = ty::UpvarId {
var_id: var_id,
closure_expr_id: id
};
let upvar_capture = tcx.upvar_capture_map.borrow()[upvar_id].clone();
var_id.encode(rbml_w);
upvar_capture.encode(rbml_w);
})
}
}
@ -1205,18 +1196,14 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
if let Some(type_scheme) = tcx.tcache.borrow().get(&lid) {
rbml_w.tag(c::tag_table_tcache, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
rbml_w.emit_type_scheme(ecx, type_scheme.clone());
})
rbml_w.emit_type_scheme(ecx, type_scheme.clone());
})
}
if let Some(type_param_def) = tcx.ty_param_defs.borrow().get(&id) {
rbml_w.tag(c::tag_table_param_defs, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
rbml_w.emit_type_param_def(ecx, type_param_def)
})
rbml_w.emit_type_param_def(ecx, type_param_def)
})
}
@ -1224,18 +1211,14 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
if let Some(method) = tcx.method_map.borrow().get(&method_call) {
rbml_w.tag(c::tag_table_method_map, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
encode_method_callee(ecx, rbml_w, method_call.adjustment, method)
})
encode_method_callee(ecx, rbml_w, method_call.adjustment, method)
})
}
if let Some(trait_ref) = tcx.object_cast_map.borrow().get(&id) {
rbml_w.tag(c::tag_table_object_cast_map, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
rbml_w.emit_trait_ref(ecx, &*trait_ref.0);
})
rbml_w.emit_trait_ref(ecx, &*trait_ref.0);
})
}
@ -1246,9 +1229,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
if let Some(method) = tcx.method_map.borrow().get(&method_call) {
rbml_w.tag(c::tag_table_method_map, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
encode_method_callee(ecx, rbml_w, method_call.adjustment, method)
})
encode_method_callee(ecx, rbml_w, method_call.adjustment, method)
})
}
}
@ -1259,10 +1240,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
if let Some(method) = tcx.method_map.borrow().get(&method_call) {
rbml_w.tag(c::tag_table_method_map, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
encode_method_callee(ecx, rbml_w,
method_call.adjustment, method)
})
encode_method_callee(ecx, rbml_w,
method_call.adjustment, method)
})
}
}
@ -1274,36 +1253,28 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
rbml_w.tag(c::tag_table_adjustments, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
rbml_w.emit_auto_adjustment(ecx, adjustment);
})
rbml_w.emit_auto_adjustment(ecx, adjustment);
})
}
if let Some(closure_type) = tcx.closure_tys.borrow().get(&ast_util::local_def(id)) {
rbml_w.tag(c::tag_table_closure_tys, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
rbml_w.emit_closure_type(ecx, closure_type);
})
rbml_w.emit_closure_type(ecx, closure_type);
})
}
if let Some(closure_kind) = tcx.closure_kinds.borrow().get(&ast_util::local_def(id)) {
rbml_w.tag(c::tag_table_closure_kinds, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
encode_closure_kind(rbml_w, *closure_kind)
})
encode_closure_kind(rbml_w, *closure_kind)
})
}
for &qualif in tcx.const_qualif_map.borrow().get(&id).iter() {
rbml_w.tag(c::tag_table_const_qualif, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
qualif.encode(rbml_w).unwrap()
})
qualif.encode(rbml_w).unwrap()
})
}
}
@ -1831,8 +1802,9 @@ fn decode_side_tables(dcx: &DecodeContext,
ast_doc: rbml::Doc) {
let tbl_doc = ast_doc.get(c::tag_table as uint);
reader::docs(tbl_doc, |tag, entry_doc| {
let id0 = entry_doc.get(c::tag_table_id as uint).as_int();
let id = dcx.tr_id(id0 as ast::NodeId);
let mut entry_dsr = reader::Decoder::new(entry_doc);
let id0: ast::NodeId = Decodable::decode(&mut entry_dsr).unwrap();
let id = dcx.tr_id(id0);
debug!(">> Side table document with tag 0x{:x} \
found for id {} (orig {})",
@ -1845,13 +1817,11 @@ fn decode_side_tables(dcx: &DecodeContext,
tag));
}
Some(value) => {
let val_doc = entry_doc.get(c::tag_table_val as uint);
let mut val_dsr = reader::Decoder::new(val_doc);
let val_dsr = &mut val_dsr;
let val_dsr = &mut entry_dsr;
match value {
c::tag_table_def => {
let def = decode_def(dcx, val_doc);
let def = decode_def(dcx, val_dsr);
dcx.tcx.def_map.borrow_mut().insert(id, def::PathResolution {
base_def: def,
// This doesn't matter cross-crate.
@ -1995,7 +1965,7 @@ fn mk_ctxt() -> parse::ParseSess {
fn roundtrip(in_item: Option<P<ast::Item>>) {
let in_item = in_item.unwrap();
let mut wr = SeekableMemWriter::new();
encode_item_ast(&mut writer::Encoder::new(&mut wr), &*in_item);
encode_item_ast(&mut Encoder::new(&mut wr), &*in_item);
let rbml_doc = rbml::Doc::new(wr.get_ref());
let out_item = decode_item_ast(rbml_doc);