Rollup merge of #30565 - michaelwoerister:opaque_encoder, r=brson
This PR changes the `emit_opaque` and `read_opaque` methods in the RBML library to use a space-efficient binary encoder that does not emit any tags and uses the LEB128 variable-length integer format for all numbers it emits. The space savings are nice, albeit a bit underwhelming, especially for dynamic libraries where metadata is already compressed. | RLIBs | NEW | OLD | |--------------|--------|-----------| |libstd | 8.8 MB | 10.5 MB | |libcore |15.6 MB | 19.7 MB | |libcollections| 3.7 MB | 4.8 MB | |librustc |34.0 MB | 37.8 MB | |libsyntax |28.3 MB | 32.1 MB | | SOs | NEW | OLD | |---------------|-----------|--------| | libstd | 4.8 MB | 5.1 MB | | librustc | 8.6 MB | 9.2 MB | | libsyntax | 7.8 MB | 8.4 MB | At least this should make up for the size increase caused recently by also storing MIR in crate metadata. Can this be a breaking change for anyone? cc @rust-lang/compiler
This commit is contained in:
commit
23d24ff667
|
@ -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))]
|
#![cfg_attr(test, feature(test))]
|
||||||
|
|
||||||
extern crate serialize;
|
extern crate serialize;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
extern crate serialize as rustc_serialize; // Used by RustcEncodable
|
||||||
|
|
||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
|
|
||||||
#[cfg(test)] extern crate test;
|
#[cfg(test)] extern crate test;
|
||||||
|
|
||||||
|
pub mod opaque;
|
||||||
|
pub mod leb128;
|
||||||
|
|
||||||
pub use self::EbmlEncoderTag::*;
|
pub use self::EbmlEncoderTag::*;
|
||||||
pub use self::Error::*;
|
pub use self::Error::*;
|
||||||
|
|
||||||
|
@ -241,6 +248,7 @@ pub mod reader {
|
||||||
|
|
||||||
use serialize;
|
use serialize;
|
||||||
|
|
||||||
|
use super::opaque;
|
||||||
use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsSub8, EsSub32,
|
use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsSub8, EsSub32,
|
||||||
EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsI64,
|
EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsI64,
|
||||||
EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
|
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
|
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 doc = try!(self.next_doc(EsOpaque));
|
||||||
|
|
||||||
let (old_parent, old_pos) = (self.parent, self.pos);
|
let result = {
|
||||||
self.parent = doc;
|
let mut opaque_decoder = opaque::Decoder::new(doc.data,
|
||||||
self.pos = doc.start;
|
doc.start);
|
||||||
|
try!(op(&mut opaque_decoder, doc))
|
||||||
|
};
|
||||||
|
|
||||||
let result = try!(op(self, doc));
|
|
||||||
|
|
||||||
self.parent = old_parent;
|
|
||||||
self.pos = old_pos;
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -877,6 +883,7 @@ pub mod writer {
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io::{self, SeekFrom, Cursor};
|
use std::io::{self, SeekFrom, Cursor};
|
||||||
|
|
||||||
|
use super::opaque;
|
||||||
use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey,
|
use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey,
|
||||||
EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8,
|
EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8,
|
||||||
EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
|
EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
|
||||||
|
@ -1120,10 +1127,16 @@ pub mod writer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_opaque<F>(&mut self, f: F) -> EncodeResult where
|
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!(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()
|
self.end_tag()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
/// Note, however, that this only works for RBML-based encoding and decoding at
|
||||||
/// the moment.
|
/// the moment.
|
||||||
pub mod tls {
|
pub mod tls {
|
||||||
use rbml::writer::Encoder as RbmlEncoder;
|
use rbml::opaque::Encoder as OpaqueEncoder;
|
||||||
use rbml::reader::Decoder as RbmlDecoder;
|
use rbml::opaque::Decoder as OpaqueDecoder;
|
||||||
use serialize;
|
use serialize;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use middle::ty::{self, Ty};
|
use middle::ty::{self, Ty};
|
||||||
|
@ -442,8 +442,8 @@ pub mod tls {
|
||||||
|
|
||||||
pub trait EncodingContext<'tcx> {
|
pub trait EncodingContext<'tcx> {
|
||||||
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
|
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
|
||||||
fn encode_ty(&self, rbml_w: &mut RbmlEncoder, t: Ty<'tcx>);
|
fn encode_ty(&self, encoder: &mut OpaqueEncoder, t: Ty<'tcx>);
|
||||||
fn encode_substs(&self, rbml_w: &mut RbmlEncoder, substs: &Substs<'tcx>);
|
fn encode_substs(&self, encoder: &mut OpaqueEncoder, substs: &Substs<'tcx>);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Marker type used for the scoped TLS slot.
|
/// 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.
|
/// Execute f after pushing the given EncodingContext onto the TLS stack.
|
||||||
pub fn enter_encoding_context<'tcx, F, R>(ecx: &EncodingContext<'tcx>,
|
pub fn enter_encoding_context<'tcx, F, R>(ecx: &EncodingContext<'tcx>,
|
||||||
rbml_w: &mut RbmlEncoder,
|
encoder: &mut OpaqueEncoder,
|
||||||
f: F) -> R
|
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;
|
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
|
/// 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
|
/// possible to construct cases where the EncodingContext is exchanged
|
||||||
/// while the same encoder is used, thus working with a wrong context.
|
/// 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
|
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
|
E: serialize::Encoder
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
unsafe_with_encoding_context(|ecx, rbml_w| {
|
unsafe_with_encoding_context(|ecx, tls_encoder| {
|
||||||
assert!(encoder as *mut _ as usize == rbml_w as *mut _ as usize);
|
assert!(encoder as *mut _ as usize == tls_encoder as *mut _ as usize);
|
||||||
|
|
||||||
let ecx: &EncodingContext<'tcx> = mem::transmute(ecx);
|
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
|
/// Execute f with access to the thread-local encoding context and
|
||||||
/// rbml encoder.
|
/// rbml encoder.
|
||||||
pub unsafe fn unsafe_with_encoding_context<F, R>(f: F) -> R
|
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| {
|
TLS_ENCODING.with(|tls| {
|
||||||
let tls_payload = (tls as *const TlsPayload)
|
let tls_payload = (tls as *const TlsPayload)
|
||||||
as *mut (&EncodingContext, &mut RbmlEncoder);
|
as *mut (&EncodingContext, &mut OpaqueEncoder);
|
||||||
f((*tls_payload).0, (*tls_payload).1)
|
f((*tls_payload).0, (*tls_payload).1)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DecodingContext<'tcx> {
|
pub trait DecodingContext<'tcx> {
|
||||||
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
|
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
|
||||||
fn decode_ty(&self, rbml_r: &mut RbmlDecoder) -> ty::Ty<'tcx>;
|
fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx>;
|
||||||
fn decode_substs(&self, rbml_r: &mut RbmlDecoder) -> Substs<'tcx>;
|
fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> Substs<'tcx>;
|
||||||
fn translate_def_id(&self, def_id: DefId) -> DefId;
|
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.
|
/// Execute f after pushing the given DecodingContext onto the TLS stack.
|
||||||
pub fn enter_decoding_context<'tcx, F, R>(dcx: &DecodingContext<'tcx>,
|
pub fn enter_decoding_context<'tcx, F, R>(dcx: &DecodingContext<'tcx>,
|
||||||
rbml_r: &mut RbmlDecoder,
|
decoder: &mut OpaqueDecoder,
|
||||||
f: F) -> R
|
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;
|
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
|
/// 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
|
pub fn with_decoding_context<'decoder, 'tcx, D, F, R>(d: &'decoder mut D, f: F) -> R
|
||||||
where D: serialize::Decoder,
|
where D: serialize::Decoder,
|
||||||
F: FnOnce(&DecodingContext<'tcx>,
|
F: FnOnce(&DecodingContext<'tcx>,
|
||||||
&mut RbmlDecoder) -> R,
|
&mut OpaqueDecoder) -> R,
|
||||||
'tcx: 'decoder
|
'tcx: 'decoder
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
unsafe_with_decoding_context(|dcx, rbml_r| {
|
unsafe_with_decoding_context(|dcx, decoder| {
|
||||||
assert!((d as *mut _ as usize) == (rbml_r as *mut _ as usize));
|
assert!((d as *mut _ as usize) == (decoder as *mut _ as usize));
|
||||||
|
|
||||||
let dcx: &DecodingContext<'tcx> = mem::transmute(dcx);
|
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
|
/// Execute f with access to the thread-local decoding context and
|
||||||
/// rbml decoder.
|
/// rbml decoder.
|
||||||
pub unsafe fn unsafe_with_decoding_context<F, R>(f: F) -> R
|
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| {
|
TLS_DECODING.with(|tls| {
|
||||||
let tls_payload = (tls as *const TlsPayload)
|
let tls_payload = (tls as *const TlsPayload)
|
||||||
as *mut (&DecodingContext, &mut RbmlDecoder);
|
as *mut (&DecodingContext, &mut OpaqueDecoder);
|
||||||
f((*tls_payload).0, (*tls_payload).1)
|
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) {
|
fn encode_ast(rbml_w: &mut Encoder, item: &InlinedItem) {
|
||||||
rbml_w.start_tag(c::tag_tree as usize);
|
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();
|
rbml_w.end_tag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,8 +361,8 @@ fn simplify_ast(ii: InlinedItemRef) -> InlinedItem {
|
||||||
|
|
||||||
fn decode_ast(par_doc: rbml::Doc) -> InlinedItem {
|
fn decode_ast(par_doc: rbml::Doc) -> InlinedItem {
|
||||||
let chi_doc = par_doc.get(c::tag_tree as usize);
|
let chi_doc = par_doc.get(c::tag_tree as usize);
|
||||||
let mut d = reader::Decoder::new(chi_doc);
|
let mut rbml_r = reader::Decoder::new(chi_doc);
|
||||||
Decodable::decode(&mut d).unwrap()
|
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
|
// 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> {
|
trait rbml_writer_helpers<'tcx> {
|
||||||
fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region);
|
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>);
|
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> {
|
impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
|
||||||
fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region) {
|
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>) {
|
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>]) {
|
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>,
|
fn emit_trait_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
|
||||||
trait_ref: &ty::TraitRef<'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>,
|
fn emit_predicate<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
|
||||||
predicate: &ty::Predicate<'tcx>) {
|
predicate: &ty::Predicate<'tcx>) {
|
||||||
self.emit_opaque(|this| {
|
self.emit_opaque(|this| {
|
||||||
Ok(tyencode::enc_predicate(this,
|
Ok(tyencode::enc_predicate(&mut this.cursor,
|
||||||
&ecx.ty_str_ctxt(),
|
&ecx.ty_str_ctxt(),
|
||||||
predicate))
|
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>,
|
fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
|
||||||
bounds: &ty::ExistentialBounds<'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(),
|
&ecx.ty_str_ctxt(),
|
||||||
bounds)));
|
bounds)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds) {
|
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(),
|
&ecx.ty_str_ctxt(),
|
||||||
bounds)));
|
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>,
|
fn emit_substs<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
|
||||||
substs: &subst::Substs<'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(),
|
&ecx.ty_str_ctxt(),
|
||||||
substs)));
|
substs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_auto_adjustment<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
|
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>;
|
-> adjustment::AutoDerefRef<'tcx>;
|
||||||
fn read_autoref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
|
fn read_autoref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
|
||||||
-> adjustment::AutoRef<'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
|
// Versions of the type reading functions that don't need the full
|
||||||
// DecodeContext.
|
// 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
|
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
|
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));
|
debug!("read_ty_encoded({})", type_string(doc));
|
||||||
Ok(op(
|
Ok(op(
|
||||||
&mut tydecode::TyDecoder::with_doc(
|
&mut tydecode::TyDecoder::with_doc(
|
||||||
dcx.tcx, dcx.cdata.cnum, doc,
|
dcx.tcx, dcx.cdata.cnum, doc,
|
||||||
&mut |a| this.convert_def_id(dcx, a))))
|
&mut |d| convert_def_id(dcx, d))))
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
|
|
||||||
fn type_string(doc: rbml::Doc) -> String {
|
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>)
|
fn read_substs<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
|
||||||
-> subst::Substs<'tcx> {
|
-> subst::Substs<'tcx> {
|
||||||
self.read_opaque(|this, doc| {
|
self.read_opaque(|_, doc| {
|
||||||
Ok(tydecode::TyDecoder::with_doc(dcx.tcx, dcx.cdata.cnum, 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())
|
.parse_substs())
|
||||||
}).unwrap()
|
}).unwrap()
|
||||||
}
|
}
|
||||||
|
@ -1097,47 +1084,46 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
|
||||||
{
|
{
|
||||||
Decodable::decode(self).unwrap()
|
Decodable::decode(self).unwrap()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Converts a def-id that appears in a type. The correct
|
// Converts a def-id that appears in a type. The correct
|
||||||
/// translation will depend on what kind of def-id this is.
|
// translation will depend on what kind of def-id this is.
|
||||||
/// This is a subtle point: type definitions are not
|
// This is a subtle point: type definitions are not
|
||||||
/// inlined into the current crate, so if the def-id names
|
// inlined into the current crate, so if the def-id names
|
||||||
/// a nominal type or type alias, then it should be
|
// a nominal type or type alias, then it should be
|
||||||
/// translated to refer to the source crate.
|
// translated to refer to the source crate.
|
||||||
///
|
//
|
||||||
/// However, *type parameters* are cloned along with the function
|
// However, *type parameters* are cloned along with the function
|
||||||
/// they are attached to. So we should translate those def-ids
|
// they are attached to. So we should translate those def-ids
|
||||||
/// to refer to the new, cloned copy of the type parameter.
|
// to refer to the new, cloned copy of the type parameter.
|
||||||
/// We only see references to free type parameters in the body of
|
// We only see references to free type parameters in the body of
|
||||||
/// an inlined function. In such cases, we need the def-id to
|
// 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
|
// be a local id so that the TypeContents code is able to lookup
|
||||||
/// the relevant info in the ty_param_defs table.
|
// the relevant info in the ty_param_defs table.
|
||||||
///
|
//
|
||||||
/// *Region parameters*, unfortunately, are another kettle of fish.
|
// *Region parameters*, unfortunately, are another kettle of fish.
|
||||||
/// In such cases, def_id's can appear in types to distinguish
|
// In such cases, def_id's can appear in types to distinguish
|
||||||
/// shadowed bound regions and so forth. It doesn't actually
|
// shadowed bound regions and so forth. It doesn't actually
|
||||||
/// matter so much what we do to these, since regions are erased
|
// 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
|
// at trans time, but it's good to keep them consistent just in
|
||||||
/// case. We translate them with `tr_def_id()` which will map
|
// case. We translate them with `tr_def_id()` which will map
|
||||||
/// the crate numbers back to the original source crate.
|
// the crate numbers back to the original source crate.
|
||||||
///
|
//
|
||||||
/// Scopes will end up as being totally bogus. This can actually
|
// Scopes will end up as being totally bogus. This can actually
|
||||||
/// be fixed though.
|
// be fixed though.
|
||||||
///
|
//
|
||||||
/// Unboxed closures are cloned along with the function being
|
// Unboxed closures are cloned along with the function being
|
||||||
/// inlined, and all side tables use interned node IDs, so we
|
// inlined, and all side tables use interned node IDs, so we
|
||||||
/// translate their def IDs accordingly.
|
// translate their def IDs accordingly.
|
||||||
///
|
//
|
||||||
/// It'd be really nice to refactor the type repr to not include
|
// It'd be really nice to refactor the type repr to not include
|
||||||
/// def-ids so that all these distinctions were unnecessary.
|
// def-ids so that all these distinctions were unnecessary.
|
||||||
fn convert_def_id(&mut self,
|
fn convert_def_id(dcx: &DecodeContext,
|
||||||
dcx: &DecodeContext,
|
did: DefId)
|
||||||
did: DefId)
|
-> DefId {
|
||||||
-> DefId {
|
let r = dcx.tr_def_id(did);
|
||||||
let r = dcx.tr_def_id(did);
|
debug!("convert_def_id(did={:?})={:?}", did, r);
|
||||||
debug!("convert_def_id(did={:?})={:?}", did, r);
|
return r;
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_side_tables(dcx: &DecodeContext,
|
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 decoder = reader::Decoder::new(mir_doc);
|
||||||
|
|
||||||
let mut mir = tls::enter_decoding_context(&dcx, &mut decoder, |_, decoder| {
|
let mut mir = decoder.read_opaque(|opaque_decoder, _| {
|
||||||
Decodable::decode(decoder).unwrap()
|
tls::enter_decoding_context(&dcx, opaque_decoder, |_, opaque_decoder| {
|
||||||
});
|
Decodable::decode(opaque_decoder)
|
||||||
|
})
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
let mut def_id_and_span_translator = MirDefIdAndSpanTranslator {
|
let mut def_id_and_span_translator = MirDefIdAndSpanTranslator {
|
||||||
crate_metadata: cdata,
|
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| {
|
reader::tagged_docs(cm_doc, tag_codemap_filemap).map(|filemap_doc| {
|
||||||
let mut decoder = reader::Decoder::new(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()
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,15 +140,9 @@ fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder,
|
||||||
ecx: &EncodeContext<'a, 'tcx>,
|
ecx: &EncodeContext<'a, 'tcx>,
|
||||||
trait_ref: ty::TraitRef<'tcx>,
|
trait_ref: ty::TraitRef<'tcx>,
|
||||||
tag: usize) {
|
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);
|
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();
|
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);
|
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,
|
rbml_w: &mut Encoder,
|
||||||
typ: Ty<'tcx>) {
|
closure_type: &ty::ClosureTy<'tcx>) {
|
||||||
let ty_str_ctxt = &tyencode::ctxt {
|
tyencode::enc_closure_ty(rbml_w.writer, &ecx.ty_str_ctxt(), closure_type);
|
||||||
diag: ecx.diag,
|
rbml_w.mark_stable_position();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
fn encode_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
rbml_w: &mut Encoder,
|
rbml_w: &mut Encoder,
|
||||||
typ: Ty<'tcx>) {
|
typ: Ty<'tcx>) {
|
||||||
rbml_w.start_tag(tag_items_data_item_type);
|
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();
|
rbml_w.end_tag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +216,8 @@ fn encode_region(ecx: &EncodeContext,
|
||||||
rbml_w: &mut Encoder,
|
rbml_w: &mut Encoder,
|
||||||
r: ty::Region) {
|
r: ty::Region) {
|
||||||
rbml_w.start_tag(tag_items_data_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();
|
rbml_w.end_tag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -592,17 +547,10 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
|
||||||
{
|
{
|
||||||
rbml_w.start_tag(tag);
|
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 {
|
for param in &generics.types {
|
||||||
rbml_w.start_tag(tag_type_param_def);
|
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();
|
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) {
|
if let Some(mir) = ecx.mir_map.get(&id) {
|
||||||
rbml_w.start_tag(tag_mir as usize);
|
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();
|
rbml_w.end_tag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -916,23 +868,17 @@ fn encode_xrefs<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
rbml_w: &mut Encoder,
|
rbml_w: &mut Encoder,
|
||||||
xrefs: FnvHashMap<XRef<'tcx>, u32>)
|
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()];
|
let mut xref_positions = vec![0; xrefs.len()];
|
||||||
rbml_w.start_tag(tag_xref_data);
|
rbml_w.start_tag(tag_xref_data);
|
||||||
for (xref, id) in xrefs.into_iter() {
|
for (xref, id) in xrefs.into_iter() {
|
||||||
xref_positions[id as usize] = rbml_w.mark_stable_position() as u32;
|
xref_positions[id as usize] = rbml_w.mark_stable_position() as u32;
|
||||||
match xref {
|
match xref {
|
||||||
XRef::Predicate(p) => {
|
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.end_tag();
|
||||||
|
|
||||||
rbml_w.start_tag(tag_xref_index);
|
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);
|
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();
|
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);
|
let mut rbml_w = Encoder::new(&mut wr);
|
||||||
tls::enter_encoding_context(&ecx, &mut rbml_w, |_, rbml_w| {
|
encode_metadata_inner(&mut rbml_w, &ecx, krate)
|
||||||
encode_metadata_inner(rbml_w, &ecx, krate)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RBML compacts the encoded bytes whenever appropriate,
|
// 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
|
// Get the encoded string for a type
|
||||||
pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Vec<u8> {
|
pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Vec<u8> {
|
||||||
let mut wr = Cursor::new(Vec::new());
|
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(),
|
diag: tcx.sess.diagnostic(),
|
||||||
ds: def_to_string,
|
ds: def_to_string,
|
||||||
tcx: tcx,
|
tcx: tcx,
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
// This module provides implementations for the thread-local encoding and
|
// This module provides implementations for the thread-local encoding and
|
||||||
// decoding context traits in rustc::middle::cstore::tls.
|
// decoding context traits in rustc::middle::cstore::tls.
|
||||||
|
|
||||||
use rbml::writer::Encoder as RbmlEncoder;
|
use rbml::opaque::Encoder as OpaqueEncoder;
|
||||||
use rbml::reader::Decoder as RbmlDecoder;
|
use rbml::opaque::Decoder as OpaqueDecoder;
|
||||||
use rustc::middle::cstore::tls;
|
use rustc::middle::cstore::tls;
|
||||||
use rustc::middle::def_id::DefId;
|
use rustc::middle::def_id::DefId;
|
||||||
use rustc::middle::subst::Substs;
|
use rustc::middle::subst::Substs;
|
||||||
|
@ -23,25 +23,18 @@ use encoder;
|
||||||
use tydecode::TyDecoder;
|
use tydecode::TyDecoder;
|
||||||
use tyencode;
|
use tyencode;
|
||||||
|
|
||||||
|
|
||||||
impl<'a, 'tcx: 'a> tls::EncodingContext<'tcx> for encoder::EncodeContext<'a, 'tcx> {
|
impl<'a, 'tcx: 'a> tls::EncodingContext<'tcx> for encoder::EncodeContext<'a, 'tcx> {
|
||||||
|
|
||||||
fn tcx<'s>(&'s self) -> &'s ty::ctxt<'tcx> {
|
fn tcx<'s>(&'s self) -> &'s ty::ctxt<'tcx> {
|
||||||
&self.tcx
|
&self.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_ty(&self, rbml_w: &mut RbmlEncoder, t: ty::Ty<'tcx>) {
|
fn encode_ty(&self, encoder: &mut OpaqueEncoder, t: ty::Ty<'tcx>) {
|
||||||
encoder::write_type(self, rbml_w, t);
|
tyencode::enc_ty(encoder.cursor, &self.ty_str_ctxt(), t);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_substs(&self, rbml_w: &mut RbmlEncoder, substs: &Substs<'tcx>) {
|
fn encode_substs(&self, encoder: &mut OpaqueEncoder, substs: &Substs<'tcx>) {
|
||||||
let ty_str_ctxt = &tyencode::ctxt {
|
tyencode::enc_substs(encoder.cursor, &self.ty_str_ctxt(), substs);
|
||||||
diag: self.diag,
|
|
||||||
ds: encoder::def_to_string,
|
|
||||||
tcx: self.tcx,
|
|
||||||
abbrevs: &self.type_abbrevs
|
|
||||||
};
|
|
||||||
tyencode::enc_substs(rbml_w, ty_str_ctxt, substs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,12 +49,12 @@ impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> {
|
||||||
&self.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| {
|
let def_id_convert = &mut |did| {
|
||||||
decoder::translate_def_id(self.crate_metadata, 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(
|
let mut ty_decoder = TyDecoder::new(
|
||||||
self.crate_metadata.data.as_slice(),
|
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 can just reuse the tydecode implementation for parsing types, but
|
||||||
// we have to make sure to leave the rbml reader at the position just
|
// we have to make sure to leave the rbml reader at the position just
|
||||||
// after the type.
|
// after the type.
|
||||||
rbml_r.advance(end_position - starting_position);
|
decoder.advance(end_position - starting_position);
|
||||||
ty
|
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| {
|
let def_id_convert = &mut |did| {
|
||||||
decoder::translate_def_id(self.crate_metadata, 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(
|
let mut ty_decoder = TyDecoder::new(
|
||||||
self.crate_metadata.data.as_slice(),
|
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();
|
let end_position = ty_decoder.position();
|
||||||
|
|
||||||
rbml_r.advance(end_position - starting_position);
|
decoder.advance(end_position - starting_position);
|
||||||
substs
|
substs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ use middle::subst::VecPerParamSpace;
|
||||||
use middle::ty::{self, ToPredicate, Ty, HasTypeFlags};
|
use middle::ty::{self, ToPredicate, Ty, HasTypeFlags};
|
||||||
|
|
||||||
use rbml;
|
use rbml;
|
||||||
|
use rbml::leb128;
|
||||||
use std::str;
|
use std::str;
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
@ -103,9 +104,10 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_vuint(&mut self) -> usize {
|
fn parse_vuint(&mut self) -> usize {
|
||||||
let res = rbml::reader::vuint_at(self.data, self.pos).unwrap();
|
let (value, bytes_read) = leb128::read_unsigned_leb128(self.data,
|
||||||
self.pos = res.next;
|
self.pos);
|
||||||
res.val
|
self.pos += bytes_read;
|
||||||
|
value as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_name(&mut self, last: char) -> ast::Name {
|
fn parse_name(&mut self, last: char) -> ast::Name {
|
||||||
|
|
|
@ -31,9 +31,8 @@ use syntax::abi::Abi;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::errors::Handler;
|
use syntax::errors::Handler;
|
||||||
|
|
||||||
use rbml::writer::{self, Encoder};
|
use rbml::leb128;
|
||||||
|
use encoder;
|
||||||
macro_rules! mywrite { ($w:expr, $($arg:tt)*) => ({ write!($w.writer, $($arg)*); }) }
|
|
||||||
|
|
||||||
pub struct ctxt<'a, 'tcx: 'a> {
|
pub struct ctxt<'a, 'tcx: 'a> {
|
||||||
pub diag: &'a Handler,
|
pub diag: &'a Handler,
|
||||||
|
@ -44,6 +43,17 @@ pub struct ctxt<'a, 'tcx: 'a> {
|
||||||
pub abbrevs: &'a abbrev_map<'tcx>
|
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.
|
// Compact string representation for Ty values. API TyStr & parse_from_str.
|
||||||
// Extra parameters are for converting to/from def_ids in the string rep.
|
// Extra parameters are for converting to/from def_ids in the string rep.
|
||||||
// Whatever format you choose should not contain pipe characters.
|
// 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 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) {
|
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 => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// type abbreviations needs a stable position
|
let pos = w.position();
|
||||||
let pos = w.mark_stable_position();
|
|
||||||
|
|
||||||
match t.sty {
|
match t.sty {
|
||||||
ty::TyBool => mywrite!(w, "b"),
|
ty::TyBool => { write!(w, "b"); }
|
||||||
ty::TyChar => mywrite!(w, "c"),
|
ty::TyChar => { write!(w, "c"); }
|
||||||
ty::TyInt(t) => {
|
ty::TyInt(t) => {
|
||||||
match t {
|
match t {
|
||||||
ast::TyIs => mywrite!(w, "is"),
|
ast::TyIs => write!(w, "is"),
|
||||||
ast::TyI8 => mywrite!(w, "MB"),
|
ast::TyI8 => write!(w, "MB"),
|
||||||
ast::TyI16 => mywrite!(w, "MW"),
|
ast::TyI16 => write!(w, "MW"),
|
||||||
ast::TyI32 => mywrite!(w, "ML"),
|
ast::TyI32 => write!(w, "ML"),
|
||||||
ast::TyI64 => mywrite!(w, "MD")
|
ast::TyI64 => write!(w, "MD")
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
ty::TyUint(t) => {
|
ty::TyUint(t) => {
|
||||||
match t {
|
match t {
|
||||||
ast::TyUs => mywrite!(w, "us"),
|
ast::TyUs => write!(w, "us"),
|
||||||
ast::TyU8 => mywrite!(w, "Mb"),
|
ast::TyU8 => write!(w, "Mb"),
|
||||||
ast::TyU16 => mywrite!(w, "Mw"),
|
ast::TyU16 => write!(w, "Mw"),
|
||||||
ast::TyU32 => mywrite!(w, "Ml"),
|
ast::TyU32 => write!(w, "Ml"),
|
||||||
ast::TyU64 => mywrite!(w, "Md")
|
ast::TyU64 => write!(w, "Md")
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
ty::TyFloat(t) => {
|
ty::TyFloat(t) => {
|
||||||
match t {
|
match t {
|
||||||
ast::TyF32 => mywrite!(w, "Mf"),
|
ast::TyF32 => write!(w, "Mf"),
|
||||||
ast::TyF64 => mywrite!(w, "MF"),
|
ast::TyF64 => write!(w, "MF"),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
ty::TyEnum(def, substs) => {
|
ty::TyEnum(def, substs) => {
|
||||||
mywrite!(w, "t[{}|", (cx.ds)(def.did));
|
write!(w, "t[{}|", (cx.ds)(def.did));
|
||||||
enc_substs(w, cx, substs);
|
enc_substs(w, cx, substs);
|
||||||
mywrite!(w, "]");
|
write!(w, "]");
|
||||||
}
|
}
|
||||||
ty::TyTrait(box ty::TraitTy { ref principal,
|
ty::TyTrait(box ty::TraitTy { ref principal,
|
||||||
ref bounds }) => {
|
ref bounds }) => {
|
||||||
mywrite!(w, "x[");
|
write!(w, "x[");
|
||||||
enc_trait_ref(w, cx, principal.0);
|
enc_trait_ref(w, cx, principal.0);
|
||||||
enc_existential_bounds(w, cx, bounds);
|
enc_existential_bounds(w, cx, bounds);
|
||||||
mywrite!(w, "]");
|
write!(w, "]");
|
||||||
}
|
}
|
||||||
ty::TyTuple(ref ts) => {
|
ty::TyTuple(ref ts) => {
|
||||||
mywrite!(w, "T[");
|
write!(w, "T[");
|
||||||
for t in ts { enc_ty(w, cx, *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::TyBox(typ) => { write!(w, "~"); enc_ty(w, cx, typ); }
|
||||||
ty::TyRawPtr(mt) => { mywrite!(w, "*"); enc_mt(w, cx, mt); }
|
ty::TyRawPtr(mt) => { write!(w, "*"); enc_mt(w, cx, mt); }
|
||||||
ty::TyRef(r, mt) => {
|
ty::TyRef(r, mt) => {
|
||||||
mywrite!(w, "&");
|
write!(w, "&");
|
||||||
enc_region(w, cx, *r);
|
enc_region(w, cx, *r);
|
||||||
enc_mt(w, cx, mt);
|
enc_mt(w, cx, mt);
|
||||||
}
|
}
|
||||||
ty::TyArray(t, sz) => {
|
ty::TyArray(t, sz) => {
|
||||||
mywrite!(w, "V");
|
write!(w, "V");
|
||||||
enc_ty(w, cx, t);
|
enc_ty(w, cx, t);
|
||||||
mywrite!(w, "/{}|", sz);
|
write!(w, "/{}|", sz);
|
||||||
}
|
}
|
||||||
ty::TySlice(t) => {
|
ty::TySlice(t) => {
|
||||||
mywrite!(w, "V");
|
write!(w, "V");
|
||||||
enc_ty(w, cx, t);
|
enc_ty(w, cx, t);
|
||||||
mywrite!(w, "/|");
|
write!(w, "/|");
|
||||||
}
|
}
|
||||||
ty::TyStr => {
|
ty::TyStr => {
|
||||||
mywrite!(w, "v");
|
write!(w, "v");
|
||||||
}
|
}
|
||||||
ty::TyBareFn(Some(def_id), f) => {
|
ty::TyBareFn(Some(def_id), f) => {
|
||||||
mywrite!(w, "F");
|
write!(w, "F");
|
||||||
mywrite!(w, "{}|", (cx.ds)(def_id));
|
write!(w, "{}|", (cx.ds)(def_id));
|
||||||
enc_bare_fn_ty(w, cx, f);
|
enc_bare_fn_ty(w, cx, f);
|
||||||
}
|
}
|
||||||
ty::TyBareFn(None, f) => {
|
ty::TyBareFn(None, f) => {
|
||||||
mywrite!(w, "G");
|
write!(w, "G");
|
||||||
enc_bare_fn_ty(w, cx, f);
|
enc_bare_fn_ty(w, cx, f);
|
||||||
}
|
}
|
||||||
ty::TyInfer(_) => {
|
ty::TyInfer(_) => {
|
||||||
cx.diag.bug("cannot encode inference variable types");
|
cx.diag.bug("cannot encode inference variable types");
|
||||||
}
|
}
|
||||||
ty::TyParam(ParamTy {space, idx, name}) => {
|
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) => {
|
ty::TyStruct(def, substs) => {
|
||||||
mywrite!(w, "a[{}|", (cx.ds)(def.did));
|
write!(w, "a[{}|", (cx.ds)(def.did));
|
||||||
enc_substs(w, cx, substs);
|
enc_substs(w, cx, substs);
|
||||||
mywrite!(w, "]");
|
write!(w, "]");
|
||||||
}
|
}
|
||||||
ty::TyClosure(def, ref substs) => {
|
ty::TyClosure(def, ref substs) => {
|
||||||
mywrite!(w, "k[{}|", (cx.ds)(def));
|
write!(w, "k[{}|", (cx.ds)(def));
|
||||||
enc_substs(w, cx, &substs.func_substs);
|
enc_substs(w, cx, &substs.func_substs);
|
||||||
for ty in &substs.upvar_tys {
|
for ty in &substs.upvar_tys {
|
||||||
enc_ty(w, cx, ty);
|
enc_ty(w, cx, ty);
|
||||||
}
|
}
|
||||||
mywrite!(w, ".");
|
write!(w, ".");
|
||||||
mywrite!(w, "]");
|
write!(w, "]");
|
||||||
}
|
}
|
||||||
ty::TyProjection(ref data) => {
|
ty::TyProjection(ref data) => {
|
||||||
mywrite!(w, "P[");
|
write!(w, "P[");
|
||||||
enc_trait_ref(w, cx, data.trait_ref);
|
enc_trait_ref(w, cx, data.trait_ref);
|
||||||
mywrite!(w, "{}]", data.item_name);
|
write!(w, "{}]", data.item_name);
|
||||||
}
|
}
|
||||||
ty::TyError => {
|
ty::TyError => {
|
||||||
mywrite!(w, "e");
|
write!(w, "e");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let end = w.mark_stable_position();
|
let end = w.position();
|
||||||
let len = end - pos;
|
let len = end - pos;
|
||||||
|
|
||||||
let buf: &mut [u8] = &mut [0; 16]; // vuint < 15 bytes
|
let mut abbrev = Cursor::new(Vec::with_capacity(16));
|
||||||
let mut abbrev = Cursor::new(buf);
|
|
||||||
abbrev.write_all(b"#");
|
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 {
|
cx.abbrevs.borrow_mut().insert(t, ty_abbrev {
|
||||||
s: if abbrev.position() < len {
|
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,
|
// if the abbreviation is longer than the real type,
|
||||||
// don't use #-notation. However, insert it here so
|
// don't use #-notation. However, insert it here so
|
||||||
// other won't have to `mark_stable_position`
|
// 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 {
|
match mt {
|
||||||
hir::MutImmutable => (),
|
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>) {
|
mt: ty::TypeAndMut<'tcx>) {
|
||||||
enc_mutability(w, mt.mutbl);
|
enc_mutability(w, mt.mutbl);
|
||||||
enc_ty(w, cx, mt.ty);
|
enc_ty(w, cx, mt.ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enc_opt<T, F>(w: &mut Encoder, t: Option<T>, enc_f: F) where
|
fn enc_opt<T, F>(w: &mut Cursor<Vec<u8>>, t: Option<T>, enc_f: F) where
|
||||||
F: FnOnce(&mut Encoder, T),
|
F: FnOnce(&mut Cursor<Vec<u8>>, T),
|
||||||
{
|
{
|
||||||
match t {
|
match t {
|
||||||
None => mywrite!(w, "n"),
|
None => {
|
||||||
|
write!(w, "n");
|
||||||
|
}
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
mywrite!(w, "s");
|
write!(w, "s");
|
||||||
enc_f(w, v);
|
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>,
|
cx: &ctxt<'a, 'tcx>,
|
||||||
v: &VecPerParamSpace<T>,
|
v: &VecPerParamSpace<T>,
|
||||||
mut op: F) where
|
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() {
|
for &space in &subst::ParamSpace::all() {
|
||||||
mywrite!(w, "[");
|
write!(w, "[");
|
||||||
for t in v.get_slice(space) {
|
for t in v.get_slice(space) {
|
||||||
op(w, cx, t);
|
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>) {
|
substs: &subst::Substs<'tcx>) {
|
||||||
enc_region_substs(w, cx, &substs.regions);
|
enc_region_substs(w, cx, &substs.regions);
|
||||||
enc_vec_per_param_space(w, cx, &substs.types,
|
enc_vec_per_param_space(w, cx, &substs.types,
|
||||||
|w, cx, &ty| enc_ty(w, cx, ty));
|
|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 {
|
match *substs {
|
||||||
subst::ErasedRegions => {
|
subst::ErasedRegions => {
|
||||||
mywrite!(w, "e");
|
write!(w, "e");
|
||||||
}
|
}
|
||||||
subst::NonerasedRegions(ref regions) => {
|
subst::NonerasedRegions(ref regions) => {
|
||||||
mywrite!(w, "n");
|
write!(w, "n");
|
||||||
enc_vec_per_param_space(w, cx, regions,
|
enc_vec_per_param_space(w, cx, regions,
|
||||||
|w, cx, &r| enc_region(w, cx, r));
|
|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 {
|
match r {
|
||||||
ty::ReLateBound(id, br) => {
|
ty::ReLateBound(id, br) => {
|
||||||
mywrite!(w, "b[{}|", id.depth);
|
write!(w, "b[{}|", id.depth);
|
||||||
enc_bound_region(w, cx, br);
|
enc_bound_region(w, cx, br);
|
||||||
mywrite!(w, "]");
|
write!(w, "]");
|
||||||
}
|
}
|
||||||
ty::ReEarlyBound(ref data) => {
|
ty::ReEarlyBound(ref data) => {
|
||||||
mywrite!(w, "B[{}|{}|{}]",
|
write!(w, "B[{}|{}|{}]",
|
||||||
data.space.to_uint(),
|
data.space.to_uint(),
|
||||||
data.index,
|
data.index,
|
||||||
data.name);
|
data.name);
|
||||||
}
|
}
|
||||||
ty::ReFree(ref fr) => {
|
ty::ReFree(ref fr) => {
|
||||||
mywrite!(w, "f[");
|
write!(w, "f[");
|
||||||
enc_scope(w, cx, fr.scope);
|
enc_scope(w, cx, fr.scope);
|
||||||
mywrite!(w, "|");
|
write!(w, "|");
|
||||||
enc_bound_region(w, cx, fr.bound_region);
|
enc_bound_region(w, cx, fr.bound_region);
|
||||||
mywrite!(w, "]");
|
write!(w, "]");
|
||||||
}
|
}
|
||||||
ty::ReScope(scope) => {
|
ty::ReScope(scope) => {
|
||||||
mywrite!(w, "s");
|
write!(w, "s");
|
||||||
enc_scope(w, cx, scope);
|
enc_scope(w, cx, scope);
|
||||||
mywrite!(w, "|");
|
write!(w, "|");
|
||||||
}
|
}
|
||||||
ty::ReStatic => {
|
ty::ReStatic => {
|
||||||
mywrite!(w, "t");
|
write!(w, "t");
|
||||||
}
|
}
|
||||||
ty::ReEmpty => {
|
ty::ReEmpty => {
|
||||||
mywrite!(w, "e");
|
write!(w, "e");
|
||||||
}
|
}
|
||||||
ty::ReVar(_) | ty::ReSkolemized(..) => {
|
ty::ReVar(_) | ty::ReSkolemized(..) => {
|
||||||
// these should not crop up after typeck
|
// 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) {
|
match cx.tcx.region_maps.code_extent_data(scope) {
|
||||||
region::CodeExtentData::CallSiteScope {
|
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 {
|
region::CodeExtentData::ParameterScope {
|
||||||
fn_id, body_id } => mywrite!(w, "P[{}|{}]", fn_id, body_id),
|
fn_id, body_id } => write!(w, "P[{}|{}]", fn_id, body_id),
|
||||||
region::CodeExtentData::Misc(node_id) => mywrite!(w, "M{}", node_id),
|
region::CodeExtentData::Misc(node_id) => write!(w, "M{}", node_id),
|
||||||
region::CodeExtentData::Remainder(region::BlockRemainder {
|
region::CodeExtentData::Remainder(region::BlockRemainder {
|
||||||
block: b, first_statement_index: i }) => mywrite!(w, "B[{}|{}]", b, i),
|
block: b, first_statement_index: i }) => write!(w, "B[{}|{}]", b, i),
|
||||||
region::CodeExtentData::DestructionScope(node_id) => mywrite!(w, "D{}", node_id),
|
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 {
|
match br {
|
||||||
ty::BrAnon(idx) => {
|
ty::BrAnon(idx) => {
|
||||||
mywrite!(w, "a{}|", idx);
|
write!(w, "a{}|", idx);
|
||||||
}
|
}
|
||||||
ty::BrNamed(d, name) => {
|
ty::BrNamed(d, name) => {
|
||||||
mywrite!(w, "[{}|{}]",
|
write!(w, "[{}|{}]",
|
||||||
(cx.ds)(d),
|
(cx.ds)(d),
|
||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
ty::BrFresh(id) => {
|
ty::BrFresh(id) => {
|
||||||
mywrite!(w, "f{}|", id);
|
write!(w, "f{}|", id);
|
||||||
}
|
}
|
||||||
ty::BrEnv => {
|
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>) {
|
s: ty::TraitRef<'tcx>) {
|
||||||
mywrite!(w, "{}|", (cx.ds)(s.def_id));
|
write!(w, "{}|", (cx.ds)(s.def_id));
|
||||||
enc_substs(w, cx, s.substs);
|
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 {
|
match p {
|
||||||
hir::Unsafety::Normal => mywrite!(w, "n"),
|
hir::Unsafety::Normal => write!(w, "n"),
|
||||||
hir::Unsafety::Unsafe => mywrite!(w, "u"),
|
hir::Unsafety::Unsafe => write!(w, "u"),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enc_abi(w: &mut Encoder, abi: Abi) {
|
fn enc_abi(w: &mut Cursor<Vec<u8>>, abi: Abi) {
|
||||||
mywrite!(w, "[");
|
write!(w, "[");
|
||||||
mywrite!(w, "{}", abi.name());
|
write!(w, "{}", abi.name());
|
||||||
mywrite!(w, "]")
|
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>) {
|
ft: &ty::BareFnTy<'tcx>) {
|
||||||
enc_unsafety(w, ft.unsafety);
|
enc_unsafety(w, ft.unsafety);
|
||||||
enc_abi(w, ft.abi);
|
enc_abi(w, ft.abi);
|
||||||
enc_fn_sig(w, cx, &ft.sig);
|
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>) {
|
ft: &ty::ClosureTy<'tcx>) {
|
||||||
enc_unsafety(w, ft.unsafety);
|
enc_unsafety(w, ft.unsafety);
|
||||||
enc_fn_sig(w, cx, &ft.sig);
|
enc_fn_sig(w, cx, &ft.sig);
|
||||||
enc_abi(w, ft.abi);
|
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>) {
|
fsig: &ty::PolyFnSig<'tcx>) {
|
||||||
mywrite!(w, "[");
|
write!(w, "[");
|
||||||
for ty in &fsig.0.inputs {
|
for ty in &fsig.0.inputs {
|
||||||
enc_ty(w, cx, *ty);
|
enc_ty(w, cx, *ty);
|
||||||
}
|
}
|
||||||
mywrite!(w, "]");
|
write!(w, "]");
|
||||||
if fsig.0.variadic {
|
if fsig.0.variadic {
|
||||||
mywrite!(w, "V");
|
write!(w, "V");
|
||||||
} else {
|
} else {
|
||||||
mywrite!(w, "N");
|
write!(w, "N");
|
||||||
}
|
}
|
||||||
match fsig.0.output {
|
match fsig.0.output {
|
||||||
ty::FnConverging(result_type) => {
|
ty::FnConverging(result_type) => {
|
||||||
enc_ty(w, cx, result_type);
|
enc_ty(w, cx, result_type);
|
||||||
}
|
}
|
||||||
ty::FnDiverging => {
|
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 {
|
for bound in bs {
|
||||||
match bound {
|
match bound {
|
||||||
ty::BoundSend => mywrite!(w, "S"),
|
ty::BoundSend => write!(w, "S"),
|
||||||
ty::BoundSized => mywrite!(w, "Z"),
|
ty::BoundSized => write!(w, "Z"),
|
||||||
ty::BoundCopy => mywrite!(w, "P"),
|
ty::BoundCopy => write!(w, "P"),
|
||||||
ty::BoundSync => mywrite!(w, "T"),
|
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>,
|
cx: &ctxt<'a,'tcx>,
|
||||||
bs: &ty::ExistentialBounds<'tcx>) {
|
bs: &ty::ExistentialBounds<'tcx>) {
|
||||||
enc_builtin_bounds(w, cx, &bs.builtin_bounds);
|
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);
|
enc_region(w, cx, bs.region_bound);
|
||||||
|
|
||||||
for tp in &bs.projection_bounds {
|
for tp in &bs.projection_bounds {
|
||||||
mywrite!(w, "P");
|
write!(w, "P");
|
||||||
enc_projection_predicate(w, cx, &tp.0);
|
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>) {
|
v: &ty::TypeParameterDef<'tcx>) {
|
||||||
mywrite!(w, "{}:{}|{}|{}|{}|",
|
write!(w, "{}:{}|{}|{}|{}|",
|
||||||
v.name, (cx.ds)(v.def_id),
|
v.name, (cx.ds)(v.def_id),
|
||||||
v.space.to_uint(), v.index, (cx.ds)(v.default_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_opt(w, v.default, |w, t| enc_ty(w, cx, t));
|
||||||
enc_object_lifetime_default(w, cx, v.object_lifetime_default);
|
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) {
|
v: &ty::RegionParameterDef) {
|
||||||
mywrite!(w, "{}:{}|{}|{}|",
|
write!(w, "{}:{}|{}|{}|",
|
||||||
v.name, (cx.ds)(v.def_id),
|
v.name, (cx.ds)(v.def_id),
|
||||||
v.space.to_uint(), v.index);
|
v.space.to_uint(), v.index);
|
||||||
for &r in &v.bounds {
|
for &r in &v.bounds {
|
||||||
mywrite!(w, "R");
|
write!(w, "R");
|
||||||
enc_region(w, cx, 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>,
|
cx: &ctxt<'a, 'tcx>,
|
||||||
default: ty::ObjectLifetimeDefault)
|
default: ty::ObjectLifetimeDefault)
|
||||||
{
|
{
|
||||||
match default {
|
match default {
|
||||||
ty::ObjectLifetimeDefault::Ambiguous => mywrite!(w, "a"),
|
ty::ObjectLifetimeDefault::Ambiguous => {
|
||||||
ty::ObjectLifetimeDefault::BaseDefault => mywrite!(w, "b"),
|
write!(w, "a");
|
||||||
|
}
|
||||||
|
ty::ObjectLifetimeDefault::BaseDefault => {
|
||||||
|
write!(w, "b");
|
||||||
|
}
|
||||||
ty::ObjectLifetimeDefault::Specific(r) => {
|
ty::ObjectLifetimeDefault::Specific(r) => {
|
||||||
mywrite!(w, "s");
|
write!(w, "s");
|
||||||
enc_region(w, cx, r);
|
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>,
|
cx: &ctxt<'a, 'tcx>,
|
||||||
p: &ty::Predicate<'tcx>)
|
p: &ty::Predicate<'tcx>)
|
||||||
{
|
{
|
||||||
match *p {
|
match *p {
|
||||||
ty::Predicate::Trait(ref trait_ref) => {
|
ty::Predicate::Trait(ref trait_ref) => {
|
||||||
mywrite!(w, "t");
|
write!(w, "t");
|
||||||
enc_trait_ref(w, cx, trait_ref.0.trait_ref);
|
enc_trait_ref(w, cx, trait_ref.0.trait_ref);
|
||||||
}
|
}
|
||||||
ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => {
|
ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => {
|
||||||
mywrite!(w, "e");
|
write!(w, "e");
|
||||||
enc_ty(w, cx, a);
|
enc_ty(w, cx, a);
|
||||||
enc_ty(w, cx, b);
|
enc_ty(w, cx, b);
|
||||||
}
|
}
|
||||||
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(a, 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, a);
|
||||||
enc_region(w, cx, b);
|
enc_region(w, cx, b);
|
||||||
}
|
}
|
||||||
ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
|
ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
|
||||||
mywrite!(w, "o");
|
write!(w, "o");
|
||||||
enc_ty(w, cx, a);
|
enc_ty(w, cx, a);
|
||||||
enc_region(w, cx, b);
|
enc_region(w, cx, b);
|
||||||
}
|
}
|
||||||
ty::Predicate::Projection(ty::Binder(ref data)) => {
|
ty::Predicate::Projection(ty::Binder(ref data)) => {
|
||||||
mywrite!(w, "p");
|
write!(w, "p");
|
||||||
enc_projection_predicate(w, cx, data)
|
enc_projection_predicate(w, cx, data);
|
||||||
}
|
}
|
||||||
ty::Predicate::WellFormed(data) => {
|
ty::Predicate::WellFormed(data) => {
|
||||||
mywrite!(w, "w");
|
write!(w, "w");
|
||||||
enc_ty(w, cx, data);
|
enc_ty(w, cx, data);
|
||||||
}
|
}
|
||||||
ty::Predicate::ObjectSafe(trait_def_id) => {
|
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>,
|
cx: &ctxt<'a, 'tcx>,
|
||||||
data: &ty::ProjectionPredicate<'tcx>) {
|
data: &ty::ProjectionPredicate<'tcx>) {
|
||||||
enc_trait_ref(w, cx, data.projection_ty.trait_ref);
|
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);
|
enc_ty(w, cx, data.ty);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ use middle::pat_util::simple_name;
|
||||||
use middle::subst::Substs;
|
use middle::subst::Substs;
|
||||||
use middle::ty::{self, Ty, HasTypeFlags};
|
use middle::ty::{self, Ty, HasTypeFlags};
|
||||||
use rustc::front::map as hir_map;
|
use rustc::front::map as hir_map;
|
||||||
|
use rustc::util::common::time;
|
||||||
use rustc_mir::mir_map::MirMap;
|
use rustc_mir::mir_map::MirMap;
|
||||||
use session::config::{self, NoDebugInfo, FullDebugInfo};
|
use session::config::{self, NoDebugInfo, FullDebugInfo};
|
||||||
use session::Session;
|
use session::Session;
|
||||||
|
@ -3057,7 +3058,9 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
let reachable_symbol_ids = filter_reachable_ids(&shared_ccx);
|
let reachable_symbol_ids = filter_reachable_ids(&shared_ccx);
|
||||||
|
|
||||||
// Translate the metadata.
|
// 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() {
|
if shared_ccx.sess().trans_stats() {
|
||||||
let stats = shared_ccx.stats();
|
let stats = shared_ccx.stats();
|
||||||
|
|
|
@ -164,18 +164,15 @@ impl Eq for Span {}
|
||||||
|
|
||||||
impl Encodable for Span {
|
impl Encodable for Span {
|
||||||
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
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
|
try!(s.emit_u32(self.lo.0));
|
||||||
// added by the RBML metadata encoding. The should be solved differently
|
s.emit_u32(self.hi.0)
|
||||||
// altogether some time (FIXME #21482)
|
|
||||||
s.emit_u64( (self.lo.0 as u64) | ((self.hi.0 as u64) << 32) )
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for Span {
|
impl Decodable for Span {
|
||||||
fn decode<D: Decoder>(d: &mut D) -> Result<Span, D::Error> {
|
fn decode<D: Decoder>(d: &mut D) -> Result<Span, D::Error> {
|
||||||
let lo_hi: u64 = try! { d.read_u64() };
|
let lo = BytePos(try! { d.read_u32() });
|
||||||
let lo = BytePos(lo_hi as u32);
|
let hi = BytePos(try! { d.read_u32() });
|
||||||
let hi = BytePos((lo_hi >> 32) as u32);
|
|
||||||
Ok(mk_sp(lo, hi))
|
Ok(mk_sp(lo, hi))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue