Use a more efficient encoding for opaque data in RBML.

This commit is contained in:
Michael Woerister 2015-12-25 13:59:02 -05:00
parent 89753077fc
commit fa2a7411e4
12 changed files with 1308 additions and 369 deletions

162
src/librbml/leb128.rs Normal file
View File

@ -0,0 +1,162 @@
// 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.
#[inline]
pub fn write_to_vec(vec: &mut Vec<u8>, position: &mut usize, byte: u8)
{
if *position == vec.len() {
vec.push(byte);
} else {
vec[*position] = byte;
}
*position += 1;
}
pub fn write_unsigned_leb128(out: &mut Vec<u8>,
start_position: usize,
mut value: u64)
-> usize {
let mut position = start_position;
loop
{
let mut byte = (value & 0x7F) as u8;
value >>= 7;
if value != 0 {
byte |= 0x80;
}
write_to_vec(out, &mut position, byte);
if value == 0 {
break;
}
}
return position - start_position;
}
pub fn read_unsigned_leb128(data: &[u8],
start_position: usize)
-> (u64, usize) {
let mut result = 0;
let mut shift = 0;
let mut position = start_position;
loop {
let byte = data[position];
position += 1;
result |= ((byte & 0x7F) as u64) << shift;
if (byte & 0x80) == 0 {
break;
}
shift += 7;
}
(result, position - start_position)
}
pub fn write_signed_leb128(out: &mut Vec<u8>,
start_position: usize,
mut value: i64) -> usize {
let mut position = start_position;
loop {
let mut byte = (value as u8) & 0x7f;
value >>= 7;
let more = !((((value == 0 ) && ((byte & 0x40) == 0)) ||
((value == -1) && ((byte & 0x40) != 0))));
if more {
byte |= 0x80; // Mark this byte to show that more bytes will follow.
}
write_to_vec(out, &mut position, byte);
if !more {
break;
}
}
return position - start_position;
}
pub fn read_signed_leb128(data: &[u8],
start_position: usize)
-> (i64, usize) {
let mut result = 0;
let mut shift = 0;
let mut position = start_position;
let mut byte;
loop {
byte = data[position];
position += 1;
result |= ((byte & 0x7F) as i64) << shift;
shift += 7;
if (byte & 0x80) == 0 {
break;
}
}
if (shift < 64) && ((byte & 0x40) != 0) {
/* sign extend */
result |= -(1i64 << shift);
}
(result, position - start_position)
}
#[test]
fn test_unsigned_leb128() {
let mut stream = Vec::with_capacity(10000);
for x in 0..62 {
let pos = stream.len();
let bytes_written = write_unsigned_leb128(&mut stream, pos, 3 << x);
assert_eq!(stream.len(), pos + bytes_written);
}
let mut position = 0;
for x in 0..62 {
let expected = 3 << x;
let (actual, bytes_read) = read_unsigned_leb128(&stream, position);
assert_eq!(expected, actual);
position += bytes_read;
}
assert_eq!(stream.len(), position);
}
#[test]
fn test_signed_leb128() {
let mut values = Vec::new();
let mut i = -500;
while i < 500 {
values.push(i * 123457i64);
i += 1;
}
let mut stream = Vec::new();
for &x in &values {
let pos = stream.len();
let bytes_written = write_signed_leb128(&mut stream, pos, x);
assert_eq!(stream.len(), pos + bytes_written);
}
let mut pos = 0;
for &x in &values {
let (value, bytes_read) = read_signed_leb128(&mut stream, pos);
pos += bytes_read;
assert_eq!(x, value);
}
assert_eq!(pos, stream.len());
}

View File

@ -128,10 +128,17 @@
#![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::EbmlEncoderTag::*;
pub use self::Error::*;
@ -241,6 +248,7 @@ pub mod reader {
use serialize;
use super::opaque;
use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsSub8, EsSub32,
EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsI64,
EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
@ -621,18 +629,16 @@ pub mod reader {
}
pub fn read_opaque<R, F>(&mut self, op: F) -> DecodeResult<R> where
F: FnOnce(&mut Decoder, Doc) -> DecodeResult<R>,
F: FnOnce(&mut opaque::Decoder, Doc) -> DecodeResult<R>,
{
let doc = try!(self.next_doc(EsOpaque));
let (old_parent, old_pos) = (self.parent, self.pos);
self.parent = doc;
self.pos = doc.start;
let result = {
let mut opaque_decoder = opaque::Decoder::new(doc.data,
doc.start);
try!(op(&mut opaque_decoder, doc))
};
let result = try!(op(self, doc));
self.parent = old_parent;
self.pos = old_pos;
Ok(result)
}
@ -877,6 +883,7 @@ pub mod writer {
use std::io::prelude::*;
use std::io::{self, SeekFrom, Cursor};
use super::opaque;
use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey,
EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8,
EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
@ -1120,10 +1127,16 @@ pub mod writer {
}
pub fn emit_opaque<F>(&mut self, f: F) -> EncodeResult where
F: FnOnce(&mut Encoder) -> EncodeResult,
F: FnOnce(&mut opaque::Encoder) -> EncodeResult,
{
try!(self.start_tag(EsOpaque as usize));
try!(f(self));
{
let mut opaque_encoder = opaque::Encoder::new(self.writer);
try!(f(&mut opaque_encoder));
}
self.mark_stable_position();
self.end_tag()
}
}

811
src/librbml/opaque.rs Normal file
View File

@ -0,0 +1,811 @@
// 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.
use Error as DecodeError;
use writer::EncodeResult;
use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128,
write_unsigned_leb128};
use std::io::{self, Write};
use serialize;
//=-----------------------------------------------------------------------------
// Encoder
//=-----------------------------------------------------------------------------
pub struct Encoder<'a> {
pub cursor: &'a mut io::Cursor<Vec<u8>>,
}
impl<'a> Encoder<'a> {
pub fn new(cursor: &'a mut io::Cursor<Vec<u8>>) -> Encoder<'a> {
Encoder {
cursor: cursor
}
}
}
macro_rules! write_uleb128 {
($enc:expr, $value:expr) => {{
let pos = $enc.cursor.position() as usize;
let bytes_written = write_unsigned_leb128($enc.cursor.get_mut(), pos, $value as u64);
$enc.cursor.set_position((pos + bytes_written) as u64);
Ok(())
}}
}
macro_rules! write_sleb128 {
($enc:expr, $value:expr) => {{
let pos = $enc.cursor.position() as usize;
let bytes_written = write_signed_leb128($enc.cursor.get_mut(), pos, $value as i64);
$enc.cursor.set_position((pos + bytes_written) as u64);
Ok(())
}}
}
impl<'a> serialize::Encoder for Encoder<'a> {
type Error = io::Error;
fn emit_nil(&mut self) -> EncodeResult {
Ok(())
}
fn emit_uint(&mut self, v: usize) -> EncodeResult {
write_uleb128!(self, v)
}
fn emit_u64(&mut self, v: u64) -> EncodeResult {
write_uleb128!(self, v)
}
fn emit_u32(&mut self, v: u32) -> EncodeResult {
write_uleb128!(self, v)
}
fn emit_u16(&mut self, v: u16) -> EncodeResult {
write_uleb128!(self, v)
}
fn emit_u8(&mut self, v: u8) -> EncodeResult {
let _ = self.cursor.write_all(&[v]);
Ok(())
}
fn emit_int(&mut self, v: isize) -> EncodeResult {
write_sleb128!(self, v)
}
fn emit_i64(&mut self, v: i64) -> EncodeResult {
write_sleb128!(self, v)
}
fn emit_i32(&mut self, v: i32) -> EncodeResult {
write_sleb128!(self, v)
}
fn emit_i16(&mut self, v: i16) -> EncodeResult {
write_sleb128!(self, v)
}
fn emit_i8(&mut self, v: i8) -> EncodeResult {
let as_u8: u8 = unsafe { ::std::mem::transmute(v) };
let _ = self.cursor.write_all(&[as_u8]);
Ok(())
}
fn emit_bool(&mut self, v: bool) -> EncodeResult {
self.emit_u8(if v { 1 } else { 0 })
}
fn emit_f64(&mut self, v: f64) -> EncodeResult {
let as_u64: u64 = unsafe { ::std::mem::transmute(v) };
self.emit_u64(as_u64)
}
fn emit_f32(&mut self, v: f32) -> EncodeResult {
let as_u32: u32 = unsafe { ::std::mem::transmute(v) };
self.emit_u32(as_u32)
}
fn emit_char(&mut self, v: char) -> EncodeResult {
self.emit_u32(v as u32)
}
fn emit_str(&mut self, v: &str) -> EncodeResult {
try!(self.emit_uint(v.len()));
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
{
try!(self.emit_uint(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,
{
try!(self.emit_uint(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,
{
try!(self.emit_uint(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> {
pub fn position(&self) -> usize {
self.cursor.position() as usize
}
pub fn from_rbml<'b: 'c, 'c>(rbml: &'c mut ::writer::Encoder<'b>) -> Encoder<'c> {
Encoder {
cursor: rbml.writer
}
}
}
//=-----------------------------------------------------------------------------
// Decoder
//=-----------------------------------------------------------------------------
pub struct Decoder<'a> {
pub data: &'a [u8],
position: usize,
}
impl<'a> Decoder<'a> {
pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> {
Decoder {
data: data,
position: position
}
}
pub fn position(&self) -> usize {
self.position
}
pub fn advance(&mut self, bytes: usize) {
self.position += bytes;
}
}
macro_rules! read_uleb128 {
($dec:expr, $t:ty) => ({
let (value, bytes_read) = read_unsigned_leb128($dec.data, $dec.position);
$dec.position += bytes_read;
Ok(value as $t)
})
}
macro_rules! read_sleb128 {
($dec:expr, $t:ty) => ({
let (value, bytes_read) = read_signed_leb128($dec.data, $dec.position);
$dec.position += bytes_read;
Ok(value as $t)
})
}
impl<'a> serialize::Decoder for Decoder<'a> {
type Error = DecodeError;
fn read_nil(&mut self) -> Result<(), Self::Error> {
Ok(())
}
fn read_u64(&mut self) -> Result<u64, Self::Error> {
read_uleb128!(self, u64)
}
fn read_u32(&mut self) -> Result<u32, Self::Error> {
read_uleb128!(self, u32)
}
fn read_u16(&mut self) -> Result<u16, Self::Error> {
read_uleb128!(self, u16)
}
fn read_u8(&mut self) -> Result<u8, Self::Error> {
let value = self.data[self.position];
self.position += 1;
Ok(value)
}
fn read_uint(&mut self) -> Result<usize, Self::Error> {
read_uleb128!(self, usize)
}
fn read_i64(&mut self) -> Result<i64, Self::Error> {
read_sleb128!(self, i64)
}
fn read_i32(&mut self) -> Result<i32, Self::Error> {
read_sleb128!(self, i32)
}
fn read_i16(&mut self) -> Result<i16, Self::Error> {
read_sleb128!(self, i16)
}
fn read_i8(&mut self) -> Result<i8, Self::Error> {
let as_u8 = self.data[self.position];
self.position += 1;
unsafe {
Ok(::std::mem::transmute(as_u8))
}
}
fn read_int(&mut self) -> Result<isize, Self::Error> {
read_sleb128!(self, isize)
}
fn read_bool(&mut self) -> Result<bool, Self::Error> {
let value = try!(self.read_u8());
Ok(value != 0)
}
fn read_f64(&mut self) -> Result<f64, Self::Error> {
let bits = try!(self.read_u64());
Ok(unsafe { ::std::mem::transmute(bits) })
}
fn read_f32(&mut self) -> Result<f32, Self::Error> {
let bits = try!(self.read_u32());
Ok(unsafe { ::std::mem::transmute(bits) })
}
fn read_char(&mut self) -> Result<char, Self::Error> {
let bits = try!(self.read_u32());
Ok(::std::char::from_u32(bits).unwrap())
}
fn read_str(&mut self) -> Result<String, Self::Error> {
let len = try!(self.read_uint());
let s = ::std::str::from_utf8(&self.data[self.position .. self.position + len]).unwrap();
self.position += len;
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 = try!(self.read_uint());
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 = try!(self.read_uint());
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 = try!(self.read_uint());
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 = try!(self.read_uint());
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())
}
}
#[cfg(test)]
mod tests {
use serialize::{Encodable, Decodable};
use std::io::{Cursor};
use std::fmt::Debug;
use super::{Encoder, Decoder};
#[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
struct Struct {
a: (),
b: u8,
c: u16,
d: u32,
e: u64,
f: usize,
g: i8,
h: i16,
i: i32,
j: i64,
k: isize,
l: char,
m: String,
n: f32,
o: f64,
p: bool,
q: Option<u32>,
}
fn check_round_trip<T: Encodable+Decodable+PartialEq+Debug>(values: Vec<T>) {
let mut cursor = Cursor::new(Vec::new());
for value in &values {
let mut encoder = Encoder::new(&mut cursor);
Encodable::encode(&value, &mut encoder).unwrap();
}
let data = cursor.into_inner();
let mut decoder = Decoder::new(&data[..], 0);
for value in values {
let decoded = Decodable::decode(&mut decoder).unwrap();
assert_eq!(value, decoded);
}
}
#[test]
fn test_unit() {
check_round_trip(vec![(), (), (), ()]);
}
#[test]
fn test_u8() {
let mut vec = vec![];
for i in ::std::u8::MIN .. ::std::u8::MAX {
vec.push(i);
}
check_round_trip(vec);
}
#[test]
fn test_u16() {
for i in ::std::u16::MIN .. ::std::u16::MAX {
check_round_trip(vec![1, 2, 3, i, i, i]);
}
}
#[test]
fn test_u32() {
check_round_trip(vec![1, 2, 3, ::std::u32::MIN, 0, 1, ::std::u32::MAX, 2, 1]);
}
#[test]
fn test_u64() {
check_round_trip(vec![1, 2, 3, ::std::u64::MIN, 0, 1, ::std::u64::MAX, 2, 1]);
}
#[test]
fn test_usize() {
check_round_trip(vec![1, 2, 3, ::std::usize::MIN, 0, 1, ::std::usize::MAX, 2, 1]);
}
#[test]
fn test_i8() {
let mut vec = vec![];
for i in ::std::i8::MIN .. ::std::i8::MAX {
vec.push(i);
}
check_round_trip(vec);
}
#[test]
fn test_i16() {
for i in ::std::i16::MIN .. ::std::i16::MAX {
check_round_trip(vec![-1, 2, -3, i, i, i, 2]);
}
}
#[test]
fn test_i32() {
check_round_trip(vec![-1, 2, -3, ::std::i32::MIN, 0, 1, ::std::i32::MAX, 2, 1]);
}
#[test]
fn test_i64() {
check_round_trip(vec![-1, 2, -3, ::std::i64::MIN, 0, 1, ::std::i64::MAX, 2, 1]);
}
#[test]
fn test_isize() {
check_round_trip(vec![-1, 2, -3, ::std::isize::MIN, 0, 1, ::std::isize::MAX, 2, 1]);
}
#[test]
fn test_bool() {
check_round_trip(vec![false, true, true, false, false]);
}
#[test]
fn test_f32() {
let mut vec = vec![];
for i in -100 .. 100 {
vec.push( (i as f32) / 3.0 );
}
check_round_trip(vec);
}
#[test]
fn test_f64() {
let mut vec = vec![];
for i in -100 .. 100 {
vec.push( (i as f64) / 3.0 );
}
check_round_trip(vec);
}
#[test]
fn test_char() {
let vec = vec!['a', 'b', 'c', 'd', 'A', 'X', ' ', '#', 'Ö', 'Ä', 'µ', '€'];
check_round_trip(vec);
}
#[test]
fn test_string() {
let vec = vec![
"abcbuÖeiovÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(),
"abcbuÖganeiovÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(),
"abcbuÖganeiovÄnameÜavmpßvmea€µsbpapmaebn".to_string(),
"abcbuÖganeiovÄnameÜavmpßvmeabpnvapeapmaebn".to_string(),
"abcbuÖganeiÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(),
"abcbuÖganeiovÄnameÜavmpßvmea€µsbpmaebn".to_string(),
"abcbuÖganeiovÄnameÜavmpßvmea€µnvapeapmaebn".to_string()];
check_round_trip(vec);
}
#[test]
fn test_option() {
check_round_trip(vec![Some(-1i8)]);
check_round_trip(vec![Some(-2i16)]);
check_round_trip(vec![Some(-3i32)]);
check_round_trip(vec![Some(-4i64)]);
check_round_trip(vec![Some(-5isize)]);
let none_i8: Option<i8> = None;
check_round_trip(vec![none_i8]);
let none_i16: Option<i16> = None;
check_round_trip(vec![none_i16]);
let none_i32: Option<i32> = None;
check_round_trip(vec![none_i32]);
let none_i64: Option<i64> = None;
check_round_trip(vec![none_i64]);
let none_isize: Option<isize> = None;
check_round_trip(vec![none_isize]);
}
#[test]
fn test_struct() {
check_round_trip(vec![Struct {
a: (),
b: 10,
c: 11,
d: 12,
e: 13,
f: 14,
g: 15,
h: 16,
i: 17,
j: 18,
k: 19,
l: 'x',
m: "abc".to_string(),
n: 20.5,
o: 21.5,
p: false,
q: None,
}]);
check_round_trip(vec![Struct {
a: (),
b: 101,
c: 111,
d: 121,
e: 131,
f: 141,
g: -15,
h: -16,
i: -17,
j: -18,
k: -19,
l: 'y',
m: "def".to_string(),
n: -20.5,
o: -21.5,
p: true,
q: Some(1234567),
}]);
}
#[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
enum Enum {
Variant1,
Variant2(usize, f32),
Variant3 { a: i32, b: char, c: bool }
}
#[test]
fn test_enum() {
check_round_trip(vec![Enum::Variant1,
Enum::Variant2(1, 2.5),
Enum::Variant3 { a: 3, b: 'b', c: false },
Enum::Variant3 { a: -4, b: 'f', c: true }]);
}
#[test]
fn test_sequence() {
let mut vec = vec![];
for i in -100i64 .. 100i64 {
vec.push(i*100000);
}
check_round_trip(vec![vec]);
}
#[test]
fn test_hash_map() {
use std::collections::HashMap;
let mut map = HashMap::new();
for i in -100i64 .. 100i64 {
map.insert(i*100000, i*10000);
}
check_round_trip(vec![map]);
}
#[test]
fn test_tuples() {
check_round_trip(vec![('x', (), false, 0.5f32)]);
check_round_trip(vec![(9i8, 10u16, 1.5f64)]);
check_round_trip(vec![(-12i16, 11u8, 12usize)]);
check_round_trip(vec![(1234567isize, 100000000000000u64, 99999999999999i64)]);
check_round_trip(vec![(String::new(), "some string".to_string())]);
}
}

View File

@ -432,8 +432,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
/// Note, however, that this only works for RBML-based encoding and decoding at
/// the moment.
pub mod tls {
use rbml::writer::Encoder as RbmlEncoder;
use rbml::reader::Decoder as RbmlDecoder;
use rbml::opaque::Encoder as OpaqueEncoder;
use rbml::opaque::Decoder as OpaqueDecoder;
use serialize;
use std::mem;
use middle::ty::{self, Ty};
@ -442,8 +442,8 @@ pub mod tls {
pub trait EncodingContext<'tcx> {
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
fn encode_ty(&self, rbml_w: &mut RbmlEncoder, t: Ty<'tcx>);
fn encode_substs(&self, rbml_w: &mut RbmlEncoder, substs: &Substs<'tcx>);
fn encode_ty(&self, encoder: &mut OpaqueEncoder, t: Ty<'tcx>);
fn encode_substs(&self, encoder: &mut OpaqueEncoder, substs: &Substs<'tcx>);
}
/// Marker type used for the scoped TLS slot.
@ -455,13 +455,13 @@ pub mod tls {
/// Execute f after pushing the given EncodingContext onto the TLS stack.
pub fn enter_encoding_context<'tcx, F, R>(ecx: &EncodingContext<'tcx>,
rbml_w: &mut RbmlEncoder,
encoder: &mut OpaqueEncoder,
f: F) -> R
where F: FnOnce(&EncodingContext<'tcx>, &mut RbmlEncoder) -> R
where F: FnOnce(&EncodingContext<'tcx>, &mut OpaqueEncoder) -> R
{
let tls_payload = (ecx as *const _, rbml_w as *mut _);
let tls_payload = (ecx as *const _, encoder as *mut _);
let tls_ptr = &tls_payload as *const _ as *const TlsPayload;
TLS_ENCODING.set(unsafe { &*tls_ptr }, || f(ecx, rbml_w))
TLS_ENCODING.set(unsafe { &*tls_ptr }, || f(ecx, encoder))
}
/// Execute f with access to the thread-local encoding context and
@ -473,16 +473,16 @@ pub mod tls {
/// possible to construct cases where the EncodingContext is exchanged
/// while the same encoder is used, thus working with a wrong context.
pub fn with_encoding_context<'tcx, E, F, R>(encoder: &mut E, f: F) -> R
where F: FnOnce(&EncodingContext<'tcx>, &mut RbmlEncoder) -> R,
where F: FnOnce(&EncodingContext<'tcx>, &mut OpaqueEncoder) -> R,
E: serialize::Encoder
{
unsafe {
unsafe_with_encoding_context(|ecx, rbml_w| {
assert!(encoder as *mut _ as usize == rbml_w as *mut _ as usize);
unsafe_with_encoding_context(|ecx, tls_encoder| {
assert!(encoder as *mut _ as usize == tls_encoder as *mut _ as usize);
let ecx: &EncodingContext<'tcx> = mem::transmute(ecx);
f(ecx, rbml_w)
f(ecx, tls_encoder)
})
}
}
@ -490,19 +490,19 @@ pub mod tls {
/// Execute f with access to the thread-local encoding context and
/// rbml encoder.
pub unsafe fn unsafe_with_encoding_context<F, R>(f: F) -> R
where F: FnOnce(&EncodingContext, &mut RbmlEncoder) -> R
where F: FnOnce(&EncodingContext, &mut OpaqueEncoder) -> R
{
TLS_ENCODING.with(|tls| {
let tls_payload = (tls as *const TlsPayload)
as *mut (&EncodingContext, &mut RbmlEncoder);
as *mut (&EncodingContext, &mut OpaqueEncoder);
f((*tls_payload).0, (*tls_payload).1)
})
}
pub trait DecodingContext<'tcx> {
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
fn decode_ty(&self, rbml_r: &mut RbmlDecoder) -> ty::Ty<'tcx>;
fn decode_substs(&self, rbml_r: &mut RbmlDecoder) -> Substs<'tcx>;
fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx>;
fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> Substs<'tcx>;
fn translate_def_id(&self, def_id: DefId) -> DefId;
}
@ -510,13 +510,13 @@ pub mod tls {
/// Execute f after pushing the given DecodingContext onto the TLS stack.
pub fn enter_decoding_context<'tcx, F, R>(dcx: &DecodingContext<'tcx>,
rbml_r: &mut RbmlDecoder,
decoder: &mut OpaqueDecoder,
f: F) -> R
where F: FnOnce(&DecodingContext<'tcx>, &mut RbmlDecoder) -> R
where F: FnOnce(&DecodingContext<'tcx>, &mut OpaqueDecoder) -> R
{
let tls_payload = (dcx as *const _, rbml_r as *mut _);
let tls_payload = (dcx as *const _, decoder as *mut _);
let tls_ptr = &tls_payload as *const _ as *const TlsPayload;
TLS_DECODING.set(unsafe { &*tls_ptr }, || f(dcx, rbml_r))
TLS_DECODING.set(unsafe { &*tls_ptr }, || f(dcx, decoder))
}
/// Execute f with access to the thread-local decoding context and
@ -530,16 +530,16 @@ pub mod tls {
pub fn with_decoding_context<'decoder, 'tcx, D, F, R>(d: &'decoder mut D, f: F) -> R
where D: serialize::Decoder,
F: FnOnce(&DecodingContext<'tcx>,
&mut RbmlDecoder) -> R,
&mut OpaqueDecoder) -> R,
'tcx: 'decoder
{
unsafe {
unsafe_with_decoding_context(|dcx, rbml_r| {
assert!((d as *mut _ as usize) == (rbml_r as *mut _ as usize));
unsafe_with_decoding_context(|dcx, decoder| {
assert!((d as *mut _ as usize) == (decoder as *mut _ as usize));
let dcx: &DecodingContext<'tcx> = mem::transmute(dcx);
f(dcx, rbml_r)
f(dcx, decoder)
})
}
}
@ -547,11 +547,11 @@ pub mod tls {
/// Execute f with access to the thread-local decoding context and
/// rbml decoder.
pub unsafe fn unsafe_with_decoding_context<F, R>(f: F) -> R
where F: FnOnce(&DecodingContext, &mut RbmlDecoder) -> R
where F: FnOnce(&DecodingContext, &mut OpaqueDecoder) -> R
{
TLS_DECODING.with(|tls| {
let tls_payload = (tls as *const TlsPayload)
as *mut (&DecodingContext, &mut RbmlDecoder);
as *mut (&DecodingContext, &mut OpaqueDecoder);
f((*tls_payload).0, (*tls_payload).1)
})
}

View File

@ -292,7 +292,7 @@ impl<D:serialize::Decoder> def_id_decoder_helpers for D
fn encode_ast(rbml_w: &mut Encoder, item: &InlinedItem) {
rbml_w.start_tag(c::tag_tree as usize);
item.encode(rbml_w);
rbml_w.emit_opaque(|this| item.encode(this));
rbml_w.end_tag();
}
@ -361,8 +361,8 @@ fn simplify_ast(ii: InlinedItemRef) -> InlinedItem {
fn decode_ast(par_doc: rbml::Doc) -> InlinedItem {
let chi_doc = par_doc.get(c::tag_tree as usize);
let mut d = reader::Decoder::new(chi_doc);
Decodable::decode(&mut d).unwrap()
let mut rbml_r = reader::Decoder::new(chi_doc);
rbml_r.read_opaque(|decoder, _| Decodable::decode(decoder)).unwrap()
}
// ______________________________________________________________________
@ -509,21 +509,6 @@ pub fn encode_cast_kind(ebml_w: &mut Encoder, kind: cast::CastKind) {
// ______________________________________________________________________
// Encoding and decoding the side tables
trait get_ty_str_ctxt<'tcx> {
fn ty_str_ctxt<'a>(&'a self) -> tyencode::ctxt<'a, 'tcx>;
}
impl<'a, 'tcx> get_ty_str_ctxt<'tcx> for e::EncodeContext<'a, 'tcx> {
fn ty_str_ctxt<'b>(&'b self) -> tyencode::ctxt<'b, 'tcx> {
tyencode::ctxt {
diag: self.tcx.sess.diagnostic(),
ds: e::def_to_string,
tcx: self.tcx,
abbrevs: &self.type_abbrevs
}
}
}
trait rbml_writer_helpers<'tcx> {
fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region);
fn emit_ty<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, ty: Ty<'tcx>);
@ -548,11 +533,15 @@ trait rbml_writer_helpers<'tcx> {
impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region) {
self.emit_opaque(|this| Ok(e::write_region(ecx, this, r)));
self.emit_opaque(|this| Ok(tyencode::enc_region(&mut this.cursor,
&ecx.ty_str_ctxt(),
r)));
}
fn emit_ty<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, ty: Ty<'tcx>) {
self.emit_opaque(|this| Ok(e::write_type(ecx, this, ty)));
self.emit_opaque(|this| Ok(tyencode::enc_ty(&mut this.cursor,
&ecx.ty_str_ctxt(),
ty)));
}
fn emit_tys<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, tys: &[Ty<'tcx>]) {
@ -561,13 +550,15 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
fn emit_trait_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
trait_ref: &ty::TraitRef<'tcx>) {
self.emit_opaque(|this| Ok(e::write_trait_ref(ecx, this, trait_ref)));
self.emit_opaque(|this| Ok(tyencode::enc_trait_ref(&mut this.cursor,
&ecx.ty_str_ctxt(),
*trait_ref)));
}
fn emit_predicate<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
predicate: &ty::Predicate<'tcx>) {
self.emit_opaque(|this| {
Ok(tyencode::enc_predicate(this,
Ok(tyencode::enc_predicate(&mut this.cursor,
&ecx.ty_str_ctxt(),
predicate))
});
@ -575,13 +566,13 @@ 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,
self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(&mut this.cursor,
&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,
self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(&mut this.cursor,
&ecx.ty_str_ctxt(),
bounds)));
}
@ -608,7 +599,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
fn emit_substs<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
substs: &subst::Substs<'tcx>) {
self.emit_opaque(|this| Ok(tyencode::enc_substs(this,
self.emit_opaque(|this| Ok(tyencode::enc_substs(&mut this.cursor,
&ecx.ty_str_ctxt(),
substs)));
}
@ -878,10 +869,6 @@ trait rbml_decoder_decoder_helpers<'tcx> {
-> adjustment::AutoDerefRef<'tcx>;
fn read_autoref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> adjustment::AutoRef<'tcx>;
fn convert_def_id(&mut self,
dcx: &DecodeContext,
did: DefId)
-> DefId;
// Versions of the type reading functions that don't need the full
// DecodeContext.
@ -933,12 +920,12 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
fn read_ty_encoded<'b, 'c, F, R>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>, op: F) -> R
where F: for<'x> FnOnce(&mut tydecode::TyDecoder<'x,'tcx>) -> R
{
return self.read_opaque(|this, doc| {
return self.read_opaque(|_, doc| {
debug!("read_ty_encoded({})", type_string(doc));
Ok(op(
&mut tydecode::TyDecoder::with_doc(
dcx.tcx, dcx.cdata.cnum, doc,
&mut |a| this.convert_def_id(dcx, a))))
&mut |d| convert_def_id(dcx, d))))
}).unwrap();
fn type_string(doc: rbml::Doc) -> String {
@ -989,9 +976,9 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
fn read_substs<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-> subst::Substs<'tcx> {
self.read_opaque(|this, doc| {
self.read_opaque(|_, doc| {
Ok(tydecode::TyDecoder::with_doc(dcx.tcx, dcx.cdata.cnum, doc,
&mut |a| this.convert_def_id(dcx, a))
&mut |d| convert_def_id(dcx, d))
.parse_substs())
}).unwrap()
}
@ -1097,48 +1084,47 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
{
Decodable::decode(self).unwrap()
}
}
/// Converts a def-id that appears in a type. The correct
/// translation will depend on what kind of def-id this is.
/// This is a subtle point: type definitions are not
/// inlined into the current crate, so if the def-id names
/// a nominal type or type alias, then it should be
/// translated to refer to the source crate.
///
/// However, *type parameters* are cloned along with the function
/// they are attached to. So we should translate those def-ids
/// to refer to the new, cloned copy of the type parameter.
/// We only see references to free type parameters in the body of
/// an inlined function. In such cases, we need the def-id to
/// be a local id so that the TypeContents code is able to lookup
/// the relevant info in the ty_param_defs table.
///
/// *Region parameters*, unfortunately, are another kettle of fish.
/// In such cases, def_id's can appear in types to distinguish
/// shadowed bound regions and so forth. It doesn't actually
/// matter so much what we do to these, since regions are erased
/// at trans time, but it's good to keep them consistent just in
/// case. We translate them with `tr_def_id()` which will map
/// the crate numbers back to the original source crate.
///
/// Scopes will end up as being totally bogus. This can actually
/// be fixed though.
///
/// Unboxed closures are cloned along with the function being
/// inlined, and all side tables use interned node IDs, so we
/// translate their def IDs accordingly.
///
/// It'd be really nice to refactor the type repr to not include
/// def-ids so that all these distinctions were unnecessary.
fn convert_def_id(&mut self,
dcx: &DecodeContext,
// Converts a def-id that appears in a type. The correct
// translation will depend on what kind of def-id this is.
// This is a subtle point: type definitions are not
// inlined into the current crate, so if the def-id names
// a nominal type or type alias, then it should be
// translated to refer to the source crate.
//
// However, *type parameters* are cloned along with the function
// they are attached to. So we should translate those def-ids
// to refer to the new, cloned copy of the type parameter.
// We only see references to free type parameters in the body of
// an inlined function. In such cases, we need the def-id to
// be a local id so that the TypeContents code is able to lookup
// the relevant info in the ty_param_defs table.
//
// *Region parameters*, unfortunately, are another kettle of fish.
// In such cases, def_id's can appear in types to distinguish
// shadowed bound regions and so forth. It doesn't actually
// matter so much what we do to these, since regions are erased
// at trans time, but it's good to keep them consistent just in
// case. We translate them with `tr_def_id()` which will map
// the crate numbers back to the original source crate.
//
// Scopes will end up as being totally bogus. This can actually
// be fixed though.
//
// Unboxed closures are cloned along with the function being
// inlined, and all side tables use interned node IDs, so we
// translate their def IDs accordingly.
//
// It'd be really nice to refactor the type repr to not include
// def-ids so that all these distinctions were unnecessary.
fn convert_def_id(dcx: &DecodeContext,
did: DefId)
-> DefId {
let r = dcx.tr_def_id(did);
debug!("convert_def_id(did={:?})={:?}", did, r);
return r;
}
}
fn decode_side_tables(dcx: &DecodeContext,
ast_doc: rbml::Doc) {

View File

@ -833,9 +833,11 @@ pub fn maybe_get_item_mir<'tcx>(cdata: Cmd,
};
let mut decoder = reader::Decoder::new(mir_doc);
let mut mir = tls::enter_decoding_context(&dcx, &mut decoder, |_, decoder| {
Decodable::decode(decoder).unwrap()
});
let mut mir = decoder.read_opaque(|opaque_decoder, _| {
tls::enter_decoding_context(&dcx, opaque_decoder, |_, opaque_decoder| {
Decodable::decode(opaque_decoder)
})
}).unwrap();
let mut def_id_and_span_translator = MirDefIdAndSpanTranslator {
crate_metadata: cdata,
@ -1643,7 +1645,9 @@ pub fn get_imported_filemaps(metadata: &[u8]) -> Vec<codemap::FileMap> {
reader::tagged_docs(cm_doc, tag_codemap_filemap).map(|filemap_doc| {
let mut decoder = reader::Decoder::new(filemap_doc);
Decodable::decode(&mut decoder).unwrap()
decoder.read_opaque(|opaque_decoder, _| {
Decodable::decode(opaque_decoder)
}).unwrap()
}).collect()
}

View File

@ -140,15 +140,9 @@ fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder,
ecx: &EncodeContext<'a, 'tcx>,
trait_ref: ty::TraitRef<'tcx>,
tag: usize) {
let ty_str_ctxt = &tyencode::ctxt {
diag: ecx.diag,
ds: def_to_string,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
rbml_w.start_tag(tag);
tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, trait_ref);
tyencode::enc_trait_ref(rbml_w.writer, &ecx.ty_str_ctxt(), trait_ref);
rbml_w.mark_stable_position();
rbml_w.end_tag();
}
@ -202,59 +196,19 @@ fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) {
rbml_w.wr_tagged_u64(tag_mod_child, id);
}
pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
rbml_w: &mut Encoder,
closure_type: &ty::ClosureTy<'tcx>) {
let ty_str_ctxt = &tyencode::ctxt {
diag: ecx.diag,
ds: def_to_string,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
tyencode::enc_closure_ty(rbml_w, ty_str_ctxt, closure_type);
}
pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
rbml_w: &mut Encoder,
typ: Ty<'tcx>) {
let ty_str_ctxt = &tyencode::ctxt {
diag: ecx.diag,
ds: def_to_string,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
tyencode::enc_ty(rbml_w, ty_str_ctxt, typ);
}
pub fn write_trait_ref<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
rbml_w: &mut Encoder,
trait_ref: &ty::TraitRef<'tcx>) {
let ty_str_ctxt = &tyencode::ctxt {
diag: ecx.diag,
ds: def_to_string,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, *trait_ref);
}
pub fn write_region(ecx: &EncodeContext,
rbml_w: &mut Encoder,
r: ty::Region) {
let ty_str_ctxt = &tyencode::ctxt {
diag: ecx.diag,
ds: def_to_string,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
tyencode::enc_region(rbml_w, ty_str_ctxt, r);
tyencode::enc_closure_ty(rbml_w.writer, &ecx.ty_str_ctxt(), closure_type);
rbml_w.mark_stable_position();
}
fn encode_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
rbml_w: &mut Encoder,
typ: Ty<'tcx>) {
rbml_w.start_tag(tag_items_data_item_type);
write_type(ecx, rbml_w, typ);
tyencode::enc_ty(rbml_w.writer, &ecx.ty_str_ctxt(), typ);
rbml_w.mark_stable_position();
rbml_w.end_tag();
}
@ -262,7 +216,8 @@ fn encode_region(ecx: &EncodeContext,
rbml_w: &mut Encoder,
r: ty::Region) {
rbml_w.start_tag(tag_items_data_region);
write_region(ecx, rbml_w, r);
tyencode::enc_region(rbml_w.writer, &ecx.ty_str_ctxt(), r);
rbml_w.mark_stable_position();
rbml_w.end_tag();
}
@ -592,17 +547,10 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
{
rbml_w.start_tag(tag);
// Type parameters
let ty_str_ctxt = &tyencode::ctxt {
diag: ecx.diag,
ds: def_to_string,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
for param in &generics.types {
rbml_w.start_tag(tag_type_param_def);
tyencode::enc_type_param_def(rbml_w, ty_str_ctxt, param);
tyencode::enc_type_param_def(rbml_w.writer, &ecx.ty_str_ctxt(), param);
rbml_w.mark_stable_position();
rbml_w.end_tag();
}
@ -871,7 +819,11 @@ fn encode_mir(ecx: &EncodeContext, rbml_w: &mut Encoder, ii: InlinedItemRef) {
if let Some(mir) = ecx.mir_map.get(&id) {
rbml_w.start_tag(tag_mir as usize);
Encodable::encode(mir, rbml_w).unwrap();
rbml_w.emit_opaque(|opaque_encoder| {
tls::enter_encoding_context(ecx, opaque_encoder, |_, opaque_encoder| {
Encodable::encode(mir, opaque_encoder)
})
}).unwrap();
rbml_w.end_tag();
}
}
@ -916,23 +868,17 @@ fn encode_xrefs<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
rbml_w: &mut Encoder,
xrefs: FnvHashMap<XRef<'tcx>, u32>)
{
let ty_str_ctxt = &tyencode::ctxt {
diag: ecx.diag,
ds: def_to_string,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
let mut xref_positions = vec![0; xrefs.len()];
rbml_w.start_tag(tag_xref_data);
for (xref, id) in xrefs.into_iter() {
xref_positions[id as usize] = rbml_w.mark_stable_position() as u32;
match xref {
XRef::Predicate(p) => {
tyencode::enc_predicate(rbml_w, ty_str_ctxt, &p)
tyencode::enc_predicate(rbml_w.writer, &ecx.ty_str_ctxt(), &p)
}
}
}
rbml_w.mark_stable_position();
rbml_w.end_tag();
rbml_w.start_tag(tag_xref_index);
@ -1750,7 +1696,9 @@ fn encode_codemap(ecx: &EncodeContext, rbml_w: &mut Encoder) {
}
rbml_w.start_tag(tag_codemap_filemap);
filemap.encode(rbml_w);
rbml_w.emit_opaque(|opaque_encoder| {
filemap.encode(opaque_encoder)
}).unwrap();
rbml_w.end_tag();
}
@ -1961,9 +1909,7 @@ pub fn encode_metadata(parms: EncodeParams, krate: &hir::Crate) -> Vec<u8> {
{
let mut rbml_w = Encoder::new(&mut wr);
tls::enter_encoding_context(&ecx, &mut rbml_w, |_, rbml_w| {
encode_metadata_inner(rbml_w, &ecx, krate)
});
encode_metadata_inner(&mut rbml_w, &ecx, krate)
}
// RBML compacts the encoded bytes whenever appropriate,
@ -2132,7 +2078,7 @@ fn encode_metadata_inner(rbml_w: &mut Encoder,
// Get the encoded string for a type
pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Vec<u8> {
let mut wr = Cursor::new(Vec::new());
tyencode::enc_ty(&mut Encoder::new(&mut wr), &tyencode::ctxt {
tyencode::enc_ty(&mut wr, &tyencode::ctxt {
diag: tcx.sess.diagnostic(),
ds: def_to_string,
tcx: tcx,

View File

@ -11,8 +11,8 @@
// This module provides implementations for the thread-local encoding and
// decoding context traits in rustc::middle::cstore::tls.
use rbml::writer::Encoder as RbmlEncoder;
use rbml::reader::Decoder as RbmlDecoder;
use rbml::opaque::Encoder as OpaqueEncoder;
use rbml::opaque::Decoder as OpaqueDecoder;
use rustc::middle::cstore::tls;
use rustc::middle::def_id::DefId;
use rustc::middle::subst::Substs;
@ -23,25 +23,18 @@ use encoder;
use tydecode::TyDecoder;
use tyencode;
impl<'a, 'tcx: 'a> tls::EncodingContext<'tcx> for encoder::EncodeContext<'a, 'tcx> {
fn tcx<'s>(&'s self) -> &'s ty::ctxt<'tcx> {
&self.tcx
}
fn encode_ty(&self, rbml_w: &mut RbmlEncoder, t: ty::Ty<'tcx>) {
encoder::write_type(self, rbml_w, t);
fn encode_ty(&self, encoder: &mut OpaqueEncoder, t: ty::Ty<'tcx>) {
tyencode::enc_ty(encoder.cursor, &self.ty_str_ctxt(), t);
}
fn encode_substs(&self, rbml_w: &mut RbmlEncoder, substs: &Substs<'tcx>) {
let ty_str_ctxt = &tyencode::ctxt {
diag: self.diag,
ds: encoder::def_to_string,
tcx: self.tcx,
abbrevs: &self.type_abbrevs
};
tyencode::enc_substs(rbml_w, ty_str_ctxt, substs);
fn encode_substs(&self, encoder: &mut OpaqueEncoder, substs: &Substs<'tcx>) {
tyencode::enc_substs(encoder.cursor, &self.ty_str_ctxt(), substs);
}
}
@ -56,12 +49,12 @@ impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> {
&self.tcx
}
fn decode_ty(&self, rbml_r: &mut RbmlDecoder) -> ty::Ty<'tcx> {
fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx> {
let def_id_convert = &mut |did| {
decoder::translate_def_id(self.crate_metadata, did)
};
let starting_position = rbml_r.position();
let starting_position = decoder.position();
let mut ty_decoder = TyDecoder::new(
self.crate_metadata.data.as_slice(),
@ -77,16 +70,16 @@ impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> {
// We can just reuse the tydecode implementation for parsing types, but
// we have to make sure to leave the rbml reader at the position just
// after the type.
rbml_r.advance(end_position - starting_position);
decoder.advance(end_position - starting_position);
ty
}
fn decode_substs(&self, rbml_r: &mut RbmlDecoder) -> Substs<'tcx> {
fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> Substs<'tcx> {
let def_id_convert = &mut |did| {
decoder::translate_def_id(self.crate_metadata, did)
};
let starting_position = rbml_r.position();
let starting_position = decoder.position();
let mut ty_decoder = TyDecoder::new(
self.crate_metadata.data.as_slice(),
@ -99,7 +92,7 @@ impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> {
let end_position = ty_decoder.position();
rbml_r.advance(end_position - starting_position);
decoder.advance(end_position - starting_position);
substs
}

View File

@ -25,6 +25,7 @@ use middle::subst::VecPerParamSpace;
use middle::ty::{self, ToPredicate, Ty, HasTypeFlags};
use rbml;
use rbml::leb128;
use std::str;
use syntax::abi;
use syntax::ast;
@ -103,9 +104,10 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
}
fn parse_vuint(&mut self) -> usize {
let res = rbml::reader::vuint_at(self.data, self.pos).unwrap();
self.pos = res.next;
res.val
let (value, bytes_read) = leb128::read_unsigned_leb128(self.data,
self.pos);
self.pos += bytes_read;
value as usize
}
fn parse_name(&mut self, last: char) -> ast::Name {

View File

@ -31,9 +31,8 @@ use syntax::abi::Abi;
use syntax::ast;
use syntax::errors::Handler;
use rbml::writer::{self, Encoder};
macro_rules! mywrite { ($w:expr, $($arg:tt)*) => ({ write!($w.writer, $($arg)*); }) }
use rbml::leb128;
use encoder;
pub struct ctxt<'a, 'tcx: 'a> {
pub diag: &'a Handler,
@ -44,6 +43,17 @@ pub struct ctxt<'a, 'tcx: 'a> {
pub abbrevs: &'a abbrev_map<'tcx>
}
impl<'a, 'tcx> encoder::EncodeContext<'a, 'tcx> {
pub fn ty_str_ctxt<'b>(&'b self) -> ctxt<'b, 'tcx> {
ctxt {
diag: self.tcx.sess.diagnostic(),
ds: encoder::def_to_string,
tcx: self.tcx,
abbrevs: &self.type_abbrevs
}
}
}
// Compact string representation for Ty values. API TyStr & parse_from_str.
// Extra parameters are for converting to/from def_ids in the string rep.
// Whatever format you choose should not contain pipe characters.
@ -53,125 +63,129 @@ pub struct ty_abbrev {
pub type abbrev_map<'tcx> = RefCell<FnvHashMap<Ty<'tcx>, ty_abbrev>>;
pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
pub fn enc_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
match cx.abbrevs.borrow_mut().get(&t) {
Some(a) => { w.writer.write_all(&a.s); return; }
Some(a) => { w.write_all(&a.s); return; }
None => {}
}
// type abbreviations needs a stable position
let pos = w.mark_stable_position();
let pos = w.position();
match t.sty {
ty::TyBool => mywrite!(w, "b"),
ty::TyChar => mywrite!(w, "c"),
ty::TyBool => { write!(w, "b"); }
ty::TyChar => { write!(w, "c"); }
ty::TyInt(t) => {
match t {
ast::TyIs => mywrite!(w, "is"),
ast::TyI8 => mywrite!(w, "MB"),
ast::TyI16 => mywrite!(w, "MW"),
ast::TyI32 => mywrite!(w, "ML"),
ast::TyI64 => mywrite!(w, "MD")
}
ast::TyIs => write!(w, "is"),
ast::TyI8 => write!(w, "MB"),
ast::TyI16 => write!(w, "MW"),
ast::TyI32 => write!(w, "ML"),
ast::TyI64 => write!(w, "MD")
};
}
ty::TyUint(t) => {
match t {
ast::TyUs => mywrite!(w, "us"),
ast::TyU8 => mywrite!(w, "Mb"),
ast::TyU16 => mywrite!(w, "Mw"),
ast::TyU32 => mywrite!(w, "Ml"),
ast::TyU64 => mywrite!(w, "Md")
}
ast::TyUs => write!(w, "us"),
ast::TyU8 => write!(w, "Mb"),
ast::TyU16 => write!(w, "Mw"),
ast::TyU32 => write!(w, "Ml"),
ast::TyU64 => write!(w, "Md")
};
}
ty::TyFloat(t) => {
match t {
ast::TyF32 => mywrite!(w, "Mf"),
ast::TyF64 => mywrite!(w, "MF"),
}
ast::TyF32 => write!(w, "Mf"),
ast::TyF64 => write!(w, "MF"),
};
}
ty::TyEnum(def, substs) => {
mywrite!(w, "t[{}|", (cx.ds)(def.did));
write!(w, "t[{}|", (cx.ds)(def.did));
enc_substs(w, cx, substs);
mywrite!(w, "]");
write!(w, "]");
}
ty::TyTrait(box ty::TraitTy { ref principal,
ref bounds }) => {
mywrite!(w, "x[");
write!(w, "x[");
enc_trait_ref(w, cx, principal.0);
enc_existential_bounds(w, cx, bounds);
mywrite!(w, "]");
write!(w, "]");
}
ty::TyTuple(ref ts) => {
mywrite!(w, "T[");
write!(w, "T[");
for t in ts { enc_ty(w, cx, *t); }
mywrite!(w, "]");
write!(w, "]");
}
ty::TyBox(typ) => { mywrite!(w, "~"); enc_ty(w, cx, typ); }
ty::TyRawPtr(mt) => { mywrite!(w, "*"); enc_mt(w, cx, mt); }
ty::TyBox(typ) => { write!(w, "~"); enc_ty(w, cx, typ); }
ty::TyRawPtr(mt) => { write!(w, "*"); enc_mt(w, cx, mt); }
ty::TyRef(r, mt) => {
mywrite!(w, "&");
write!(w, "&");
enc_region(w, cx, *r);
enc_mt(w, cx, mt);
}
ty::TyArray(t, sz) => {
mywrite!(w, "V");
write!(w, "V");
enc_ty(w, cx, t);
mywrite!(w, "/{}|", sz);
write!(w, "/{}|", sz);
}
ty::TySlice(t) => {
mywrite!(w, "V");
write!(w, "V");
enc_ty(w, cx, t);
mywrite!(w, "/|");
write!(w, "/|");
}
ty::TyStr => {
mywrite!(w, "v");
write!(w, "v");
}
ty::TyBareFn(Some(def_id), f) => {
mywrite!(w, "F");
mywrite!(w, "{}|", (cx.ds)(def_id));
write!(w, "F");
write!(w, "{}|", (cx.ds)(def_id));
enc_bare_fn_ty(w, cx, f);
}
ty::TyBareFn(None, f) => {
mywrite!(w, "G");
write!(w, "G");
enc_bare_fn_ty(w, cx, f);
}
ty::TyInfer(_) => {
cx.diag.bug("cannot encode inference variable types");
}
ty::TyParam(ParamTy {space, idx, name}) => {
mywrite!(w, "p[{}|{}|{}]", idx, space.to_uint(), name)
write!(w, "p[{}|{}|{}]", idx, space.to_uint(), name);
}
ty::TyStruct(def, substs) => {
mywrite!(w, "a[{}|", (cx.ds)(def.did));
write!(w, "a[{}|", (cx.ds)(def.did));
enc_substs(w, cx, substs);
mywrite!(w, "]");
write!(w, "]");
}
ty::TyClosure(def, ref substs) => {
mywrite!(w, "k[{}|", (cx.ds)(def));
write!(w, "k[{}|", (cx.ds)(def));
enc_substs(w, cx, &substs.func_substs);
for ty in &substs.upvar_tys {
enc_ty(w, cx, ty);
}
mywrite!(w, ".");
mywrite!(w, "]");
write!(w, ".");
write!(w, "]");
}
ty::TyProjection(ref data) => {
mywrite!(w, "P[");
write!(w, "P[");
enc_trait_ref(w, cx, data.trait_ref);
mywrite!(w, "{}]", data.item_name);
write!(w, "{}]", data.item_name);
}
ty::TyError => {
mywrite!(w, "e");
write!(w, "e");
}
}
let end = w.mark_stable_position();
let end = w.position();
let len = end - pos;
let buf: &mut [u8] = &mut [0; 16]; // vuint < 15 bytes
let mut abbrev = Cursor::new(buf);
let mut abbrev = Cursor::new(Vec::with_capacity(16));
abbrev.write_all(b"#");
writer::write_vuint(&mut abbrev, pos as usize);
{
let start_position = abbrev.position() as usize;
let bytes_written = leb128::write_unsigned_leb128(abbrev.get_mut(),
start_position,
pos);
abbrev.set_position((start_position + bytes_written) as u64);
}
cx.abbrevs.borrow_mut().insert(t, ty_abbrev {
s: if abbrev.position() < len {
@ -180,101 +194,105 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
// if the abbreviation is longer than the real type,
// don't use #-notation. However, insert it here so
// other won't have to `mark_stable_position`
w.writer.get_ref()[pos as usize..end as usize].to_owned()
w.get_ref()[pos as usize .. end as usize].to_owned()
}
});
}
fn enc_mutability(w: &mut Encoder, mt: hir::Mutability) {
fn enc_mutability(w: &mut Cursor<Vec<u8>>, mt: hir::Mutability) {
match mt {
hir::MutImmutable => (),
hir::MutMutable => mywrite!(w, "m"),
hir::MutMutable => {
write!(w, "m");
}
};
}
fn enc_mt<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
fn enc_mt<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
mt: ty::TypeAndMut<'tcx>) {
enc_mutability(w, mt.mutbl);
enc_ty(w, cx, mt.ty);
}
fn enc_opt<T, F>(w: &mut Encoder, t: Option<T>, enc_f: F) where
F: FnOnce(&mut Encoder, T),
fn enc_opt<T, F>(w: &mut Cursor<Vec<u8>>, t: Option<T>, enc_f: F) where
F: FnOnce(&mut Cursor<Vec<u8>>, T),
{
match t {
None => mywrite!(w, "n"),
None => {
write!(w, "n");
}
Some(v) => {
mywrite!(w, "s");
write!(w, "s");
enc_f(w, v);
}
}
}
fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut Encoder,
fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut Cursor<Vec<u8>>,
cx: &ctxt<'a, 'tcx>,
v: &VecPerParamSpace<T>,
mut op: F) where
F: FnMut(&mut Encoder, &ctxt<'a, 'tcx>, &T),
F: FnMut(&mut Cursor<Vec<u8>>, &ctxt<'a, 'tcx>, &T),
{
for &space in &subst::ParamSpace::all() {
mywrite!(w, "[");
write!(w, "[");
for t in v.get_slice(space) {
op(w, cx, t);
}
mywrite!(w, "]");
write!(w, "]");
}
}
pub fn enc_substs<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
pub fn enc_substs<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, 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 Encoder, cx: &ctxt, substs: &subst::RegionSubsts) {
fn enc_region_substs(w: &mut Cursor<Vec<u8>>, cx: &ctxt, substs: &subst::RegionSubsts) {
match *substs {
subst::ErasedRegions => {
mywrite!(w, "e");
write!(w, "e");
}
subst::NonerasedRegions(ref regions) => {
mywrite!(w, "n");
write!(w, "n");
enc_vec_per_param_space(w, cx, regions,
|w, cx, &r| enc_region(w, cx, r));
}
}
}
pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) {
pub fn enc_region(w: &mut Cursor<Vec<u8>>, cx: &ctxt, r: ty::Region) {
match r {
ty::ReLateBound(id, br) => {
mywrite!(w, "b[{}|", id.depth);
write!(w, "b[{}|", id.depth);
enc_bound_region(w, cx, br);
mywrite!(w, "]");
write!(w, "]");
}
ty::ReEarlyBound(ref data) => {
mywrite!(w, "B[{}|{}|{}]",
write!(w, "B[{}|{}|{}]",
data.space.to_uint(),
data.index,
data.name);
}
ty::ReFree(ref fr) => {
mywrite!(w, "f[");
write!(w, "f[");
enc_scope(w, cx, fr.scope);
mywrite!(w, "|");
write!(w, "|");
enc_bound_region(w, cx, fr.bound_region);
mywrite!(w, "]");
write!(w, "]");
}
ty::ReScope(scope) => {
mywrite!(w, "s");
write!(w, "s");
enc_scope(w, cx, scope);
mywrite!(w, "|");
write!(w, "|");
}
ty::ReStatic => {
mywrite!(w, "t");
write!(w, "t");
}
ty::ReEmpty => {
mywrite!(w, "e");
write!(w, "e");
}
ty::ReVar(_) | ty::ReSkolemized(..) => {
// these should not crop up after typeck
@ -283,107 +301,107 @@ pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) {
}
}
fn enc_scope(w: &mut Encoder, cx: &ctxt, scope: region::CodeExtent) {
fn enc_scope(w: &mut Cursor<Vec<u8>>, cx: &ctxt, scope: region::CodeExtent) {
match cx.tcx.region_maps.code_extent_data(scope) {
region::CodeExtentData::CallSiteScope {
fn_id, body_id } => mywrite!(w, "C[{}|{}]", fn_id, body_id),
fn_id, body_id } => write!(w, "C[{}|{}]", fn_id, body_id),
region::CodeExtentData::ParameterScope {
fn_id, body_id } => mywrite!(w, "P[{}|{}]", fn_id, body_id),
region::CodeExtentData::Misc(node_id) => mywrite!(w, "M{}", node_id),
fn_id, body_id } => write!(w, "P[{}|{}]", fn_id, body_id),
region::CodeExtentData::Misc(node_id) => write!(w, "M{}", node_id),
region::CodeExtentData::Remainder(region::BlockRemainder {
block: b, first_statement_index: i }) => mywrite!(w, "B[{}|{}]", b, i),
region::CodeExtentData::DestructionScope(node_id) => mywrite!(w, "D{}", node_id),
}
block: b, first_statement_index: i }) => write!(w, "B[{}|{}]", b, i),
region::CodeExtentData::DestructionScope(node_id) => write!(w, "D{}", node_id),
};
}
fn enc_bound_region(w: &mut Encoder, cx: &ctxt, br: ty::BoundRegion) {
fn enc_bound_region(w: &mut Cursor<Vec<u8>>, cx: &ctxt, br: ty::BoundRegion) {
match br {
ty::BrAnon(idx) => {
mywrite!(w, "a{}|", idx);
write!(w, "a{}|", idx);
}
ty::BrNamed(d, name) => {
mywrite!(w, "[{}|{}]",
write!(w, "[{}|{}]",
(cx.ds)(d),
name);
}
ty::BrFresh(id) => {
mywrite!(w, "f{}|", id);
write!(w, "f{}|", id);
}
ty::BrEnv => {
mywrite!(w, "e|");
write!(w, "e|");
}
}
}
pub fn enc_trait_ref<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
pub fn enc_trait_ref<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
s: ty::TraitRef<'tcx>) {
mywrite!(w, "{}|", (cx.ds)(s.def_id));
write!(w, "{}|", (cx.ds)(s.def_id));
enc_substs(w, cx, s.substs);
}
fn enc_unsafety(w: &mut Encoder, p: hir::Unsafety) {
fn enc_unsafety(w: &mut Cursor<Vec<u8>>, p: hir::Unsafety) {
match p {
hir::Unsafety::Normal => mywrite!(w, "n"),
hir::Unsafety::Unsafe => mywrite!(w, "u"),
}
hir::Unsafety::Normal => write!(w, "n"),
hir::Unsafety::Unsafe => write!(w, "u"),
};
}
fn enc_abi(w: &mut Encoder, abi: Abi) {
mywrite!(w, "[");
mywrite!(w, "{}", abi.name());
mywrite!(w, "]")
fn enc_abi(w: &mut Cursor<Vec<u8>>, abi: Abi) {
write!(w, "[");
write!(w, "{}", abi.name());
write!(w, "]");
}
pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, 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 Encoder, cx: &ctxt<'a, 'tcx>,
pub fn enc_closure_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, 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 Encoder, cx: &ctxt<'a, 'tcx>,
fn enc_fn_sig<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
fsig: &ty::PolyFnSig<'tcx>) {
mywrite!(w, "[");
write!(w, "[");
for ty in &fsig.0.inputs {
enc_ty(w, cx, *ty);
}
mywrite!(w, "]");
write!(w, "]");
if fsig.0.variadic {
mywrite!(w, "V");
write!(w, "V");
} else {
mywrite!(w, "N");
write!(w, "N");
}
match fsig.0.output {
ty::FnConverging(result_type) => {
enc_ty(w, cx, result_type);
}
ty::FnDiverging => {
mywrite!(w, "z");
write!(w, "z");
}
}
}
pub fn enc_builtin_bounds(w: &mut Encoder, _cx: &ctxt, bs: &ty::BuiltinBounds) {
pub fn enc_builtin_bounds(w: &mut Cursor<Vec<u8>>, _cx: &ctxt, bs: &ty::BuiltinBounds) {
for bound in bs {
match bound {
ty::BoundSend => mywrite!(w, "S"),
ty::BoundSized => mywrite!(w, "Z"),
ty::BoundCopy => mywrite!(w, "P"),
ty::BoundSync => mywrite!(w, "T"),
}
ty::BoundSend => write!(w, "S"),
ty::BoundSized => write!(w, "Z"),
ty::BoundCopy => write!(w, "P"),
ty::BoundSync => write!(w, "T"),
};
}
mywrite!(w, ".");
write!(w, ".");
}
pub fn enc_existential_bounds<'a,'tcx>(w: &mut Encoder,
pub fn enc_existential_bounds<'a,'tcx>(w: &mut Cursor<Vec<u8>>,
cx: &ctxt<'a,'tcx>,
bs: &ty::ExistentialBounds<'tcx>) {
enc_builtin_bounds(w, cx, &bs.builtin_bounds);
@ -391,90 +409,94 @@ pub fn enc_existential_bounds<'a,'tcx>(w: &mut Encoder,
enc_region(w, cx, bs.region_bound);
for tp in &bs.projection_bounds {
mywrite!(w, "P");
write!(w, "P");
enc_projection_predicate(w, cx, &tp.0);
}
mywrite!(w, ".");
write!(w, ".");
}
pub fn enc_type_param_def<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
pub fn enc_type_param_def<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
v: &ty::TypeParameterDef<'tcx>) {
mywrite!(w, "{}:{}|{}|{}|{}|",
write!(w, "{}:{}|{}|{}|{}|",
v.name, (cx.ds)(v.def_id),
v.space.to_uint(), v.index, (cx.ds)(v.default_def_id));
enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
enc_object_lifetime_default(w, cx, v.object_lifetime_default);
}
pub fn enc_region_param_def(w: &mut Encoder, cx: &ctxt,
pub fn enc_region_param_def(w: &mut Cursor<Vec<u8>>, cx: &ctxt,
v: &ty::RegionParameterDef) {
mywrite!(w, "{}:{}|{}|{}|",
write!(w, "{}:{}|{}|{}|",
v.name, (cx.ds)(v.def_id),
v.space.to_uint(), v.index);
for &r in &v.bounds {
mywrite!(w, "R");
write!(w, "R");
enc_region(w, cx, r);
}
mywrite!(w, ".");
write!(w, ".");
}
fn enc_object_lifetime_default<'a, 'tcx>(w: &mut Encoder,
fn enc_object_lifetime_default<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
cx: &ctxt<'a, 'tcx>,
default: ty::ObjectLifetimeDefault)
{
match default {
ty::ObjectLifetimeDefault::Ambiguous => mywrite!(w, "a"),
ty::ObjectLifetimeDefault::BaseDefault => mywrite!(w, "b"),
ty::ObjectLifetimeDefault::Ambiguous => {
write!(w, "a");
}
ty::ObjectLifetimeDefault::BaseDefault => {
write!(w, "b");
}
ty::ObjectLifetimeDefault::Specific(r) => {
mywrite!(w, "s");
write!(w, "s");
enc_region(w, cx, r);
}
}
}
pub fn enc_predicate<'a, 'tcx>(w: &mut Encoder,
pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
cx: &ctxt<'a, 'tcx>,
p: &ty::Predicate<'tcx>)
{
match *p {
ty::Predicate::Trait(ref trait_ref) => {
mywrite!(w, "t");
write!(w, "t");
enc_trait_ref(w, cx, trait_ref.0.trait_ref);
}
ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => {
mywrite!(w, "e");
write!(w, "e");
enc_ty(w, cx, a);
enc_ty(w, cx, b);
}
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
mywrite!(w, "r");
write!(w, "r");
enc_region(w, cx, a);
enc_region(w, cx, b);
}
ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
mywrite!(w, "o");
write!(w, "o");
enc_ty(w, cx, a);
enc_region(w, cx, b);
}
ty::Predicate::Projection(ty::Binder(ref data)) => {
mywrite!(w, "p");
enc_projection_predicate(w, cx, data)
write!(w, "p");
enc_projection_predicate(w, cx, data);
}
ty::Predicate::WellFormed(data) => {
mywrite!(w, "w");
write!(w, "w");
enc_ty(w, cx, data);
}
ty::Predicate::ObjectSafe(trait_def_id) => {
mywrite!(w, "O{}|", (cx.ds)(trait_def_id));
write!(w, "O{}|", (cx.ds)(trait_def_id));
}
}
}
fn enc_projection_predicate<'a, 'tcx>(w: &mut Encoder,
fn enc_projection_predicate<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
cx: &ctxt<'a, 'tcx>,
data: &ty::ProjectionPredicate<'tcx>) {
enc_trait_ref(w, cx, data.projection_ty.trait_ref);
mywrite!(w, "{}|", data.projection_ty.item_name);
write!(w, "{}|", data.projection_ty.item_name);
enc_ty(w, cx, data.ty);
}

View File

@ -44,6 +44,7 @@ use middle::pat_util::simple_name;
use middle::subst::Substs;
use middle::ty::{self, Ty, HasTypeFlags};
use rustc::front::map as hir_map;
use rustc::util::common::time;
use rustc_mir::mir_map::MirMap;
use session::config::{self, NoDebugInfo, FullDebugInfo};
use session::Session;
@ -3053,7 +3054,9 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>,
let reachable_symbol_ids = filter_reachable_ids(&shared_ccx);
// Translate the metadata.
let metadata = write_metadata(&shared_ccx, krate, &reachable_symbol_ids, mir_map);
let metadata = time(tcx.sess.time_passes(), "write metadata", || {
write_metadata(&shared_ccx, krate, &reachable_symbol_ids, mir_map)
});
if shared_ccx.sess().trans_stats() {
let stats = shared_ccx.stats();

View File

@ -164,18 +164,15 @@ impl Eq for Span {}
impl Encodable for Span {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
// Encode spans as a single u64 in order to cut down on tagging overhead
// added by the RBML metadata encoding. The should be solved differently
// altogether some time (FIXME #21482)
s.emit_u64( (self.lo.0 as u64) | ((self.hi.0 as u64) << 32) )
try!(s.emit_u32(self.lo.0));
s.emit_u32(self.hi.0)
}
}
impl Decodable for Span {
fn decode<D: Decoder>(d: &mut D) -> Result<Span, D::Error> {
let lo_hi: u64 = try! { d.read_u64() };
let lo = BytePos(lo_hi as u32);
let hi = BytePos((lo_hi >> 32) as u32);
let lo = BytePos(try! { d.read_u32() });
let hi = BytePos(try! { d.read_u32() });
Ok(mk_sp(lo, hi))
}
}