pub fn encode_opaque(&self, encoder: &mut Encoder) -> EncodeResult {
let bytes: [u8; 16] = unsafe { mem::transmute([self.0.to_le(), self.1.to_le()]) };
- encoder.emit_raw_bytes(&bytes)
+ encoder.emit_raw_bytes(&bytes);
+ Ok(())
}
pub fn decode_opaque<'a>(decoder: &mut Decoder<'a>) -> Result<Fingerprint, String> {
impl serialize::UseSpecializedDecodable for Fingerprint { }
-impl<'a> serialize::SpecializedEncoder<Fingerprint> for serialize::opaque::Encoder<'a> {
+impl serialize::SpecializedEncoder<Fingerprint> for serialize::opaque::Encoder {
fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
f.encode_opaque(self)
}
fn position(&self) -> usize;
}
-impl<'buf> TyEncoder for opaque::Encoder<'buf> {
+impl TyEncoder for opaque::Encoder {
#[inline]
fn position(&self) -> usize {
self.position()
}
impl<'enc, 'a, 'tcx> SpecializedEncoder<Fingerprint>
-for CacheEncoder<'enc, 'a, 'tcx, opaque::Encoder<'enc>>
+for CacheEncoder<'enc, 'a, 'tcx, opaque::Encoder>
{
fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
f.encode_opaque(&mut self.encoder)
impl UseSpecializedEncodable for IntEncodedWithFixedSize {}
impl UseSpecializedDecodable for IntEncodedWithFixedSize {}
-impl<'enc> SpecializedEncoder<IntEncodedWithFixedSize> for opaque::Encoder<'enc> {
+impl SpecializedEncoder<IntEncodedWithFixedSize> for opaque::Encoder {
fn specialized_encode(&mut self, x: &IntEncodedWithFixedSize) -> Result<(), Self::Error> {
let start_pos = self.position();
for i in 0 .. IntEncodedWithFixedSize::ENCODED_SIZE {
}
fn u32(&mut self, val: u32) {
- let at = self.data.len();
- leb128::write_u32_leb128(&mut self.data, at, val);
+ leb128::write_u32_leb128(&mut self.data, val);
}
fn byte(&mut self, val: u8) {
use std::env;
use rustc::session::config::nightly_options;
+use rustc_serialize::opaque::Encoder;
/// The first few bytes of files generated by incremental compilation
const FILE_MAGIC: &'static [u8] = b"RSIC";
/// the git commit hash.
const RUSTC_VERSION: Option<&'static str> = option_env!("CFG_VERSION");
-pub fn write_file_header<W: io::Write>(stream: &mut W) -> io::Result<()> {
- stream.write_all(FILE_MAGIC)?;
- stream.write_all(&[(HEADER_FORMAT_VERSION >> 0) as u8,
- (HEADER_FORMAT_VERSION >> 8) as u8])?;
+pub fn write_file_header(stream: &mut Encoder) {
+ stream.emit_raw_bytes(FILE_MAGIC);
+ stream.emit_raw_bytes(&[(HEADER_FORMAT_VERSION >> 0) as u8,
+ (HEADER_FORMAT_VERSION >> 8) as u8]);
let rustc_version = rustc_version();
assert_eq!(rustc_version.len(), (rustc_version.len() as u8) as usize);
- stream.write_all(&[rustc_version.len() as u8])?;
- stream.write_all(rustc_version.as_bytes())?;
-
- Ok(())
+ stream.emit_raw_bytes(&[rustc_version.len() as u8]);
+ stream.emit_raw_bytes(rustc_version.as_bytes());
}
/// Reads the contents of a file with a file header as defined in this module.
use rustc_data_structures::sync::join;
use rustc_serialize::Encodable as RustcEncodable;
use rustc_serialize::opaque::Encoder;
-use std::io::{self, Cursor};
use std::fs;
use std::path::PathBuf;
}
fn save_in<F>(sess: &Session, path_buf: PathBuf, encode: F)
- where F: FnOnce(&mut Encoder) -> io::Result<()>
+ where F: FnOnce(&mut Encoder)
{
debug!("save: storing data in {}", path_buf.display());
}
// generate the data in a memory buffer
- let mut wr = Cursor::new(Vec::new());
- file_format::write_file_header(&mut wr).unwrap();
- match encode(&mut Encoder::new(&mut wr)) {
- Ok(()) => {}
- Err(err) => {
- sess.err(&format!("could not encode dep-graph to `{}`: {}",
- path_buf.display(),
- err));
- return;
- }
- }
+ let mut encoder = Encoder::new(Vec::new());
+ file_format::write_file_header(&mut encoder);
+ encode(&mut encoder);
// write the data out
- let data = wr.into_inner();
+ let data = encoder.into_inner();
match fs::write(&path_buf, data) {
Ok(_) => {
debug!("save: data written to disk successfully");
}
fn encode_dep_graph(tcx: TyCtxt,
- encoder: &mut Encoder)
- -> io::Result<()> {
+ encoder: &mut Encoder) {
// First encode the commandline arguments hash
- tcx.sess.opts.dep_tracking_hash().encode(encoder)?;
+ tcx.sess.opts.dep_tracking_hash().encode(encoder).unwrap();
// Encode the graph data.
let serialized_graph = time(tcx.sess, "getting serialized graph", || {
}
time(tcx.sess, "encoding serialized graph", || {
- serialized_graph.encode(encoder)
- })?;
-
- Ok(())
+ serialized_graph.encode(encoder).unwrap();
+ });
}
fn encode_work_product_index(work_products: &FxHashMap<WorkProductId, WorkProduct>,
- encoder: &mut Encoder) -> io::Result<()> {
+ encoder: &mut Encoder) {
let serialized_products: Vec<_> = work_products
.iter()
.map(|(id, work_product)| {
})
.collect();
- serialized_products.encode(encoder)
+ serialized_products.encode(encoder).unwrap();
}
fn encode_query_cache(tcx: TyCtxt,
- encoder: &mut Encoder)
- -> io::Result<()> {
+ encoder: &mut Encoder) {
time(tcx.sess, "serialize query result cache", || {
- tcx.serialize_query_result_cache(encoder)
+ tcx.serialize_query_result_cache(encoder).unwrap();
})
}
use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
use std::hash::Hash;
-use std::io::prelude::*;
-use std::io::Cursor;
use std::path::Path;
use rustc_data_structures::sync::Lrc;
use std::u32;
use rustc::hir::intravisit;
pub struct EncodeContext<'a, 'tcx: 'a> {
- opaque: opaque::Encoder<'a>,
+ opaque: opaque::Encoder,
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &'a LinkMeta,
}
impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
- type Error = <opaque::Encoder<'a> as Encoder>::Error;
+ type Error = <opaque::Encoder as Encoder>::Error;
fn emit_nil(&mut self) -> Result<(), Self::Error> {
Ok(())
// Index the items
i = self.position();
- let index = items.write_index(&mut self.opaque.cursor);
+ let index = items.write_index(&mut self.opaque);
let index_bytes = self.position() - i;
let attrs = tcx.hir.krate_attrs();
if self.tcx.sess.meta_stats() {
let mut zero_bytes = 0;
- for e in self.opaque.cursor.get_ref() {
+ for e in self.opaque.data.iter() {
if *e == 0 {
zero_bytes += 1;
}
link_meta: &LinkMeta)
-> EncodedMetadata
{
- let mut cursor = Cursor::new(vec![]);
- cursor.write_all(METADATA_HEADER).unwrap();
+ let mut encoder = opaque::Encoder::new(vec![]);
+ encoder.emit_raw_bytes(METADATA_HEADER);
// Will be filled with the root position after encoding everything.
- cursor.write_all(&[0, 0, 0, 0]).unwrap();
+ encoder.emit_raw_bytes(&[0, 0, 0, 0]);
- let root = {
+ let (root, mut result) = {
let mut ecx = EncodeContext {
- opaque: opaque::Encoder::new(&mut cursor),
+ opaque: encoder,
tcx,
link_meta,
lazy_state: LazyState::NoNode,
// Encode all the entries and extra information in the crate,
// culminating in the `CrateRoot` which points to all of it.
- ecx.encode_crate_root()
+ let root = ecx.encode_crate_root();
+ (root, ecx.opaque.into_inner())
};
- let mut result = cursor.into_inner();
// Encode the root position.
let header = METADATA_HEADER.len();
use schema::*;
use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace};
-use std::io::{Cursor, Write};
+use rustc_serialize::opaque::Encoder;
use std::slice;
use std::u32;
self.positions[space_index][array_index] = position.to_le();
}
- pub fn write_index(&self, buf: &mut Cursor<Vec<u8>>) -> LazySeq<Index> {
+ pub fn write_index(&self, buf: &mut Encoder) -> LazySeq<Index> {
let pos = buf.position();
// First we write the length of the lower range ...
- buf.write_all(words_to_bytes(&[(self.positions[0].len() as u32).to_le()])).unwrap();
+ buf.emit_raw_bytes(words_to_bytes(&[(self.positions[0].len() as u32).to_le()]));
// ... then the values in the lower range ...
- buf.write_all(words_to_bytes(&self.positions[0][..])).unwrap();
+ buf.emit_raw_bytes(words_to_bytes(&self.positions[0][..]));
// ... then the values in the higher range.
- buf.write_all(words_to_bytes(&self.positions[1][..])).unwrap();
+ buf.emit_raw_bytes(words_to_bytes(&self.positions[1][..]));
LazySeq::with_position_and_length(pos as usize,
self.positions[0].len() + self.positions[1].len() + 1)
}
// except according to those terms.
#[inline]
-pub fn write_to_vec(vec: &mut Vec<u8>, position: usize, byte: u8) {
- if position == vec.len() {
- vec.push(byte);
- } else {
- vec[position] = byte;
- }
+pub fn write_to_vec(vec: &mut Vec<u8>, byte: u8) {
+ vec.push(byte);
}
#[cfg(target_pointer_width = "32")]
macro_rules! impl_write_unsigned_leb128 {
($fn_name:ident, $int_ty:ident) => (
#[inline]
- pub fn $fn_name(out: &mut Vec<u8>, start_position: usize, mut value: $int_ty) -> usize {
- let mut position = start_position;
+ pub fn $fn_name(out: &mut Vec<u8>, mut value: $int_ty) {
for _ in 0 .. leb128_size!($int_ty) {
let mut byte = (value & 0x7F) as u8;
value >>= 7;
byte |= 0x80;
}
- write_to_vec(out, position, byte);
- position += 1;
+ write_to_vec(out, byte);
if value == 0 {
break;
}
}
-
- position - start_position
}
)
}
/// The callback `write` is called once for each position
/// that is to be written to with the byte to be encoded
/// at that position.
-pub fn write_signed_leb128_to<W>(mut value: i128, mut write: W) -> usize
- where W: FnMut(usize, u8)
+pub fn write_signed_leb128_to<W>(mut value: i128, mut write: W)
+ where W: FnMut(u8)
{
- let mut position = 0;
-
loop {
let mut byte = (value as u8) & 0x7f;
value >>= 7;
byte |= 0x80; // Mark this byte to show that more bytes will follow.
}
- write(position, byte);
- position += 1;
+ write(byte);
if !more {
break;
}
}
- position
}
-pub fn write_signed_leb128(out: &mut Vec<u8>, start_position: usize, value: i128) -> usize {
- write_signed_leb128_to(value, |i, v| write_to_vec(out, start_position+i, v))
+pub fn write_signed_leb128(out: &mut Vec<u8>, value: i128) {
+ write_signed_leb128_to(value, |v| write_to_vec(out, v))
}
#[inline]
let mut stream = Vec::new();
for x in 0..62 {
- let pos = stream.len();
- let bytes_written = $write_fn_name(&mut stream, pos, (3u64 << x) as $int_ty);
- assert_eq!(stream.len(), pos + bytes_written);
+ $write_fn_name(&mut stream, (3u64 << x) as $int_ty);
}
let mut position = 0;
let values: Vec<_> = (-500..500).map(|i| i * 0x12345789ABCDEF).collect();
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);
+ write_signed_leb128(&mut stream, x);
}
let mut pos = 0;
for &x in &values {
#![feature(box_syntax)]
#![feature(core_intrinsics)]
#![feature(specialization)]
+#![feature(never_type)]
#![cfg_attr(test, feature(test))]
pub use self::serialize::{Decoder, Encoder, Decodable, Encodable};
use leb128::{self, read_signed_leb128, write_signed_leb128};
use std::borrow::Cow;
-use std::io::{self, Write};
use serialize;
// -----------------------------------------------------------------------------
// Encoder
// -----------------------------------------------------------------------------
-pub type EncodeResult = io::Result<()>;
+pub type EncodeResult = Result<(), !>;
-pub struct Encoder<'a> {
- pub cursor: &'a mut io::Cursor<Vec<u8>>,
+pub struct Encoder {
+ pub data: Vec<u8>,
}
-impl<'a> Encoder<'a> {
- pub fn new(cursor: &'a mut io::Cursor<Vec<u8>>) -> Encoder<'a> {
- Encoder { cursor: cursor }
+impl Encoder {
+ pub fn new(data: Vec<u8>) -> Encoder {
+ Encoder { data }
}
- pub fn emit_raw_bytes(&mut self, s: &[u8]) -> EncodeResult {
- self.cursor.write_all(s)
+ pub fn into_inner(self) -> Vec<u8> {
+ self.data
}
-}
+ pub fn emit_raw_bytes(&mut self, s: &[u8]) {
+ self.data.extend_from_slice(s);
+ }
+}
macro_rules! write_uleb128 {
($enc:expr, $value:expr, $fun:ident) => {{
- let pos = $enc.cursor.position() as usize;
- let bytes_written = leb128::$fun($enc.cursor.get_mut(), pos, $value);
- $enc.cursor.set_position((pos + bytes_written) as u64);
+ leb128::$fun(&mut $enc.data, $value);
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 i128);
- $enc.cursor.set_position((pos + bytes_written) as u64);
+ write_signed_leb128(&mut $enc.data, $value as i128);
Ok(())
}}
}
-impl<'a> serialize::Encoder for Encoder<'a> {
- type Error = io::Error;
+impl serialize::Encoder for Encoder {
+ type Error = !;
#[inline]
fn emit_nil(&mut self) -> EncodeResult {
#[inline]
fn emit_u8(&mut self, v: u8) -> EncodeResult {
- let pos = self.cursor.position() as usize;
- leb128::write_to_vec(self.cursor.get_mut(), pos, v);
- self.cursor.set_position((pos + 1) as u64);
+ self.data.push(v);
Ok(())
}
#[inline]
fn emit_str(&mut self, v: &str) -> EncodeResult {
self.emit_usize(v.len())?;
- let _ = self.cursor.write_all(v.as_bytes());
+ self.emit_raw_bytes(v.as_bytes());
Ok(())
}
}
-impl<'a> Encoder<'a> {
+impl Encoder {
#[inline]
pub fn position(&self) -> usize {
- self.cursor.position() as usize
+ self.data.len()
}
}
#[cfg(test)]
mod tests {
use serialize::{Encodable, Decodable};
- use std::io::Cursor;
use std::fmt::Debug;
use super::{Encoder, Decoder};
fn check_round_trip<T: Encodable + Decodable + PartialEq + Debug>(values: Vec<T>) {
- let mut cursor = Cursor::new(Vec::new());
+ let mut encoder = Encoder::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 data = encoder.into_inner();
let mut decoder = Decoder::new(&data[..], 0);
for value in values {
fn encode_json<T: Encodable>(val: &T, wr: &mut Cursor<Vec<u8>>) {
write!(wr, "{}", json::as_json(val));
}
-fn encode_opaque<T: Encodable>(val: &T, wr: &mut Cursor<Vec<u8>>) {
+fn encode_opaque<T: Encodable>(val: &T, wr: Vec<u8>) {
let mut encoder = opaque::Encoder::new(wr);
val.encode(&mut encoder);
}
pub fn main() {
let target = Foo{baz: false,};
- let mut wr = Cursor::new(Vec::new());
let proto = WireProtocol::JSON;
match proto {
- WireProtocol::JSON => encode_json(&target, &mut wr),
- WireProtocol::Opaque => encode_opaque(&target, &mut wr)
+ WireProtocol::JSON => encode_json(&target, &mut Cursor::new(Vec::new())),
+ WireProtocol::Opaque => encode_opaque(&target, Vec::new())
}
}