diff --git a/src/librbml/leb128.rs b/src/librbml/leb128.rs new file mode 100644 index 0000000000000..a5e8522623a2e --- /dev/null +++ b/src/librbml/leb128.rs @@ -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 or the MIT license +// , 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, 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, + 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, + 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()); +} diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index d8d6ea93f7569..f3a1bbd7e26b8 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -128,10 +128,17 @@ #![cfg_attr(test, feature(test))] extern crate serialize; + +#[cfg(test)] +extern crate serialize as rustc_serialize; // Used by RustcEncodable + #[macro_use] extern crate log; #[cfg(test)] extern crate test; +pub mod opaque; +pub mod leb128; + pub use self::EbmlEncoderTag::*; pub use self::Error::*; @@ -241,6 +248,7 @@ pub mod reader { use serialize; + use super::opaque; use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, @@ -621,18 +629,16 @@ pub mod reader { } pub fn read_opaque(&mut self, op: F) -> DecodeResult where - F: FnOnce(&mut Decoder, Doc) -> DecodeResult, + F: FnOnce(&mut opaque::Decoder, Doc) -> DecodeResult, { let doc = try!(self.next_doc(EsOpaque)); - let (old_parent, old_pos) = (self.parent, self.pos); - self.parent = doc; - self.pos = doc.start; - - let result = try!(op(self, doc)); + let result = { + let mut opaque_decoder = opaque::Decoder::new(doc.data, + doc.start); + try!(op(&mut opaque_decoder, doc)) + }; - self.parent = old_parent; - self.pos = old_pos; Ok(result) } @@ -877,6 +883,7 @@ pub mod writer { use std::io::prelude::*; use std::io::{self, SeekFrom, Cursor}; + use super::opaque; use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, @@ -1120,10 +1127,16 @@ pub mod writer { } pub fn emit_opaque(&mut self, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder) -> EncodeResult, + F: FnOnce(&mut opaque::Encoder) -> EncodeResult, { try!(self.start_tag(EsOpaque as usize)); - try!(f(self)); + + { + let mut opaque_encoder = opaque::Encoder::new(self.writer); + try!(f(&mut opaque_encoder)); + } + + self.mark_stable_position(); self.end_tag() } } diff --git a/src/librbml/opaque.rs b/src/librbml/opaque.rs new file mode 100644 index 0000000000000..64756090e8b48 --- /dev/null +++ b/src/librbml/opaque.rs @@ -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 or the MIT license +// , 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>, +} + +impl<'a> Encoder<'a> { + pub fn new(cursor: &'a mut io::Cursor>) -> 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(&mut self, _name: &str, f: F) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { + f(self) + } + + fn emit_enum_variant(&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(&mut self, _: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + f(self) + } + + fn emit_enum_struct_variant(&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(&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(&mut self, _: &str, _len: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + f(self) + } + + fn emit_struct_field(&mut self, _name: &str, _: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + f(self) + } + + fn emit_tuple(&mut self, len: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + self.emit_seq(len, f) + } + + fn emit_tuple_arg(&mut self, idx: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + self.emit_seq_elt(idx, f) + } + + fn emit_tuple_struct(&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(&mut self, idx: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + self.emit_seq_elt(idx, f) + } + + fn emit_option(&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(&mut self, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + self.emit_enum_variant("Some", 1, 1, f) + } + + fn emit_seq(&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(&mut self, _idx: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + f(self) + } + + fn emit_map(&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(&mut self, _idx: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + f(self) + } + + fn emit_map_elt_val(&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 { + read_uleb128!(self, u64) + } + + fn read_u32(&mut self) -> Result { + read_uleb128!(self, u32) + } + + fn read_u16(&mut self) -> Result { + read_uleb128!(self, u16) + } + + fn read_u8(&mut self) -> Result { + let value = self.data[self.position]; + self.position += 1; + Ok(value) + } + + fn read_uint(&mut self) -> Result { + read_uleb128!(self, usize) + } + + fn read_i64(&mut self) -> Result { + read_sleb128!(self, i64) + } + + fn read_i32(&mut self) -> Result { + read_sleb128!(self, i32) + } + + fn read_i16(&mut self) -> Result { + read_sleb128!(self, i16) + } + + fn read_i8(&mut self) -> Result { + let as_u8 = self.data[self.position]; + self.position += 1; + unsafe { + Ok(::std::mem::transmute(as_u8)) + } + } + + fn read_int(&mut self) -> Result { + read_sleb128!(self, isize) + } + + fn read_bool(&mut self) -> Result { + let value = try!(self.read_u8()); + Ok(value != 0) + } + + fn read_f64(&mut self) -> Result { + let bits = try!(self.read_u64()); + Ok(unsafe { ::std::mem::transmute(bits) }) + } + + fn read_f32(&mut self) -> Result { + let bits = try!(self.read_u32()); + Ok(unsafe { ::std::mem::transmute(bits) }) + } + + fn read_char(&mut self) -> Result { + let bits = try!(self.read_u32()); + Ok(::std::char::from_u32(bits).unwrap()) + } + + fn read_str(&mut self) -> Result { + 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(&mut self, _name: &str, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + f(self) + } + + fn read_enum_variant(&mut self, + _: &[&str], + mut f: F) + -> Result + where F: FnMut(&mut Decoder<'a>, usize) -> Result, + { + let disr = try!(self.read_uint()); + f(self, disr) + } + + fn read_enum_variant_arg(&mut self, _idx: usize, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + f(self) + } + + fn read_enum_struct_variant(&mut self, + _: &[&str], + mut f: F) -> Result + where F: FnMut(&mut Decoder<'a>, usize) -> Result, + { + let disr = try!(self.read_uint()); + f(self, disr) + } + + fn read_enum_struct_variant_field(&mut self, + _name: &str, + _idx: usize, + f: F) + -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + f(self) + } + + fn read_struct(&mut self, _name: &str, _: usize, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + f(self) + } + + fn read_struct_field(&mut self, + _name: &str, + _idx: usize, f: F) + -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + f(self) + } + + fn read_tuple(&mut self, tuple_len: usize, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + 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(&mut self, idx: usize, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + self.read_seq_elt(idx, f) + } + + fn read_tuple_struct(&mut self, + _name: &str, + len: usize, f: F) + -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + self.read_tuple(len, f) + } + + fn read_tuple_struct_arg(&mut self, + idx: usize, + f: F) + -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + self.read_tuple_arg(idx, f) + } + + fn read_option(&mut self, mut f: F) -> Result where + F: FnMut(&mut Decoder<'a>, bool) -> Result, + { + 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(&mut self, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>, usize) -> Result, + { + let len = try!(self.read_uint()); + f(self, len) + } + + fn read_seq_elt(&mut self, _idx: usize, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + f(self) + } + + fn read_map(&mut self, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>, usize) -> Result, + { + let len = try!(self.read_uint()); + f(self, len) + } + + fn read_map_elt_key(&mut self, _idx: usize, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + f(self) + } + + fn read_map_elt_val(&mut self, _idx: usize, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + 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, + } + + + fn check_round_trip(values: Vec) { + 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 = None; + check_round_trip(vec![none_i8]); + + let none_i16: Option = None; + check_round_trip(vec![none_i16]); + + let none_i32: Option = None; + check_round_trip(vec![none_i32]); + + let none_i64: Option = None; + check_round_trip(vec![none_i64]); + + let none_isize: Option = 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())]); + } +} diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 2c3b89bf2fbb2..380f543f969f0 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -432,8 +432,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { /// Note, however, that this only works for RBML-based encoding and decoding at /// the moment. pub mod tls { - use rbml::writer::Encoder as RbmlEncoder; - use rbml::reader::Decoder as RbmlDecoder; + use rbml::opaque::Encoder as OpaqueEncoder; + use rbml::opaque::Decoder as OpaqueDecoder; use serialize; use std::mem; use middle::ty::{self, Ty}; @@ -442,8 +442,8 @@ pub mod tls { pub trait EncodingContext<'tcx> { fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>; - fn encode_ty(&self, rbml_w: &mut RbmlEncoder, t: Ty<'tcx>); - fn encode_substs(&self, rbml_w: &mut RbmlEncoder, substs: &Substs<'tcx>); + fn encode_ty(&self, encoder: &mut OpaqueEncoder, t: Ty<'tcx>); + fn encode_substs(&self, encoder: &mut OpaqueEncoder, substs: &Substs<'tcx>); } /// Marker type used for the scoped TLS slot. @@ -455,13 +455,13 @@ pub mod tls { /// Execute f after pushing the given EncodingContext onto the TLS stack. pub fn enter_encoding_context<'tcx, F, R>(ecx: &EncodingContext<'tcx>, - rbml_w: &mut RbmlEncoder, + encoder: &mut OpaqueEncoder, f: F) -> R - where F: FnOnce(&EncodingContext<'tcx>, &mut RbmlEncoder) -> R + where F: FnOnce(&EncodingContext<'tcx>, &mut OpaqueEncoder) -> R { - let tls_payload = (ecx as *const _, rbml_w as *mut _); + let tls_payload = (ecx as *const _, encoder as *mut _); let tls_ptr = &tls_payload as *const _ as *const TlsPayload; - TLS_ENCODING.set(unsafe { &*tls_ptr }, || f(ecx, rbml_w)) + TLS_ENCODING.set(unsafe { &*tls_ptr }, || f(ecx, encoder)) } /// Execute f with access to the thread-local encoding context and @@ -473,16 +473,16 @@ pub mod tls { /// possible to construct cases where the EncodingContext is exchanged /// while the same encoder is used, thus working with a wrong context. pub fn with_encoding_context<'tcx, E, F, R>(encoder: &mut E, f: F) -> R - where F: FnOnce(&EncodingContext<'tcx>, &mut RbmlEncoder) -> R, + where F: FnOnce(&EncodingContext<'tcx>, &mut OpaqueEncoder) -> R, E: serialize::Encoder { unsafe { - unsafe_with_encoding_context(|ecx, rbml_w| { - assert!(encoder as *mut _ as usize == rbml_w as *mut _ as usize); + unsafe_with_encoding_context(|ecx, tls_encoder| { + assert!(encoder as *mut _ as usize == tls_encoder as *mut _ as usize); let ecx: &EncodingContext<'tcx> = mem::transmute(ecx); - f(ecx, rbml_w) + f(ecx, tls_encoder) }) } } @@ -490,19 +490,19 @@ pub mod tls { /// Execute f with access to the thread-local encoding context and /// rbml encoder. pub unsafe fn unsafe_with_encoding_context(f: F) -> R - where F: FnOnce(&EncodingContext, &mut RbmlEncoder) -> R + where F: FnOnce(&EncodingContext, &mut OpaqueEncoder) -> R { TLS_ENCODING.with(|tls| { let tls_payload = (tls as *const TlsPayload) - as *mut (&EncodingContext, &mut RbmlEncoder); + as *mut (&EncodingContext, &mut OpaqueEncoder); f((*tls_payload).0, (*tls_payload).1) }) } pub trait DecodingContext<'tcx> { fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>; - fn decode_ty(&self, rbml_r: &mut RbmlDecoder) -> ty::Ty<'tcx>; - fn decode_substs(&self, rbml_r: &mut RbmlDecoder) -> Substs<'tcx>; + fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx>; + fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> Substs<'tcx>; fn translate_def_id(&self, def_id: DefId) -> DefId; } @@ -510,13 +510,13 @@ pub mod tls { /// Execute f after pushing the given DecodingContext onto the TLS stack. pub fn enter_decoding_context<'tcx, F, R>(dcx: &DecodingContext<'tcx>, - rbml_r: &mut RbmlDecoder, + decoder: &mut OpaqueDecoder, f: F) -> R - where F: FnOnce(&DecodingContext<'tcx>, &mut RbmlDecoder) -> R + where F: FnOnce(&DecodingContext<'tcx>, &mut OpaqueDecoder) -> R { - let tls_payload = (dcx as *const _, rbml_r as *mut _); + let tls_payload = (dcx as *const _, decoder as *mut _); let tls_ptr = &tls_payload as *const _ as *const TlsPayload; - TLS_DECODING.set(unsafe { &*tls_ptr }, || f(dcx, rbml_r)) + TLS_DECODING.set(unsafe { &*tls_ptr }, || f(dcx, decoder)) } /// Execute f with access to the thread-local decoding context and @@ -530,16 +530,16 @@ pub mod tls { pub fn with_decoding_context<'decoder, 'tcx, D, F, R>(d: &'decoder mut D, f: F) -> R where D: serialize::Decoder, F: FnOnce(&DecodingContext<'tcx>, - &mut RbmlDecoder) -> R, + &mut OpaqueDecoder) -> R, 'tcx: 'decoder { unsafe { - unsafe_with_decoding_context(|dcx, rbml_r| { - assert!((d as *mut _ as usize) == (rbml_r as *mut _ as usize)); + unsafe_with_decoding_context(|dcx, decoder| { + assert!((d as *mut _ as usize) == (decoder as *mut _ as usize)); let dcx: &DecodingContext<'tcx> = mem::transmute(dcx); - f(dcx, rbml_r) + f(dcx, decoder) }) } } @@ -547,11 +547,11 @@ pub mod tls { /// Execute f with access to the thread-local decoding context and /// rbml decoder. pub unsafe fn unsafe_with_decoding_context(f: F) -> R - where F: FnOnce(&DecodingContext, &mut RbmlDecoder) -> R + where F: FnOnce(&DecodingContext, &mut OpaqueDecoder) -> R { TLS_DECODING.with(|tls| { let tls_payload = (tls as *const TlsPayload) - as *mut (&DecodingContext, &mut RbmlDecoder); + as *mut (&DecodingContext, &mut OpaqueDecoder); f((*tls_payload).0, (*tls_payload).1) }) } diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 8f74acd9ebdf6..8c3bd3c4f8a53 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -292,7 +292,7 @@ impl def_id_decoder_helpers for D fn encode_ast(rbml_w: &mut Encoder, item: &InlinedItem) { rbml_w.start_tag(c::tag_tree as usize); - item.encode(rbml_w); + rbml_w.emit_opaque(|this| item.encode(this)); rbml_w.end_tag(); } @@ -361,8 +361,8 @@ fn simplify_ast(ii: InlinedItemRef) -> InlinedItem { fn decode_ast(par_doc: rbml::Doc) -> InlinedItem { let chi_doc = par_doc.get(c::tag_tree as usize); - let mut d = reader::Decoder::new(chi_doc); - Decodable::decode(&mut d).unwrap() + let mut rbml_r = reader::Decoder::new(chi_doc); + rbml_r.read_opaque(|decoder, _| Decodable::decode(decoder)).unwrap() } // ______________________________________________________________________ @@ -509,21 +509,6 @@ pub fn encode_cast_kind(ebml_w: &mut Encoder, kind: cast::CastKind) { // ______________________________________________________________________ // Encoding and decoding the side tables -trait get_ty_str_ctxt<'tcx> { - fn ty_str_ctxt<'a>(&'a self) -> tyencode::ctxt<'a, 'tcx>; -} - -impl<'a, 'tcx> get_ty_str_ctxt<'tcx> for e::EncodeContext<'a, 'tcx> { - fn ty_str_ctxt<'b>(&'b self) -> tyencode::ctxt<'b, 'tcx> { - tyencode::ctxt { - diag: self.tcx.sess.diagnostic(), - ds: e::def_to_string, - tcx: self.tcx, - abbrevs: &self.type_abbrevs - } - } -} - trait rbml_writer_helpers<'tcx> { fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region); fn emit_ty<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, ty: Ty<'tcx>); @@ -548,11 +533,15 @@ trait rbml_writer_helpers<'tcx> { impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region) { - self.emit_opaque(|this| Ok(e::write_region(ecx, this, r))); + self.emit_opaque(|this| Ok(tyencode::enc_region(&mut this.cursor, + &ecx.ty_str_ctxt(), + r))); } fn emit_ty<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, ty: Ty<'tcx>) { - self.emit_opaque(|this| Ok(e::write_type(ecx, this, ty))); + self.emit_opaque(|this| Ok(tyencode::enc_ty(&mut this.cursor, + &ecx.ty_str_ctxt(), + ty))); } fn emit_tys<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, tys: &[Ty<'tcx>]) { @@ -561,13 +550,15 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { fn emit_trait_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, trait_ref: &ty::TraitRef<'tcx>) { - self.emit_opaque(|this| Ok(e::write_trait_ref(ecx, this, trait_ref))); + self.emit_opaque(|this| Ok(tyencode::enc_trait_ref(&mut this.cursor, + &ecx.ty_str_ctxt(), + *trait_ref))); } fn emit_predicate<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, predicate: &ty::Predicate<'tcx>) { self.emit_opaque(|this| { - Ok(tyencode::enc_predicate(this, + Ok(tyencode::enc_predicate(&mut this.cursor, &ecx.ty_str_ctxt(), predicate)) }); @@ -575,13 +566,13 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>, bounds: &ty::ExistentialBounds<'tcx>) { - self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(this, + self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(&mut this.cursor, &ecx.ty_str_ctxt(), bounds))); } fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds) { - self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(this, + self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(&mut this.cursor, &ecx.ty_str_ctxt(), bounds))); } @@ -608,9 +599,9 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { fn emit_substs<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, substs: &subst::Substs<'tcx>) { - self.emit_opaque(|this| Ok(tyencode::enc_substs(this, - &ecx.ty_str_ctxt(), - substs))); + self.emit_opaque(|this| Ok(tyencode::enc_substs(&mut this.cursor, + &ecx.ty_str_ctxt(), + substs))); } fn emit_auto_adjustment<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, @@ -878,10 +869,6 @@ trait rbml_decoder_decoder_helpers<'tcx> { -> adjustment::AutoDerefRef<'tcx>; fn read_autoref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> adjustment::AutoRef<'tcx>; - fn convert_def_id(&mut self, - dcx: &DecodeContext, - did: DefId) - -> DefId; // Versions of the type reading functions that don't need the full // DecodeContext. @@ -933,12 +920,12 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { fn read_ty_encoded<'b, 'c, F, R>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>, op: F) -> R where F: for<'x> FnOnce(&mut tydecode::TyDecoder<'x,'tcx>) -> R { - return self.read_opaque(|this, doc| { + return self.read_opaque(|_, doc| { debug!("read_ty_encoded({})", type_string(doc)); Ok(op( &mut tydecode::TyDecoder::with_doc( dcx.tcx, dcx.cdata.cnum, doc, - &mut |a| this.convert_def_id(dcx, a)))) + &mut |d| convert_def_id(dcx, d)))) }).unwrap(); fn type_string(doc: rbml::Doc) -> String { @@ -989,9 +976,9 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { fn read_substs<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> subst::Substs<'tcx> { - self.read_opaque(|this, doc| { + self.read_opaque(|_, doc| { Ok(tydecode::TyDecoder::with_doc(dcx.tcx, dcx.cdata.cnum, doc, - &mut |a| this.convert_def_id(dcx, a)) + &mut |d| convert_def_id(dcx, d)) .parse_substs()) }).unwrap() } @@ -1097,47 +1084,46 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { { Decodable::decode(self).unwrap() } +} - /// Converts a def-id that appears in a type. The correct - /// translation will depend on what kind of def-id this is. - /// This is a subtle point: type definitions are not - /// inlined into the current crate, so if the def-id names - /// a nominal type or type alias, then it should be - /// translated to refer to the source crate. - /// - /// However, *type parameters* are cloned along with the function - /// they are attached to. So we should translate those def-ids - /// to refer to the new, cloned copy of the type parameter. - /// We only see references to free type parameters in the body of - /// an inlined function. In such cases, we need the def-id to - /// be a local id so that the TypeContents code is able to lookup - /// the relevant info in the ty_param_defs table. - /// - /// *Region parameters*, unfortunately, are another kettle of fish. - /// In such cases, def_id's can appear in types to distinguish - /// shadowed bound regions and so forth. It doesn't actually - /// matter so much what we do to these, since regions are erased - /// at trans time, but it's good to keep them consistent just in - /// case. We translate them with `tr_def_id()` which will map - /// the crate numbers back to the original source crate. - /// - /// Scopes will end up as being totally bogus. This can actually - /// be fixed though. - /// - /// Unboxed closures are cloned along with the function being - /// inlined, and all side tables use interned node IDs, so we - /// translate their def IDs accordingly. - /// - /// It'd be really nice to refactor the type repr to not include - /// def-ids so that all these distinctions were unnecessary. - fn convert_def_id(&mut self, - dcx: &DecodeContext, - did: DefId) - -> DefId { - let r = dcx.tr_def_id(did); - debug!("convert_def_id(did={:?})={:?}", did, r); - return r; - } +// Converts a def-id that appears in a type. The correct +// translation will depend on what kind of def-id this is. +// This is a subtle point: type definitions are not +// inlined into the current crate, so if the def-id names +// a nominal type or type alias, then it should be +// translated to refer to the source crate. +// +// However, *type parameters* are cloned along with the function +// they are attached to. So we should translate those def-ids +// to refer to the new, cloned copy of the type parameter. +// We only see references to free type parameters in the body of +// an inlined function. In such cases, we need the def-id to +// be a local id so that the TypeContents code is able to lookup +// the relevant info in the ty_param_defs table. +// +// *Region parameters*, unfortunately, are another kettle of fish. +// In such cases, def_id's can appear in types to distinguish +// shadowed bound regions and so forth. It doesn't actually +// matter so much what we do to these, since regions are erased +// at trans time, but it's good to keep them consistent just in +// case. We translate them with `tr_def_id()` which will map +// the crate numbers back to the original source crate. +// +// Scopes will end up as being totally bogus. This can actually +// be fixed though. +// +// Unboxed closures are cloned along with the function being +// inlined, and all side tables use interned node IDs, so we +// translate their def IDs accordingly. +// +// It'd be really nice to refactor the type repr to not include +// def-ids so that all these distinctions were unnecessary. +fn convert_def_id(dcx: &DecodeContext, + did: DefId) + -> DefId { + let r = dcx.tr_def_id(did); + debug!("convert_def_id(did={:?})={:?}", did, r); + return r; } fn decode_side_tables(dcx: &DecodeContext, diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 29fe9bc759dde..54cccf087ebb6 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -833,9 +833,11 @@ pub fn maybe_get_item_mir<'tcx>(cdata: Cmd, }; let mut decoder = reader::Decoder::new(mir_doc); - let mut mir = tls::enter_decoding_context(&dcx, &mut decoder, |_, decoder| { - Decodable::decode(decoder).unwrap() - }); + let mut mir = decoder.read_opaque(|opaque_decoder, _| { + tls::enter_decoding_context(&dcx, opaque_decoder, |_, opaque_decoder| { + Decodable::decode(opaque_decoder) + }) + }).unwrap(); let mut def_id_and_span_translator = MirDefIdAndSpanTranslator { crate_metadata: cdata, @@ -1643,7 +1645,9 @@ pub fn get_imported_filemaps(metadata: &[u8]) -> Vec { reader::tagged_docs(cm_doc, tag_codemap_filemap).map(|filemap_doc| { let mut decoder = reader::Decoder::new(filemap_doc); - Decodable::decode(&mut decoder).unwrap() + decoder.read_opaque(|opaque_decoder, _| { + Decodable::decode(opaque_decoder) + }).unwrap() }).collect() } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index f1c5d47df8889..26f32e207647f 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -140,15 +140,9 @@ fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder, ecx: &EncodeContext<'a, 'tcx>, trait_ref: ty::TraitRef<'tcx>, tag: usize) { - let ty_str_ctxt = &tyencode::ctxt { - diag: ecx.diag, - ds: def_to_string, - tcx: ecx.tcx, - abbrevs: &ecx.type_abbrevs - }; - rbml_w.start_tag(tag); - tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, trait_ref); + tyencode::enc_trait_ref(rbml_w.writer, &ecx.ty_str_ctxt(), trait_ref); + rbml_w.mark_stable_position(); rbml_w.end_tag(); } @@ -202,59 +196,19 @@ fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) { rbml_w.wr_tagged_u64(tag_mod_child, id); } -pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, - rbml_w: &mut Encoder, - closure_type: &ty::ClosureTy<'tcx>) { - let ty_str_ctxt = &tyencode::ctxt { - diag: ecx.diag, - ds: def_to_string, - tcx: ecx.tcx, - abbrevs: &ecx.type_abbrevs - }; - tyencode::enc_closure_ty(rbml_w, ty_str_ctxt, closure_type); -} - -pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, +fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, rbml_w: &mut Encoder, - typ: Ty<'tcx>) { - let ty_str_ctxt = &tyencode::ctxt { - diag: ecx.diag, - ds: def_to_string, - tcx: ecx.tcx, - abbrevs: &ecx.type_abbrevs - }; - tyencode::enc_ty(rbml_w, ty_str_ctxt, typ); -} - -pub fn write_trait_ref<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, - rbml_w: &mut Encoder, - trait_ref: &ty::TraitRef<'tcx>) { - let ty_str_ctxt = &tyencode::ctxt { - diag: ecx.diag, - ds: def_to_string, - tcx: ecx.tcx, - abbrevs: &ecx.type_abbrevs - }; - tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, *trait_ref); -} - -pub fn write_region(ecx: &EncodeContext, - rbml_w: &mut Encoder, - r: ty::Region) { - let ty_str_ctxt = &tyencode::ctxt { - diag: ecx.diag, - ds: def_to_string, - tcx: ecx.tcx, - abbrevs: &ecx.type_abbrevs - }; - tyencode::enc_region(rbml_w, ty_str_ctxt, r); + closure_type: &ty::ClosureTy<'tcx>) { + tyencode::enc_closure_ty(rbml_w.writer, &ecx.ty_str_ctxt(), closure_type); + rbml_w.mark_stable_position(); } fn encode_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, rbml_w: &mut Encoder, typ: Ty<'tcx>) { rbml_w.start_tag(tag_items_data_item_type); - write_type(ecx, rbml_w, typ); + tyencode::enc_ty(rbml_w.writer, &ecx.ty_str_ctxt(), typ); + rbml_w.mark_stable_position(); rbml_w.end_tag(); } @@ -262,7 +216,8 @@ fn encode_region(ecx: &EncodeContext, rbml_w: &mut Encoder, r: ty::Region) { rbml_w.start_tag(tag_items_data_region); - write_region(ecx, rbml_w, r); + tyencode::enc_region(rbml_w.writer, &ecx.ty_str_ctxt(), r); + rbml_w.mark_stable_position(); rbml_w.end_tag(); } @@ -592,17 +547,10 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder, { rbml_w.start_tag(tag); - // Type parameters - let ty_str_ctxt = &tyencode::ctxt { - diag: ecx.diag, - ds: def_to_string, - tcx: ecx.tcx, - abbrevs: &ecx.type_abbrevs - }; - for param in &generics.types { rbml_w.start_tag(tag_type_param_def); - tyencode::enc_type_param_def(rbml_w, ty_str_ctxt, param); + tyencode::enc_type_param_def(rbml_w.writer, &ecx.ty_str_ctxt(), param); + rbml_w.mark_stable_position(); rbml_w.end_tag(); } @@ -871,7 +819,11 @@ fn encode_mir(ecx: &EncodeContext, rbml_w: &mut Encoder, ii: InlinedItemRef) { if let Some(mir) = ecx.mir_map.get(&id) { rbml_w.start_tag(tag_mir as usize); - Encodable::encode(mir, rbml_w).unwrap(); + rbml_w.emit_opaque(|opaque_encoder| { + tls::enter_encoding_context(ecx, opaque_encoder, |_, opaque_encoder| { + Encodable::encode(mir, opaque_encoder) + }) + }).unwrap(); rbml_w.end_tag(); } } @@ -916,23 +868,17 @@ fn encode_xrefs<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, rbml_w: &mut Encoder, xrefs: FnvHashMap, u32>) { - let ty_str_ctxt = &tyencode::ctxt { - diag: ecx.diag, - ds: def_to_string, - tcx: ecx.tcx, - abbrevs: &ecx.type_abbrevs - }; - let mut xref_positions = vec![0; xrefs.len()]; rbml_w.start_tag(tag_xref_data); for (xref, id) in xrefs.into_iter() { xref_positions[id as usize] = rbml_w.mark_stable_position() as u32; match xref { XRef::Predicate(p) => { - tyencode::enc_predicate(rbml_w, ty_str_ctxt, &p) + tyencode::enc_predicate(rbml_w.writer, &ecx.ty_str_ctxt(), &p) } } } + rbml_w.mark_stable_position(); rbml_w.end_tag(); rbml_w.start_tag(tag_xref_index); @@ -1750,7 +1696,9 @@ fn encode_codemap(ecx: &EncodeContext, rbml_w: &mut Encoder) { } rbml_w.start_tag(tag_codemap_filemap); - filemap.encode(rbml_w); + rbml_w.emit_opaque(|opaque_encoder| { + filemap.encode(opaque_encoder) + }).unwrap(); rbml_w.end_tag(); } @@ -1961,9 +1909,7 @@ pub fn encode_metadata(parms: EncodeParams, krate: &hir::Crate) -> Vec { { let mut rbml_w = Encoder::new(&mut wr); - tls::enter_encoding_context(&ecx, &mut rbml_w, |_, rbml_w| { - encode_metadata_inner(rbml_w, &ecx, krate) - }); + encode_metadata_inner(&mut rbml_w, &ecx, krate) } // RBML compacts the encoded bytes whenever appropriate, @@ -2132,7 +2078,7 @@ fn encode_metadata_inner(rbml_w: &mut Encoder, // Get the encoded string for a type pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Vec { let mut wr = Cursor::new(Vec::new()); - tyencode::enc_ty(&mut Encoder::new(&mut wr), &tyencode::ctxt { + tyencode::enc_ty(&mut wr, &tyencode::ctxt { diag: tcx.sess.diagnostic(), ds: def_to_string, tcx: tcx, diff --git a/src/librustc_metadata/tls_context.rs b/src/librustc_metadata/tls_context.rs index eb82d2df94d15..37e661c21e15a 100644 --- a/src/librustc_metadata/tls_context.rs +++ b/src/librustc_metadata/tls_context.rs @@ -11,8 +11,8 @@ // This module provides implementations for the thread-local encoding and // decoding context traits in rustc::middle::cstore::tls. -use rbml::writer::Encoder as RbmlEncoder; -use rbml::reader::Decoder as RbmlDecoder; +use rbml::opaque::Encoder as OpaqueEncoder; +use rbml::opaque::Decoder as OpaqueDecoder; use rustc::middle::cstore::tls; use rustc::middle::def_id::DefId; use rustc::middle::subst::Substs; @@ -23,25 +23,18 @@ use encoder; use tydecode::TyDecoder; use tyencode; - impl<'a, 'tcx: 'a> tls::EncodingContext<'tcx> for encoder::EncodeContext<'a, 'tcx> { fn tcx<'s>(&'s self) -> &'s ty::ctxt<'tcx> { &self.tcx } - fn encode_ty(&self, rbml_w: &mut RbmlEncoder, t: ty::Ty<'tcx>) { - encoder::write_type(self, rbml_w, t); + fn encode_ty(&self, encoder: &mut OpaqueEncoder, t: ty::Ty<'tcx>) { + tyencode::enc_ty(encoder.cursor, &self.ty_str_ctxt(), t); } - fn encode_substs(&self, rbml_w: &mut RbmlEncoder, substs: &Substs<'tcx>) { - let ty_str_ctxt = &tyencode::ctxt { - diag: self.diag, - ds: encoder::def_to_string, - tcx: self.tcx, - abbrevs: &self.type_abbrevs - }; - tyencode::enc_substs(rbml_w, ty_str_ctxt, substs); + fn encode_substs(&self, encoder: &mut OpaqueEncoder, substs: &Substs<'tcx>) { + tyencode::enc_substs(encoder.cursor, &self.ty_str_ctxt(), substs); } } @@ -56,12 +49,12 @@ impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> { &self.tcx } - fn decode_ty(&self, rbml_r: &mut RbmlDecoder) -> ty::Ty<'tcx> { + fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx> { let def_id_convert = &mut |did| { decoder::translate_def_id(self.crate_metadata, did) }; - let starting_position = rbml_r.position(); + let starting_position = decoder.position(); let mut ty_decoder = TyDecoder::new( self.crate_metadata.data.as_slice(), @@ -77,16 +70,16 @@ impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> { // We can just reuse the tydecode implementation for parsing types, but // we have to make sure to leave the rbml reader at the position just // after the type. - rbml_r.advance(end_position - starting_position); + decoder.advance(end_position - starting_position); ty } - fn decode_substs(&self, rbml_r: &mut RbmlDecoder) -> Substs<'tcx> { + fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> Substs<'tcx> { let def_id_convert = &mut |did| { decoder::translate_def_id(self.crate_metadata, did) }; - let starting_position = rbml_r.position(); + let starting_position = decoder.position(); let mut ty_decoder = TyDecoder::new( self.crate_metadata.data.as_slice(), @@ -99,7 +92,7 @@ impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> { let end_position = ty_decoder.position(); - rbml_r.advance(end_position - starting_position); + decoder.advance(end_position - starting_position); substs } diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs index b99431d265618..c7a5faed35cd0 100644 --- a/src/librustc_metadata/tydecode.rs +++ b/src/librustc_metadata/tydecode.rs @@ -25,6 +25,7 @@ use middle::subst::VecPerParamSpace; use middle::ty::{self, ToPredicate, Ty, HasTypeFlags}; use rbml; +use rbml::leb128; use std::str; use syntax::abi; use syntax::ast; @@ -103,9 +104,10 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } fn parse_vuint(&mut self) -> usize { - let res = rbml::reader::vuint_at(self.data, self.pos).unwrap(); - self.pos = res.next; - res.val + let (value, bytes_read) = leb128::read_unsigned_leb128(self.data, + self.pos); + self.pos += bytes_read; + value as usize } fn parse_name(&mut self, last: char) -> ast::Name { diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index 6d42871201b8e..f03c25d698feb 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -31,9 +31,8 @@ use syntax::abi::Abi; use syntax::ast; use syntax::errors::Handler; -use rbml::writer::{self, Encoder}; - -macro_rules! mywrite { ($w:expr, $($arg:tt)*) => ({ write!($w.writer, $($arg)*); }) } +use rbml::leb128; +use encoder; pub struct ctxt<'a, 'tcx: 'a> { pub diag: &'a Handler, @@ -44,6 +43,17 @@ pub struct ctxt<'a, 'tcx: 'a> { pub abbrevs: &'a abbrev_map<'tcx> } +impl<'a, 'tcx> encoder::EncodeContext<'a, 'tcx> { + pub fn ty_str_ctxt<'b>(&'b self) -> ctxt<'b, 'tcx> { + ctxt { + diag: self.tcx.sess.diagnostic(), + ds: encoder::def_to_string, + tcx: self.tcx, + abbrevs: &self.type_abbrevs + } + } +} + // Compact string representation for Ty values. API TyStr & parse_from_str. // Extra parameters are for converting to/from def_ids in the string rep. // Whatever format you choose should not contain pipe characters. @@ -53,125 +63,129 @@ pub struct ty_abbrev { pub type abbrev_map<'tcx> = RefCell, 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>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) { match cx.abbrevs.borrow_mut().get(&t) { - Some(a) => { w.writer.write_all(&a.s); return; } + Some(a) => { w.write_all(&a.s); return; } None => {} } - // type abbreviations needs a stable position - let pos = w.mark_stable_position(); + let pos = w.position(); match t.sty { - ty::TyBool => mywrite!(w, "b"), - ty::TyChar => mywrite!(w, "c"), + ty::TyBool => { write!(w, "b"); } + ty::TyChar => { write!(w, "c"); } ty::TyInt(t) => { match t { - ast::TyIs => mywrite!(w, "is"), - ast::TyI8 => mywrite!(w, "MB"), - ast::TyI16 => mywrite!(w, "MW"), - ast::TyI32 => mywrite!(w, "ML"), - ast::TyI64 => mywrite!(w, "MD") - } + ast::TyIs => write!(w, "is"), + ast::TyI8 => write!(w, "MB"), + ast::TyI16 => write!(w, "MW"), + ast::TyI32 => write!(w, "ML"), + ast::TyI64 => write!(w, "MD") + }; } ty::TyUint(t) => { match t { - ast::TyUs => mywrite!(w, "us"), - ast::TyU8 => mywrite!(w, "Mb"), - ast::TyU16 => mywrite!(w, "Mw"), - ast::TyU32 => mywrite!(w, "Ml"), - ast::TyU64 => mywrite!(w, "Md") - } + ast::TyUs => write!(w, "us"), + ast::TyU8 => write!(w, "Mb"), + ast::TyU16 => write!(w, "Mw"), + ast::TyU32 => write!(w, "Ml"), + ast::TyU64 => write!(w, "Md") + }; } ty::TyFloat(t) => { match t { - ast::TyF32 => mywrite!(w, "Mf"), - ast::TyF64 => mywrite!(w, "MF"), - } + ast::TyF32 => write!(w, "Mf"), + ast::TyF64 => write!(w, "MF"), + }; } ty::TyEnum(def, substs) => { - mywrite!(w, "t[{}|", (cx.ds)(def.did)); + write!(w, "t[{}|", (cx.ds)(def.did)); enc_substs(w, cx, substs); - mywrite!(w, "]"); + write!(w, "]"); } ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { - mywrite!(w, "x["); + write!(w, "x["); enc_trait_ref(w, cx, principal.0); enc_existential_bounds(w, cx, bounds); - mywrite!(w, "]"); + write!(w, "]"); } ty::TyTuple(ref ts) => { - mywrite!(w, "T["); + write!(w, "T["); for t in ts { enc_ty(w, cx, *t); } - mywrite!(w, "]"); + write!(w, "]"); } - ty::TyBox(typ) => { mywrite!(w, "~"); enc_ty(w, cx, typ); } - ty::TyRawPtr(mt) => { mywrite!(w, "*"); enc_mt(w, cx, mt); } + ty::TyBox(typ) => { write!(w, "~"); enc_ty(w, cx, typ); } + ty::TyRawPtr(mt) => { write!(w, "*"); enc_mt(w, cx, mt); } ty::TyRef(r, mt) => { - mywrite!(w, "&"); + write!(w, "&"); enc_region(w, cx, *r); enc_mt(w, cx, mt); } ty::TyArray(t, sz) => { - mywrite!(w, "V"); + write!(w, "V"); enc_ty(w, cx, t); - mywrite!(w, "/{}|", sz); + write!(w, "/{}|", sz); } ty::TySlice(t) => { - mywrite!(w, "V"); + write!(w, "V"); enc_ty(w, cx, t); - mywrite!(w, "/|"); + write!(w, "/|"); } ty::TyStr => { - mywrite!(w, "v"); + write!(w, "v"); } ty::TyBareFn(Some(def_id), f) => { - mywrite!(w, "F"); - mywrite!(w, "{}|", (cx.ds)(def_id)); + write!(w, "F"); + write!(w, "{}|", (cx.ds)(def_id)); enc_bare_fn_ty(w, cx, f); } ty::TyBareFn(None, f) => { - mywrite!(w, "G"); + write!(w, "G"); enc_bare_fn_ty(w, cx, f); } ty::TyInfer(_) => { cx.diag.bug("cannot encode inference variable types"); } ty::TyParam(ParamTy {space, idx, name}) => { - mywrite!(w, "p[{}|{}|{}]", idx, space.to_uint(), name) + write!(w, "p[{}|{}|{}]", idx, space.to_uint(), name); } ty::TyStruct(def, substs) => { - mywrite!(w, "a[{}|", (cx.ds)(def.did)); + write!(w, "a[{}|", (cx.ds)(def.did)); enc_substs(w, cx, substs); - mywrite!(w, "]"); + write!(w, "]"); } ty::TyClosure(def, ref substs) => { - mywrite!(w, "k[{}|", (cx.ds)(def)); + write!(w, "k[{}|", (cx.ds)(def)); enc_substs(w, cx, &substs.func_substs); for ty in &substs.upvar_tys { enc_ty(w, cx, ty); } - mywrite!(w, "."); - mywrite!(w, "]"); + write!(w, "."); + write!(w, "]"); } ty::TyProjection(ref data) => { - mywrite!(w, "P["); + write!(w, "P["); enc_trait_ref(w, cx, data.trait_ref); - mywrite!(w, "{}]", data.item_name); + write!(w, "{}]", data.item_name); } ty::TyError => { - mywrite!(w, "e"); + write!(w, "e"); } } - let end = w.mark_stable_position(); + let end = w.position(); let len = end - pos; - let buf: &mut [u8] = &mut [0; 16]; // vuint < 15 bytes - let mut abbrev = Cursor::new(buf); + let mut abbrev = Cursor::new(Vec::with_capacity(16)); abbrev.write_all(b"#"); - writer::write_vuint(&mut abbrev, pos as usize); + { + let start_position = abbrev.position() as usize; + let bytes_written = leb128::write_unsigned_leb128(abbrev.get_mut(), + start_position, + pos); + abbrev.set_position((start_position + bytes_written) as u64); + } cx.abbrevs.borrow_mut().insert(t, ty_abbrev { s: if abbrev.position() < len { @@ -180,101 +194,105 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) { // if the abbreviation is longer than the real type, // don't use #-notation. However, insert it here so // other won't have to `mark_stable_position` - w.writer.get_ref()[pos as usize..end as usize].to_owned() + w.get_ref()[pos as usize .. end as usize].to_owned() } }); } -fn enc_mutability(w: &mut Encoder, mt: hir::Mutability) { +fn enc_mutability(w: &mut Cursor>, mt: hir::Mutability) { match mt { hir::MutImmutable => (), - hir::MutMutable => mywrite!(w, "m"), - } + hir::MutMutable => { + write!(w, "m"); + } + }; } -fn enc_mt<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, +fn enc_mt<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, mt: ty::TypeAndMut<'tcx>) { enc_mutability(w, mt.mutbl); enc_ty(w, cx, mt.ty); } -fn enc_opt(w: &mut Encoder, t: Option, enc_f: F) where - F: FnOnce(&mut Encoder, T), +fn enc_opt(w: &mut Cursor>, t: Option, enc_f: F) where + F: FnOnce(&mut Cursor>, T), { match t { - None => mywrite!(w, "n"), + None => { + write!(w, "n"); + } Some(v) => { - mywrite!(w, "s"); + write!(w, "s"); enc_f(w, v); } } } -fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut Encoder, +fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, v: &VecPerParamSpace, mut op: F) where - F: FnMut(&mut Encoder, &ctxt<'a, 'tcx>, &T), + F: FnMut(&mut Cursor>, &ctxt<'a, 'tcx>, &T), { for &space in &subst::ParamSpace::all() { - mywrite!(w, "["); + write!(w, "["); for t in v.get_slice(space) { op(w, cx, t); } - mywrite!(w, "]"); + write!(w, "]"); } } -pub fn enc_substs<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, +pub fn enc_substs<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, substs: &subst::Substs<'tcx>) { enc_region_substs(w, cx, &substs.regions); enc_vec_per_param_space(w, cx, &substs.types, |w, cx, &ty| enc_ty(w, cx, ty)); } -fn enc_region_substs(w: &mut Encoder, cx: &ctxt, substs: &subst::RegionSubsts) { +fn enc_region_substs(w: &mut Cursor>, cx: &ctxt, substs: &subst::RegionSubsts) { match *substs { subst::ErasedRegions => { - mywrite!(w, "e"); + write!(w, "e"); } subst::NonerasedRegions(ref regions) => { - mywrite!(w, "n"); + write!(w, "n"); enc_vec_per_param_space(w, cx, regions, |w, cx, &r| enc_region(w, cx, r)); } } } -pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) { +pub fn enc_region(w: &mut Cursor>, cx: &ctxt, r: ty::Region) { match r { ty::ReLateBound(id, br) => { - mywrite!(w, "b[{}|", id.depth); + write!(w, "b[{}|", id.depth); enc_bound_region(w, cx, br); - mywrite!(w, "]"); + write!(w, "]"); } ty::ReEarlyBound(ref data) => { - mywrite!(w, "B[{}|{}|{}]", - data.space.to_uint(), - data.index, - data.name); + write!(w, "B[{}|{}|{}]", + data.space.to_uint(), + data.index, + data.name); } ty::ReFree(ref fr) => { - mywrite!(w, "f["); + write!(w, "f["); enc_scope(w, cx, fr.scope); - mywrite!(w, "|"); + write!(w, "|"); enc_bound_region(w, cx, fr.bound_region); - mywrite!(w, "]"); + write!(w, "]"); } ty::ReScope(scope) => { - mywrite!(w, "s"); + write!(w, "s"); enc_scope(w, cx, scope); - mywrite!(w, "|"); + write!(w, "|"); } ty::ReStatic => { - mywrite!(w, "t"); + write!(w, "t"); } ty::ReEmpty => { - mywrite!(w, "e"); + write!(w, "e"); } ty::ReVar(_) | ty::ReSkolemized(..) => { // these should not crop up after typeck @@ -283,107 +301,107 @@ pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) { } } -fn enc_scope(w: &mut Encoder, cx: &ctxt, scope: region::CodeExtent) { +fn enc_scope(w: &mut Cursor>, cx: &ctxt, scope: region::CodeExtent) { match cx.tcx.region_maps.code_extent_data(scope) { region::CodeExtentData::CallSiteScope { - fn_id, body_id } => mywrite!(w, "C[{}|{}]", fn_id, body_id), + fn_id, body_id } => write!(w, "C[{}|{}]", fn_id, body_id), region::CodeExtentData::ParameterScope { - fn_id, body_id } => mywrite!(w, "P[{}|{}]", fn_id, body_id), - region::CodeExtentData::Misc(node_id) => mywrite!(w, "M{}", node_id), + fn_id, body_id } => write!(w, "P[{}|{}]", fn_id, body_id), + region::CodeExtentData::Misc(node_id) => write!(w, "M{}", node_id), region::CodeExtentData::Remainder(region::BlockRemainder { - block: b, first_statement_index: i }) => mywrite!(w, "B[{}|{}]", b, i), - region::CodeExtentData::DestructionScope(node_id) => mywrite!(w, "D{}", node_id), - } + block: b, first_statement_index: i }) => write!(w, "B[{}|{}]", b, i), + region::CodeExtentData::DestructionScope(node_id) => write!(w, "D{}", node_id), + }; } -fn enc_bound_region(w: &mut Encoder, cx: &ctxt, br: ty::BoundRegion) { +fn enc_bound_region(w: &mut Cursor>, cx: &ctxt, br: ty::BoundRegion) { match br { ty::BrAnon(idx) => { - mywrite!(w, "a{}|", idx); + write!(w, "a{}|", idx); } ty::BrNamed(d, name) => { - mywrite!(w, "[{}|{}]", + write!(w, "[{}|{}]", (cx.ds)(d), name); } ty::BrFresh(id) => { - mywrite!(w, "f{}|", id); + write!(w, "f{}|", id); } ty::BrEnv => { - mywrite!(w, "e|"); + write!(w, "e|"); } } } -pub fn enc_trait_ref<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, +pub fn enc_trait_ref<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, s: ty::TraitRef<'tcx>) { - mywrite!(w, "{}|", (cx.ds)(s.def_id)); + write!(w, "{}|", (cx.ds)(s.def_id)); enc_substs(w, cx, s.substs); } -fn enc_unsafety(w: &mut Encoder, p: hir::Unsafety) { +fn enc_unsafety(w: &mut Cursor>, p: hir::Unsafety) { match p { - hir::Unsafety::Normal => mywrite!(w, "n"), - hir::Unsafety::Unsafe => mywrite!(w, "u"), - } + hir::Unsafety::Normal => write!(w, "n"), + hir::Unsafety::Unsafe => write!(w, "u"), + }; } -fn enc_abi(w: &mut Encoder, abi: Abi) { - mywrite!(w, "["); - mywrite!(w, "{}", abi.name()); - mywrite!(w, "]") +fn enc_abi(w: &mut Cursor>, abi: Abi) { + write!(w, "["); + write!(w, "{}", abi.name()); + write!(w, "]"); } -pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, +pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, ft: &ty::BareFnTy<'tcx>) { enc_unsafety(w, ft.unsafety); enc_abi(w, ft.abi); enc_fn_sig(w, cx, &ft.sig); } -pub fn enc_closure_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, +pub fn enc_closure_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, ft: &ty::ClosureTy<'tcx>) { enc_unsafety(w, ft.unsafety); enc_fn_sig(w, cx, &ft.sig); enc_abi(w, ft.abi); } -fn enc_fn_sig<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, +fn enc_fn_sig<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, fsig: &ty::PolyFnSig<'tcx>) { - mywrite!(w, "["); + write!(w, "["); for ty in &fsig.0.inputs { enc_ty(w, cx, *ty); } - mywrite!(w, "]"); + write!(w, "]"); if fsig.0.variadic { - mywrite!(w, "V"); + write!(w, "V"); } else { - mywrite!(w, "N"); + write!(w, "N"); } match fsig.0.output { ty::FnConverging(result_type) => { enc_ty(w, cx, result_type); } ty::FnDiverging => { - mywrite!(w, "z"); + write!(w, "z"); } } } -pub fn enc_builtin_bounds(w: &mut Encoder, _cx: &ctxt, bs: &ty::BuiltinBounds) { +pub fn enc_builtin_bounds(w: &mut Cursor>, _cx: &ctxt, bs: &ty::BuiltinBounds) { for bound in bs { match bound { - ty::BoundSend => mywrite!(w, "S"), - ty::BoundSized => mywrite!(w, "Z"), - ty::BoundCopy => mywrite!(w, "P"), - ty::BoundSync => mywrite!(w, "T"), - } + ty::BoundSend => write!(w, "S"), + ty::BoundSized => write!(w, "Z"), + ty::BoundCopy => write!(w, "P"), + ty::BoundSync => write!(w, "T"), + }; } - mywrite!(w, "."); + write!(w, "."); } -pub fn enc_existential_bounds<'a,'tcx>(w: &mut Encoder, +pub fn enc_existential_bounds<'a,'tcx>(w: &mut Cursor>, cx: &ctxt<'a,'tcx>, bs: &ty::ExistentialBounds<'tcx>) { enc_builtin_bounds(w, cx, &bs.builtin_bounds); @@ -391,90 +409,94 @@ pub fn enc_existential_bounds<'a,'tcx>(w: &mut Encoder, enc_region(w, cx, bs.region_bound); for tp in &bs.projection_bounds { - mywrite!(w, "P"); + write!(w, "P"); enc_projection_predicate(w, cx, &tp.0); } - mywrite!(w, "."); + write!(w, "."); } -pub fn enc_type_param_def<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, +pub fn enc_type_param_def<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, v: &ty::TypeParameterDef<'tcx>) { - mywrite!(w, "{}:{}|{}|{}|{}|", + write!(w, "{}:{}|{}|{}|{}|", v.name, (cx.ds)(v.def_id), v.space.to_uint(), v.index, (cx.ds)(v.default_def_id)); enc_opt(w, v.default, |w, t| enc_ty(w, cx, t)); enc_object_lifetime_default(w, cx, v.object_lifetime_default); } -pub fn enc_region_param_def(w: &mut Encoder, cx: &ctxt, +pub fn enc_region_param_def(w: &mut Cursor>, cx: &ctxt, v: &ty::RegionParameterDef) { - mywrite!(w, "{}:{}|{}|{}|", + write!(w, "{}:{}|{}|{}|", v.name, (cx.ds)(v.def_id), v.space.to_uint(), v.index); for &r in &v.bounds { - mywrite!(w, "R"); + write!(w, "R"); enc_region(w, cx, r); } - mywrite!(w, "."); + write!(w, "."); } -fn enc_object_lifetime_default<'a, 'tcx>(w: &mut Encoder, +fn enc_object_lifetime_default<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, default: ty::ObjectLifetimeDefault) { match default { - ty::ObjectLifetimeDefault::Ambiguous => mywrite!(w, "a"), - ty::ObjectLifetimeDefault::BaseDefault => mywrite!(w, "b"), + ty::ObjectLifetimeDefault::Ambiguous => { + write!(w, "a"); + } + ty::ObjectLifetimeDefault::BaseDefault => { + write!(w, "b"); + } ty::ObjectLifetimeDefault::Specific(r) => { - mywrite!(w, "s"); + write!(w, "s"); enc_region(w, cx, r); } } } -pub fn enc_predicate<'a, 'tcx>(w: &mut Encoder, +pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, p: &ty::Predicate<'tcx>) { match *p { ty::Predicate::Trait(ref trait_ref) => { - mywrite!(w, "t"); + write!(w, "t"); enc_trait_ref(w, cx, trait_ref.0.trait_ref); } ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => { - mywrite!(w, "e"); + write!(w, "e"); enc_ty(w, cx, a); enc_ty(w, cx, b); } ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => { - mywrite!(w, "r"); + write!(w, "r"); enc_region(w, cx, a); enc_region(w, cx, b); } ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => { - mywrite!(w, "o"); + write!(w, "o"); enc_ty(w, cx, a); enc_region(w, cx, b); } ty::Predicate::Projection(ty::Binder(ref data)) => { - mywrite!(w, "p"); - enc_projection_predicate(w, cx, data) + write!(w, "p"); + enc_projection_predicate(w, cx, data); } ty::Predicate::WellFormed(data) => { - mywrite!(w, "w"); + write!(w, "w"); enc_ty(w, cx, data); } ty::Predicate::ObjectSafe(trait_def_id) => { - mywrite!(w, "O{}|", (cx.ds)(trait_def_id)); + write!(w, "O{}|", (cx.ds)(trait_def_id)); } } } -fn enc_projection_predicate<'a, 'tcx>(w: &mut Encoder, +fn enc_projection_predicate<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, data: &ty::ProjectionPredicate<'tcx>) { enc_trait_ref(w, cx, data.projection_ty.trait_ref); - mywrite!(w, "{}|", data.projection_ty.item_name); + write!(w, "{}|", data.projection_ty.item_name); enc_ty(w, cx, data.ty); } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 996e72bdad325..4197f80cb5ea3 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -44,6 +44,7 @@ use middle::pat_util::simple_name; use middle::subst::Substs; use middle::ty::{self, Ty, HasTypeFlags}; use rustc::front::map as hir_map; +use rustc::util::common::time; use rustc_mir::mir_map::MirMap; use session::config::{self, NoDebugInfo, FullDebugInfo}; use session::Session; @@ -3057,7 +3058,9 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>, let reachable_symbol_ids = filter_reachable_ids(&shared_ccx); // Translate the metadata. - let metadata = write_metadata(&shared_ccx, krate, &reachable_symbol_ids, mir_map); + let metadata = time(tcx.sess.time_passes(), "write metadata", || { + write_metadata(&shared_ccx, krate, &reachable_symbol_ids, mir_map) + }); if shared_ccx.sess().trans_stats() { let stats = shared_ccx.stats(); diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 18659cb2e78f1..19236f2cd98a8 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -164,18 +164,15 @@ impl Eq for Span {} impl Encodable for Span { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - // Encode spans as a single u64 in order to cut down on tagging overhead - // added by the RBML metadata encoding. The should be solved differently - // altogether some time (FIXME #21482) - s.emit_u64( (self.lo.0 as u64) | ((self.hi.0 as u64) << 32) ) + try!(s.emit_u32(self.lo.0)); + s.emit_u32(self.hi.0) } } impl Decodable for Span { fn decode(d: &mut D) -> Result { - let lo_hi: u64 = try! { d.read_u64() }; - let lo = BytePos(lo_hi as u32); - let hi = BytePos((lo_hi >> 32) as u32); + let lo = BytePos(try! { d.read_u32() }); + let hi = BytePos(try! { d.read_u32() }); Ok(mk_sp(lo, hi)) } }