mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Use a more efficient encoding for opaque data in RBML.
This commit is contained in:
parent
89753077fc
commit
fa2a7411e4
162
src/librbml/leb128.rs
Normal file
162
src/librbml/leb128.rs
Normal 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());
|
||||
}
|
@ -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
811
src/librbml/opaque.rs
Normal 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())]);
|
||||
}
|
||||
}
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
@ -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,9 +599,9 @@ 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,
|
||||
&ecx.ty_str_ctxt(),
|
||||
substs)));
|
||||
self.emit_opaque(|this| Ok(tyencode::enc_substs(&mut this.cursor,
|
||||
&ecx.ty_str_ctxt(),
|
||||
substs)));
|
||||
}
|
||||
|
||||
fn emit_auto_adjustment<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
|
||||
@ -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,47 +1084,46 @@ 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,
|
||||
did: DefId)
|
||||
-> DefId {
|
||||
let r = dcx.tr_def_id(did);
|
||||
debug!("convert_def_id(did={:?})={:?}", did, r);
|
||||
return r;
|
||||
}
|
||||
// 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,
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
|
@ -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>,
|
||||
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>,
|
||||
fn write_closure_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);
|
||||
closure_type: &ty::ClosureTy<'tcx>) {
|
||||
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,
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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[{}|{}|{}]",
|
||||
data.space.to_uint(),
|
||||
data.index,
|
||||
data.name);
|
||||
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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user