Remove std::io from ebml

This commit is contained in:
Alex Crichton 2013-10-21 17:11:42 -07:00
parent 620ab3853a
commit c4907cfd14
7 changed files with 393 additions and 379 deletions

View File

@ -96,17 +96,8 @@ pub mod reader {
use std::cast::transmute;
use std::int;
use std::io;
use std::option::{None, Option, Some};
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
use std::ptr::offset;
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
use std::unstable::intrinsics::bswap32;
// ebml reading
struct Res {
@ -144,6 +135,9 @@ pub mod reader {
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
pub fn vuint_at(data: &[u8], start: uint) -> Res {
use std::ptr::offset;
use std::unstable::intrinsics::bswap32;
if data.len() - start < 4 {
return vuint_at_slow(data, start);
}
@ -178,8 +172,7 @@ pub mod reader {
}
}
#[cfg(target_arch = "arm")]
#[cfg(target_arch = "mips")]
#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"))]
pub fn vuint_at(data: &[u8], start: uint) -> Res {
vuint_at_slow(data, start)
}
@ -265,17 +258,17 @@ pub mod reader {
pub fn doc_as_u16(d: Doc) -> u16 {
assert_eq!(d.end, d.start + 2u);
io::u64_from_be_bytes(*d.data, d.start, 2u) as u16
::std::io::u64_from_be_bytes(*d.data, d.start, 2u) as u16
}
pub fn doc_as_u32(d: Doc) -> u32 {
assert_eq!(d.end, d.start + 4u);
io::u64_from_be_bytes(*d.data, d.start, 4u) as u32
::std::io::u64_from_be_bytes(*d.data, d.start, 4u) as u32
}
pub fn doc_as_u64(d: Doc) -> u64 {
assert_eq!(d.end, d.start + 8u);
io::u64_from_be_bytes(*d.data, d.start, 8u)
::std::io::u64_from_be_bytes(*d.data, d.start, 8u)
}
pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
@ -614,11 +607,14 @@ pub mod writer {
use std::cast;
use std::clone::Clone;
use std::io;
use std::rt::io;
use std::rt::io::{Writer, Seek};
use std::rt::io::mem::MemWriter;
// ebml writing
pub struct Encoder {
writer: @io::Writer,
// FIXME(#5665): this should take a trait object
writer: @mut MemWriter,
priv size_positions: ~[uint],
}
@ -631,7 +627,7 @@ pub mod writer {
}
}
fn write_sized_vuint(w: @io::Writer, n: uint, size: uint) {
fn write_sized_vuint(w: @mut MemWriter, n: uint, size: uint) {
match size {
1u => w.write(&[0x80u8 | (n as u8)]),
2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]),
@ -643,7 +639,7 @@ pub mod writer {
};
}
fn write_vuint(w: @io::Writer, n: uint) {
fn write_vuint(w: @mut MemWriter, n: uint) {
if n < 0x7f_u { write_sized_vuint(w, n, 1u); return; }
if n < 0x4000_u { write_sized_vuint(w, n, 2u); return; }
if n < 0x200000_u { write_sized_vuint(w, n, 3u); return; }
@ -651,7 +647,7 @@ pub mod writer {
fail!("vint to write too big: {}", n);
}
pub fn Encoder(w: @io::Writer) -> Encoder {
pub fn Encoder(w: @mut MemWriter) -> Encoder {
let size_positions: ~[uint] = ~[];
Encoder {
writer: w,
@ -668,7 +664,7 @@ pub mod writer {
write_vuint(self.writer, tag_id);
// Write a placeholder four-byte size.
self.size_positions.push(self.writer.tell());
self.size_positions.push(self.writer.tell() as uint);
let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8];
self.writer.write(zeroes);
}
@ -676,10 +672,10 @@ pub mod writer {
pub fn end_tag(&mut self) {
let last_size_pos = self.size_positions.pop();
let cur_pos = self.writer.tell();
self.writer.seek(last_size_pos as int, io::SeekSet);
let size = (cur_pos - last_size_pos - 4u);
write_sized_vuint(self.writer, size, 4u);
self.writer.seek(cur_pos as int, io::SeekSet);
self.writer.seek(last_size_pos as i64, io::SeekSet);
let size = (cur_pos as uint - last_size_pos - 4);
write_sized_vuint(self.writer, size as uint, 4u);
self.writer.seek(cur_pos as i64, io::SeekSet);
debug!("End tag (size = {})", size);
}
@ -697,19 +693,19 @@ pub mod writer {
}
pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) {
do io::u64_to_be_bytes(v, 8u) |v| {
do ::std::io::u64_to_be_bytes(v, 8u) |v| {
self.wr_tagged_bytes(tag_id, v);
}
}
pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) {
do io::u64_to_be_bytes(v as u64, 4u) |v| {
do ::std::io::u64_to_be_bytes(v as u64, 4u) |v| {
self.wr_tagged_bytes(tag_id, v);
}
}
pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) {
do io::u64_to_be_bytes(v as u64, 2u) |v| {
do ::std::io::u64_to_be_bytes(v as u64, 2u) |v| {
self.wr_tagged_bytes(tag_id, v);
}
}
@ -719,19 +715,19 @@ pub mod writer {
}
pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) {
do io::u64_to_be_bytes(v as u64, 8u) |v| {
do ::std::io::u64_to_be_bytes(v as u64, 8u) |v| {
self.wr_tagged_bytes(tag_id, v);
}
}
pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) {
do io::u64_to_be_bytes(v as u64, 4u) |v| {
do ::std::io::u64_to_be_bytes(v as u64, 4u) |v| {
self.wr_tagged_bytes(tag_id, v);
}
}
pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) {
do io::u64_to_be_bytes(v as u64, 2u) |v| {
do ::std::io::u64_to_be_bytes(v as u64, 2u) |v| {
self.wr_tagged_bytes(tag_id, v);
}
}
@ -963,18 +959,18 @@ mod tests {
use serialize::Encodable;
use serialize;
use std::io;
use std::rt::io::Decorator;
use std::rt::io::mem::MemWriter;
use std::option::{None, Option, Some};
#[test]
fn test_option_int() {
fn test_v(v: Option<int>) {
debug!("v == {:?}", v);
let bytes = do io::with_bytes_writer |wr| {
let mut ebml_w = writer::Encoder(wr);
v.encode(&mut ebml_w)
};
let ebml_doc = reader::Doc(@bytes);
let wr = @mut MemWriter::new();
let mut ebml_w = writer::Encoder(wr);
v.encode(&mut ebml_w);
let ebml_doc = reader::Doc(@wr.inner_ref().to_owned());
let mut deser = reader::Decoder(ebml_doc);
let v1 = serialize::Decodable::decode(&mut deser);
debug!("v1 == {:?}", v1);

View File

@ -522,6 +522,8 @@ mod test {
use std::str;
use std::rand;
use std::num::Zero;
use std::rt::io::Decorator;
use std::rt::io::mem::MemWriter;
#[test]
fn test_new_nil() {
@ -795,10 +797,10 @@ mod test {
use serialize::{Encodable, Decodable};
let u = Uuid::new_v4();
let bytes = do std::io::with_bytes_writer |wr| {
u.encode(&mut ebml::writer::Encoder(wr));
};
let u2 = Decodable::decode(&mut ebml::reader::Decoder(ebml::reader::Doc(@bytes)));
let wr = @mut MemWriter::new();
u.encode(&mut ebml::writer::Encoder(wr));
let doc = ebml::reader::Doc(@wr.inner_ref().to_owned());
let u2 = Decodable::decode(&mut ebml::reader::Decoder(doc));
assert_eq!(u, u2);
}
}

View File

@ -22,12 +22,16 @@ use middle::typeck;
use middle;
use std::hashmap::{HashMap, HashSet};
use std::io;
use std::rt::io::extensions::WriterByteConversions;
use std::rt::io::{Writer, Seek, Decorator};
use std::rt::io::mem::MemWriter;
use std::str;
use std::vec;
use extra::flate;
use extra::serialize::Encodable;
use extra;
use syntax::abi::AbiSet;
use syntax::ast::*;
use syntax::ast;
@ -68,17 +72,17 @@ pub struct EncodeParams<'self> {
}
struct Stats {
inline_bytes: uint,
attr_bytes: uint,
dep_bytes: uint,
lang_item_bytes: uint,
link_args_bytes: uint,
impl_bytes: uint,
misc_bytes: uint,
item_bytes: uint,
index_bytes: uint,
zero_bytes: uint,
total_bytes: uint,
inline_bytes: u64,
attr_bytes: u64,
dep_bytes: u64,
lang_item_bytes: u64,
link_args_bytes: u64,
impl_bytes: u64,
misc_bytes: u64,
item_bytes: u64,
index_bytes: u64,
zero_bytes: u64,
total_bytes: u64,
n_inlines: uint
}
@ -133,7 +137,7 @@ fn encode_region_param(ecx: &EncodeContext,
#[deriving(Clone)]
struct entry<T> {
val: T,
pos: uint
pos: u64
}
fn add_to_index(ebml_w: &mut writer::Encoder,
@ -1395,10 +1399,9 @@ fn create_index<T:Clone + Hash + IterBytes + 'static>(
fn encode_index<T:'static>(
ebml_w: &mut writer::Encoder,
buckets: ~[@~[entry<T>]],
write_fn: &fn(@io::Writer, &T)) {
let writer = ebml_w.writer;
write_fn: &fn(@mut MemWriter, &T)) {
ebml_w.start_tag(tag_index);
let mut bucket_locs: ~[uint] = ~[];
let mut bucket_locs = ~[];
ebml_w.start_tag(tag_index_buckets);
for bucket in buckets.iter() {
bucket_locs.push(ebml_w.writer.tell());
@ -1406,8 +1409,11 @@ fn encode_index<T:'static>(
for elt in (**bucket).iter() {
ebml_w.start_tag(tag_index_buckets_bucket_elt);
assert!(elt.pos < 0xffff_ffff);
writer.write_be_u32(elt.pos as u32);
write_fn(writer, &elt.val);
{
let wr: &mut MemWriter = ebml_w.writer;
wr.write_be_u32_(elt.pos as u32);
}
write_fn(ebml_w.writer, &elt.val);
ebml_w.end_tag();
}
ebml_w.end_tag();
@ -1416,19 +1422,21 @@ fn encode_index<T:'static>(
ebml_w.start_tag(tag_index_table);
for pos in bucket_locs.iter() {
assert!(*pos < 0xffff_ffff);
writer.write_be_u32(*pos as u32);
let wr: &mut MemWriter = ebml_w.writer;
wr.write_be_u32_(*pos as u32);
}
ebml_w.end_tag();
ebml_w.end_tag();
}
fn write_str(writer: @io::Writer, s: ~str) {
writer.write_str(s);
fn write_str(writer: @mut MemWriter, s: ~str) {
writer.write(s.as_bytes());
}
fn write_i64(writer: @io::Writer, &n: &i64) {
fn write_i64(writer: @mut MemWriter, &n: &i64) {
let wr: &mut MemWriter = writer;
assert!(n < 0x7fff_ffff);
writer.write_be_u32(n as u32);
wr.write_be_u32_(n as u32);
}
fn encode_meta_item(ebml_w: &mut writer::Encoder, mi: @MetaItem) {
@ -1581,11 +1589,17 @@ fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
ebml_w.start_tag(tag_lang_items_item);
ebml_w.start_tag(tag_lang_items_item_id);
ebml_w.writer.write_be_u32(i as u32);
{
let wr: &mut MemWriter = ebml_w.writer;
wr.write_be_u32_(i as u32);
}
ebml_w.end_tag(); // tag_lang_items_item_id
ebml_w.start_tag(tag_lang_items_item_node_id);
ebml_w.writer.write_be_u32(id.node as u32);
{
let wr: &mut MemWriter = ebml_w.writer;
wr.write_be_u32_(id.node as u32);
}
ebml_w.end_tag(); // tag_lang_items_item_node_id
ebml_w.end_tag(); // tag_lang_items_item
@ -1602,7 +1616,7 @@ fn encode_link_args(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
let link_args = cstore::get_used_link_args(ecx.cstore);
for link_arg in link_args.iter() {
ebml_w.start_tag(tag_link_args_arg);
ebml_w.writer.write_str(link_arg.to_str());
ebml_w.writer.write(link_arg.as_bytes());
ebml_w.end_tag();
}
@ -1720,7 +1734,7 @@ pub static metadata_encoding_version : &'static [u8] =
0, 0, 0, 1 ];
pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
let wr = @io::BytesWriter::new();
let wr = @mut MemWriter::new();
let stats = Stats {
inline_bytes: 0,
attr_bytes: 0,
@ -1765,55 +1779,55 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
reachable: reachable,
};
let mut ebml_w = writer::Encoder(wr as @io::Writer);
let mut ebml_w = writer::Encoder(wr);
encode_hash(&mut ebml_w, ecx.link_meta.extras_hash);
let mut i = *wr.pos;
let mut i = wr.tell();
let crate_attrs = synthesize_crate_attrs(&ecx, crate);
encode_attributes(&mut ebml_w, crate_attrs);
ecx.stats.attr_bytes = *wr.pos - i;
ecx.stats.attr_bytes = wr.tell() - i;
i = *wr.pos;
i = wr.tell();
encode_crate_deps(&ecx, &mut ebml_w, ecx.cstore);
ecx.stats.dep_bytes = *wr.pos - i;
ecx.stats.dep_bytes = wr.tell() - i;
// Encode the language items.
i = *wr.pos;
i = wr.tell();
encode_lang_items(&ecx, &mut ebml_w);
ecx.stats.lang_item_bytes = *wr.pos - i;
ecx.stats.lang_item_bytes = wr.tell() - i;
// Encode the link args.
i = *wr.pos;
i = wr.tell();
encode_link_args(&ecx, &mut ebml_w);
ecx.stats.link_args_bytes = *wr.pos - i;
ecx.stats.link_args_bytes = wr.tell() - i;
// Encode the def IDs of impls, for coherence checking.
i = *wr.pos;
i = wr.tell();
encode_impls(&ecx, crate, &mut ebml_w);
ecx.stats.impl_bytes = *wr.pos - i;
ecx.stats.impl_bytes = wr.tell() - i;
// Encode miscellaneous info.
i = *wr.pos;
i = wr.tell();
encode_misc_info(&ecx, crate, &mut ebml_w);
ecx.stats.misc_bytes = *wr.pos - i;
ecx.stats.misc_bytes = wr.tell() - i;
// Encode and index the items.
ebml_w.start_tag(tag_items);
i = *wr.pos;
i = wr.tell();
let items_index = encode_info_for_items(&ecx, &mut ebml_w, crate);
ecx.stats.item_bytes = *wr.pos - i;
ecx.stats.item_bytes = wr.tell() - i;
i = *wr.pos;
i = wr.tell();
let items_buckets = create_index(items_index);
encode_index(&mut ebml_w, items_buckets, write_i64);
ecx.stats.index_bytes = *wr.pos - i;
ecx.stats.index_bytes = wr.tell() - i;
ebml_w.end_tag();
ecx.stats.total_bytes = *wr.pos;
ecx.stats.total_bytes = wr.tell();
if (tcx.sess.meta_stats()) {
for e in wr.bytes.iter() {
for e in wr.inner_ref().iter() {
if *e == 0 {
ecx.stats.zero_bytes += 1;
}
@ -1837,7 +1851,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
// remaining % 4 bytes.
wr.write(&[0u8, 0u8, 0u8, 0u8]);
let writer_bytes: &mut ~[u8] = wr.bytes;
let writer_bytes: &mut ~[u8] = wr.inner_mut_ref();
metadata_encoding_version.to_owned() +
flate::deflate_bytes(*writer_bytes)
@ -1850,7 +1864,7 @@ pub fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> ~str {
ds: def_to_str,
tcx: tcx,
abbrevs: tyencode::ac_no_abbrevs};
do io::with_str_writer |wr| {
tyencode::enc_ty(wr, cx, t);
}
let wr = @mut MemWriter::new();
tyencode::enc_ty(wr, cx, t);
str::from_utf8(*wr.inner_ref())
}

View File

@ -10,19 +10,26 @@
// Type encoding
use std::hashmap::HashMap;
use std::rt::io;
use std::rt::io::{Decorator, Writer, Seek};
use std::rt::io::mem::MemWriter;
use std::str;
use std::fmt;
use middle::ty::param_ty;
use middle::ty;
use std::hashmap::HashMap;
use std::io::WriterUtil;
use std::io;
use syntax::abi::AbiSet;
use syntax::ast;
use syntax::ast::*;
use syntax::diagnostic::span_handler;
use syntax::print::pprust::*;
macro_rules! mywrite( ($wr:expr, $($arg:tt)*) => (
format_args!(|a| { mywrite($wr, a) }, $($arg)*)
) )
pub struct ctxt {
diag: @mut span_handler,
// Def -> str Callback:
@ -46,6 +53,10 @@ pub enum abbrev_ctxt {
ac_use_abbrevs(@mut HashMap<ty::t, ty_abbrev>),
}
fn mywrite(w: @mut MemWriter, fmt: &fmt::Arguments) {
fmt::write(&mut *w as &mut io::Writer, fmt);
}
fn cx_uses_abbrevs(cx: @ctxt) -> bool {
match cx.abbrevs {
ac_no_abbrevs => return false,
@ -53,41 +64,43 @@ fn cx_uses_abbrevs(cx: @ctxt) -> bool {
}
}
pub fn enc_ty(w: @io::Writer, cx: @ctxt, t: ty::t) {
pub fn enc_ty(w: @mut MemWriter, cx: @ctxt, t: ty::t) {
match cx.abbrevs {
ac_no_abbrevs => {
let result_str = match cx.tcx.short_names_cache.find(&t) {
Some(&s) => s,
None => {
let s = do io::with_str_writer |wr| {
enc_sty(wr, cx, &ty::get(t).sty);
}.to_managed();
let wr = @mut MemWriter::new();
enc_sty(wr, cx, &ty::get(t).sty);
let s = str::from_utf8(*wr.inner_ref()).to_managed();
cx.tcx.short_names_cache.insert(t, s);
s
}
};
w.write_str(result_str);
w.write(result_str.as_bytes());
}
ac_use_abbrevs(abbrevs) => {
match abbrevs.find(&t) {
Some(a) => { w.write_str(a.s); return; }
Some(a) => { w.write(a.s.as_bytes()); return; }
None => {}
}
let pos = w.tell();
enc_sty(w, cx, &ty::get(t).sty);
let end = w.tell();
let len = end - pos;
fn estimate_sz(u: uint) -> uint {
fn estimate_sz(u: u64) -> u64 {
let mut n = u;
let mut len = 0u;
while n != 0u { len += 1u; n = n >> 4u; }
let mut len = 0;
while n != 0 { len += 1; n = n >> 4; }
return len;
}
let abbrev_len = 3u + estimate_sz(pos) + estimate_sz(len);
let abbrev_len = 3 + estimate_sz(pos) + estimate_sz(len);
if abbrev_len < len {
// I.e. it's actually an abbreviation.
let s = format!("\\#{:x}:{:x}\\#", pos, len).to_managed();
let a = ty_abbrev { pos: pos, len: len, s: s };
let a = ty_abbrev { pos: pos as uint,
len: len as uint,
s: s };
abbrevs.insert(t, a);
}
return;
@ -95,301 +108,253 @@ pub fn enc_ty(w: @io::Writer, cx: @ctxt, t: ty::t) {
}
}
fn enc_mutability(w: @io::Writer, mt: ast::Mutability) {
fn enc_mutability(w: @mut MemWriter, mt: ast::Mutability) {
match mt {
MutImmutable => (),
MutMutable => w.write_char('m'),
MutImmutable => (),
MutMutable => mywrite!(w, "m"),
}
}
fn enc_mt(w: @io::Writer, cx: @ctxt, mt: ty::mt) {
fn enc_mt(w: @mut MemWriter, cx: @ctxt, mt: ty::mt) {
enc_mutability(w, mt.mutbl);
enc_ty(w, cx, mt.ty);
}
fn enc_opt<T>(w: @io::Writer, t: Option<T>, enc_f: &fn(T)) {
fn enc_opt<T>(w: @mut MemWriter, t: Option<T>, enc_f: &fn(T)) {
match t {
None => w.write_char('n'),
Some(v) => {
w.write_char('s');
enc_f(v);
}
None => mywrite!(w, "n"),
Some(v) => {
mywrite!(w, "s");
enc_f(v);
}
}
}
fn enc_substs(w: @io::Writer, cx: @ctxt, substs: &ty::substs) {
fn enc_substs(w: @mut MemWriter, cx: @ctxt, substs: &ty::substs) {
enc_region_substs(w, cx, &substs.regions);
do enc_opt(w, substs.self_ty) |t| { enc_ty(w, cx, t) }
w.write_char('[');
mywrite!(w, "[");
for t in substs.tps.iter() { enc_ty(w, cx, *t); }
w.write_char(']');
mywrite!(w, "]");
}
fn enc_region_substs(w: @io::Writer, cx: @ctxt, substs: &ty::RegionSubsts) {
fn enc_region_substs(w: @mut MemWriter, cx: @ctxt, substs: &ty::RegionSubsts) {
match *substs {
ty::ErasedRegions => {
w.write_char('e');
mywrite!(w, "e");
}
ty::NonerasedRegions(ref regions) => {
w.write_char('n');
mywrite!(w, "n");
for &r in regions.iter() {
enc_region(w, cx, r);
}
w.write_char('.');
mywrite!(w, ".");
}
}
}
fn enc_region(w: @io::Writer, cx: @ctxt, r: ty::Region) {
fn enc_region(w: @mut MemWriter, cx: @ctxt, r: ty::Region) {
match r {
ty::re_bound(br) => {
w.write_char('b');
enc_bound_region(w, cx, br);
}
ty::re_free(ref fr) => {
w.write_char('f');
w.write_char('[');
w.write_int(fr.scope_id);
w.write_char('|');
enc_bound_region(w, cx, fr.bound_region);
w.write_char(']');
}
ty::re_scope(nid) => {
w.write_char('s');
w.write_int(nid);
w.write_char('|');
}
ty::re_static => {
w.write_char('t');
}
ty::re_empty => {
w.write_char('e');
}
ty::re_infer(_) => {
// these should not crop up after typeck
cx.diag.handler().bug("Cannot encode region variables");
}
ty::re_bound(br) => {
mywrite!(w, "b");
enc_bound_region(w, cx, br);
}
ty::re_free(ref fr) => {
mywrite!(w, "f[{}|", fr.scope_id);
enc_bound_region(w, cx, fr.bound_region);
mywrite!(w, "]");
}
ty::re_scope(nid) => mywrite!(w, "s{}|", nid),
ty::re_static => mywrite!(w, "t"),
ty::re_empty => mywrite!(w, "e"),
ty::re_infer(_) => {
// these should not crop up after typeck
cx.diag.handler().bug("Cannot encode region variables");
}
}
}
fn enc_bound_region(w: @io::Writer, cx: @ctxt, br: ty::bound_region) {
fn enc_bound_region(w: @mut MemWriter, cx: @ctxt, br: ty::bound_region) {
match br {
ty::br_self => w.write_char('s'),
ty::br_anon(idx) => {
w.write_char('a');
w.write_uint(idx);
w.write_char('|');
}
ty::br_named(s) => {
w.write_char('[');
w.write_str(cx.tcx.sess.str_of(s));
w.write_char(']')
}
ty::br_cap_avoid(id, br) => {
w.write_char('c');
w.write_int(id);
w.write_char('|');
enc_bound_region(w, cx, *br);
}
ty::br_fresh(id) => {
w.write_uint(id);
}
ty::br_self => mywrite!(w, "s"),
ty::br_anon(idx) => mywrite!(w, "a{}|", idx),
ty::br_named(s) => mywrite!(w, "[{}]", cx.tcx.sess.str_of(s)),
ty::br_cap_avoid(id, br) => {
mywrite!(w, "c{}|", id);
enc_bound_region(w, cx, *br);
}
ty::br_fresh(id) => mywrite!(w, "{}", id),
}
}
pub fn enc_vstore(w: @io::Writer, cx: @ctxt, v: ty::vstore) {
w.write_char('/');
pub fn enc_vstore(w: @mut MemWriter, cx: @ctxt, v: ty::vstore) {
mywrite!(w, "/");
match v {
ty::vstore_fixed(u) => {
w.write_uint(u);
w.write_char('|');
}
ty::vstore_uniq => {
w.write_char('~');
}
ty::vstore_box => {
w.write_char('@');
}
ty::vstore_slice(r) => {
w.write_char('&');
enc_region(w, cx, r);
}
ty::vstore_fixed(u) => mywrite!(w, "{}|", u),
ty::vstore_uniq => mywrite!(w, "~"),
ty::vstore_box => mywrite!(w, "@"),
ty::vstore_slice(r) => {
mywrite!(w, "&");
enc_region(w, cx, r);
}
}
}
pub fn enc_trait_ref(w: @io::Writer, cx: @ctxt, s: &ty::TraitRef) {
w.write_str((cx.ds)(s.def_id));
w.write_char('|');
pub fn enc_trait_ref(w: @mut MemWriter, cx: @ctxt, s: &ty::TraitRef) {
mywrite!(w, "{}|", (cx.ds)(s.def_id));
enc_substs(w, cx, &s.substs);
}
pub fn enc_trait_store(w: @io::Writer, cx: @ctxt, s: ty::TraitStore) {
pub fn enc_trait_store(w: @mut MemWriter, cx: @ctxt, s: ty::TraitStore) {
match s {
ty::UniqTraitStore => w.write_char('~'),
ty::BoxTraitStore => w.write_char('@'),
ty::UniqTraitStore => mywrite!(w, "~"),
ty::BoxTraitStore => mywrite!(w, "@"),
ty::RegionTraitStore(re) => {
w.write_char('&');
mywrite!(w, "&");
enc_region(w, cx, re);
}
}
}
fn enc_sty(w: @io::Writer, cx: @ctxt, st: &ty::sty) {
fn enc_sty(w: @mut MemWriter, cx: @ctxt, st: &ty::sty) {
match *st {
ty::ty_nil => w.write_char('n'),
ty::ty_bot => w.write_char('z'),
ty::ty_bool => w.write_char('b'),
ty::ty_char => w.write_char('c'),
ty::ty_int(t) => {
match t {
ty_i => w.write_char('i'),
ty_i8 => w.write_str(&"MB"),
ty_i16 => w.write_str(&"MW"),
ty_i32 => w.write_str(&"ML"),
ty_i64 => w.write_str(&"MD")
ty::ty_nil => mywrite!(w, "n"),
ty::ty_bot => mywrite!(w, "z"),
ty::ty_bool => mywrite!(w, "b"),
ty::ty_char => mywrite!(w, "c"),
ty::ty_int(t) => {
match t {
ty_i => mywrite!(w, "i"),
ty_i8 => mywrite!(w, "MB"),
ty_i16 => mywrite!(w, "MW"),
ty_i32 => mywrite!(w, "ML"),
ty_i64 => mywrite!(w, "MD")
}
}
}
ty::ty_uint(t) => {
match t {
ty_u => w.write_char('u'),
ty_u8 => w.write_str(&"Mb"),
ty_u16 => w.write_str(&"Mw"),
ty_u32 => w.write_str(&"Ml"),
ty_u64 => w.write_str(&"Md")
ty::ty_uint(t) => {
match t {
ty_u => mywrite!(w, "u"),
ty_u8 => mywrite!(w, "Mb"),
ty_u16 => mywrite!(w, "Mw"),
ty_u32 => mywrite!(w, "Ml"),
ty_u64 => mywrite!(w, "Md")
}
}
}
ty::ty_float(t) => {
match t {
ty_f32 => w.write_str(&"Mf"),
ty_f64 => w.write_str(&"MF"),
ty::ty_float(t) => {
match t {
ty_f32 => mywrite!(w, "Mf"),
ty_f64 => mywrite!(w, "MF"),
}
}
}
ty::ty_enum(def, ref substs) => {
w.write_str(&"t[");
w.write_str((cx.ds)(def));
w.write_char('|');
enc_substs(w, cx, substs);
w.write_char(']');
}
ty::ty_trait(def, ref substs, store, mt, bounds) => {
w.write_str(&"x[");
w.write_str((cx.ds)(def));
w.write_char('|');
enc_substs(w, cx, substs);
enc_trait_store(w, cx, store);
enc_mutability(w, mt);
let bounds = ty::ParamBounds {builtin_bounds: bounds,
trait_bounds: ~[]};
enc_bounds(w, cx, &bounds);
w.write_char(']');
}
ty::ty_tup(ref ts) => {
w.write_str(&"T[");
for t in ts.iter() { enc_ty(w, cx, *t); }
w.write_char(']');
}
ty::ty_box(mt) => { w.write_char('@'); enc_mt(w, cx, mt); }
ty::ty_uniq(mt) => { w.write_char('~'); enc_mt(w, cx, mt); }
ty::ty_ptr(mt) => { w.write_char('*'); enc_mt(w, cx, mt); }
ty::ty_rptr(r, mt) => {
w.write_char('&');
enc_region(w, cx, r);
enc_mt(w, cx, mt);
}
ty::ty_evec(mt, v) => {
w.write_char('V');
enc_mt(w, cx, mt);
enc_vstore(w, cx, v);
}
ty::ty_estr(v) => {
w.write_char('v');
enc_vstore(w, cx, v);
}
ty::ty_unboxed_vec(mt) => { w.write_char('U'); enc_mt(w, cx, mt); }
ty::ty_closure(ref f) => {
w.write_char('f');
enc_closure_ty(w, cx, f);
}
ty::ty_bare_fn(ref f) => {
w.write_char('F');
enc_bare_fn_ty(w, cx, f);
}
ty::ty_infer(_) => {
cx.diag.handler().bug("Cannot encode inference variable types");
}
ty::ty_param(param_ty {idx: id, def_id: did}) => {
w.write_char('p');
w.write_str((cx.ds)(did));
w.write_char('|');
w.write_str(id.to_str());
}
ty::ty_self(did) => {
w.write_char('s');
w.write_str((cx.ds)(did));
w.write_char('|');
}
ty::ty_type => w.write_char('Y'),
ty::ty_opaque_closure_ptr(p) => {
w.write_str(&"C&");
enc_sigil(w, p);
}
ty::ty_opaque_box => w.write_char('B'),
ty::ty_struct(def, ref substs) => {
debug!("~~~~ {}", "a[");
w.write_str(&"a[");
let s = (cx.ds)(def);
debug!("~~~~ {}", s);
w.write_str(s);
debug!("~~~~ {}", "|");
w.write_char('|');
enc_substs(w, cx, substs);
debug!("~~~~ {}", "]");
w.write_char(']');
}
ty::ty_err => fail!("Shouldn't encode error type")
ty::ty_enum(def, ref substs) => {
mywrite!(w, "t[{}|", (cx.ds)(def));
enc_substs(w, cx, substs);
mywrite!(w, "]");
}
ty::ty_trait(def, ref substs, store, mt, bounds) => {
mywrite!(w, "x[{}|", (cx.ds)(def));
enc_substs(w, cx, substs);
enc_trait_store(w, cx, store);
enc_mutability(w, mt);
let bounds = ty::ParamBounds {builtin_bounds: bounds,
trait_bounds: ~[]};
enc_bounds(w, cx, &bounds);
mywrite!(w, "]");
}
ty::ty_tup(ref ts) => {
mywrite!(w, "T[");
for t in ts.iter() { enc_ty(w, cx, *t); }
mywrite!(w, "]");
}
ty::ty_box(mt) => { mywrite!(w, "@"); enc_mt(w, cx, mt); }
ty::ty_uniq(mt) => { mywrite!(w, "~"); enc_mt(w, cx, mt); }
ty::ty_ptr(mt) => { mywrite!(w, "*"); enc_mt(w, cx, mt); }
ty::ty_rptr(r, mt) => {
mywrite!(w, "&");
enc_region(w, cx, r);
enc_mt(w, cx, mt);
}
ty::ty_evec(mt, v) => {
mywrite!(w, "V");
enc_mt(w, cx, mt);
enc_vstore(w, cx, v);
}
ty::ty_estr(v) => {
mywrite!(w, "v");
enc_vstore(w, cx, v);
}
ty::ty_unboxed_vec(mt) => { mywrite!(w, "U"); enc_mt(w, cx, mt); }
ty::ty_closure(ref f) => {
mywrite!(w, "f");
enc_closure_ty(w, cx, f);
}
ty::ty_bare_fn(ref f) => {
mywrite!(w, "F");
enc_bare_fn_ty(w, cx, f);
}
ty::ty_infer(_) => {
cx.diag.handler().bug("Cannot encode inference variable types");
}
ty::ty_param(param_ty {idx: id, def_id: did}) => {
mywrite!(w, "p{}|{}", (cx.ds)(did), id);
}
ty::ty_self(did) => {
mywrite!(w, "s{}|", (cx.ds)(did));
}
ty::ty_type => mywrite!(w, "Y"),
ty::ty_opaque_closure_ptr(p) => {
mywrite!(w, "C&");
enc_sigil(w, p);
}
ty::ty_opaque_box => mywrite!(w, "B"),
ty::ty_struct(def, ref substs) => {
mywrite!(w, "a[{}|", (cx.ds)(def));
enc_substs(w, cx, substs);
mywrite!(w, "]");
}
ty::ty_err => fail!("Shouldn't encode error type")
}
}
fn enc_sigil(w: @io::Writer, sigil: Sigil) {
fn enc_sigil(w: @mut MemWriter, sigil: Sigil) {
match sigil {
ManagedSigil => w.write_str("@"),
OwnedSigil => w.write_str("~"),
BorrowedSigil => w.write_str("&"),
ManagedSigil => mywrite!(w, "@"),
OwnedSigil => mywrite!(w, "~"),
BorrowedSigil => mywrite!(w, "&"),
}
}
fn enc_purity(w: @io::Writer, p: purity) {
fn enc_purity(w: @mut MemWriter, p: purity) {
match p {
impure_fn => w.write_char('i'),
unsafe_fn => w.write_char('u'),
extern_fn => w.write_char('c')
impure_fn => mywrite!(w, "i"),
unsafe_fn => mywrite!(w, "u"),
extern_fn => mywrite!(w, "c")
}
}
fn enc_abi_set(w: @io::Writer, abis: AbiSet) {
w.write_char('[');
fn enc_abi_set(w: @mut MemWriter, abis: AbiSet) {
mywrite!(w, "[");
do abis.each |abi| {
w.write_str(abi.name());
w.write_char(',');
mywrite!(w, "{},", abi.name());
true
};
w.write_char(']')
mywrite!(w, "]")
}
fn enc_onceness(w: @io::Writer, o: Onceness) {
fn enc_onceness(w: @mut MemWriter, o: Onceness) {
match o {
Once => w.write_char('o'),
Many => w.write_char('m')
Once => mywrite!(w, "o"),
Many => mywrite!(w, "m")
}
}
pub fn enc_bare_fn_ty(w: @io::Writer, cx: @ctxt, ft: &ty::BareFnTy) {
pub fn enc_bare_fn_ty(w: @mut MemWriter, cx: @ctxt, ft: &ty::BareFnTy) {
enc_purity(w, ft.purity);
enc_abi_set(w, ft.abis);
enc_fn_sig(w, cx, &ft.sig);
}
fn enc_closure_ty(w: @io::Writer, cx: @ctxt, ft: &ty::ClosureTy) {
fn enc_closure_ty(w: @mut MemWriter, cx: @ctxt, ft: &ty::ClosureTy) {
enc_sigil(w, ft.sigil);
enc_purity(w, ft.purity);
enc_onceness(w, ft.onceness);
@ -400,37 +365,34 @@ fn enc_closure_ty(w: @io::Writer, cx: @ctxt, ft: &ty::ClosureTy) {
enc_fn_sig(w, cx, &ft.sig);
}
fn enc_fn_sig(w: @io::Writer, cx: @ctxt, fsig: &ty::FnSig) {
w.write_char('[');
fn enc_fn_sig(w: @mut MemWriter, cx: @ctxt, fsig: &ty::FnSig) {
mywrite!(w, "[");
for ty in fsig.inputs.iter() {
enc_ty(w, cx, *ty);
}
w.write_char(']');
mywrite!(w, "]");
enc_ty(w, cx, fsig.output);
}
fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: &ty::ParamBounds) {
fn enc_bounds(w: @mut MemWriter, cx: @ctxt, bs: &ty::ParamBounds) {
for bound in bs.builtin_bounds.iter() {
match bound {
ty::BoundSend => w.write_char('S'),
ty::BoundFreeze => w.write_char('K'),
ty::BoundStatic => w.write_char('O'),
ty::BoundSized => w.write_char('Z'),
ty::BoundSend => mywrite!(w, "S"),
ty::BoundFreeze => mywrite!(w, "K"),
ty::BoundStatic => mywrite!(w, "O"),
ty::BoundSized => mywrite!(w, "Z"),
}
}
for &tp in bs.trait_bounds.iter() {
w.write_char('I');
mywrite!(w, "I");
enc_trait_ref(w, cx, tp);
}
w.write_char('.');
mywrite!(w, ".");
}
pub fn enc_type_param_def(w: @io::Writer, cx: @ctxt, v: &ty::TypeParameterDef) {
w.write_str(cx.tcx.sess.str_of(v.ident));
w.write_char(':');
w.write_str((cx.ds)(v.def_id));
w.write_char('|');
pub fn enc_type_param_def(w: @mut MemWriter, cx: @ctxt, v: &ty::TypeParameterDef) {
mywrite!(w, "{}:{}|", cx.tcx.sess.str_of(v.ident), (cx.ds)(v.def_id));
enc_bounds(w, cx, v.bounds);
}

View File

@ -23,13 +23,6 @@ use middle::{ty, typeck, moves};
use middle;
use util::ppaux::ty_to_str;
use std::at_vec;
use std::libc;
use extra::ebml::reader;
use extra::ebml;
use extra::serialize;
use extra::serialize::{Encoder, Encodable, EncoderHelpers, DecoderHelpers};
use extra::serialize::{Decoder, Decodable};
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util::inlined_item_utils;
@ -40,9 +33,18 @@ use syntax::fold::*;
use syntax::fold;
use syntax::parse::token;
use syntax;
use writer = extra::ebml::writer;
use std::at_vec;
use std::libc;
use std::cast;
use std::rt::io::Seek;
use extra::ebml::reader;
use extra::ebml;
use extra::serialize;
use extra::serialize::{Encoder, Encodable, EncoderHelpers, DecoderHelpers};
use extra::serialize::{Decoder, Decodable};
use writer = extra::ebml::writer;
#[cfg(test)] use syntax::parse;
#[cfg(test)] use syntax::print::pprust;
@ -1319,14 +1321,14 @@ fn mk_ctxt() -> @fake_ext_ctxt {
#[cfg(test)]
fn roundtrip(in_item: Option<@ast::item>) {
use std::io;
use std::rt::io::Decorator;
use std::rt::io::mem::MemWriter;
let in_item = in_item.unwrap();
let bytes = do io::with_bytes_writer |wr| {
let mut ebml_w = writer::Encoder(wr);
encode_item_ast(&mut ebml_w, in_item);
};
let ebml_doc = reader::Doc(@bytes);
let wr = @mut MemWriter::new();
let mut ebml_w = writer::Encoder(wr);
encode_item_ast(&mut ebml_w, in_item);
let ebml_doc = reader::Doc(@wr.inner_ref().to_owned());
let out_item = decode_item_ast(ebml_doc);
assert_eq!(in_item, out_item);

View File

@ -22,46 +22,66 @@ use vec;
/// Writes to an owned, growable byte vector
pub struct MemWriter {
priv buf: ~[u8]
priv buf: ~[u8],
priv pos: uint,
}
impl MemWriter {
pub fn new() -> MemWriter { MemWriter { buf: vec::with_capacity(128) } }
pub fn new() -> MemWriter {
MemWriter { buf: vec::with_capacity(128), pos: 0 }
}
}
impl Writer for MemWriter {
fn write(&mut self, buf: &[u8]) {
self.buf.push_all(buf)
// Make sure the internal buffer is as least as big as where we
// currently are
let difference = self.pos as i64 - self.buf.len() as i64;
if difference > 0 {
self.buf.grow(difference as uint, &0);
}
// Figure out what bytes will be used to overwrite what's currently
// there (left), and what will be appended on the end (right)
let cap = self.buf.len() - self.pos;
let (left, right) = if cap <= buf.len() {
(buf.slice_to(cap), buf.slice_from(cap))
} else {
(buf, &[])
};
// Do the necessary writes
if left.len() > 0 {
vec::bytes::copy_memory(self.buf.mut_slice_from(self.pos),
left, left.len());
}
if right.len() > 0 {
self.buf.push_all(right);
}
// Bump us forward
self.pos += buf.len();
}
fn flush(&mut self) { /* no-op */ }
}
impl Seek for MemWriter {
fn tell(&self) -> u64 { self.buf.len() as u64 }
fn tell(&self) -> u64 { self.pos as u64 }
fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
fn seek(&mut self, pos: i64, style: SeekStyle) {
match style {
SeekSet => { self.pos = pos as uint; }
SeekEnd => { self.pos = self.buf.len() + pos as uint; }
SeekCur => { self.pos += pos as uint; }
}
}
}
impl Decorator<~[u8]> for MemWriter {
fn inner(self) -> ~[u8] {
match self {
MemWriter { buf: buf } => buf
}
}
fn inner_ref<'a>(&'a self) -> &'a ~[u8] {
match *self {
MemWriter { buf: ref buf } => buf
}
}
fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] {
match *self {
MemWriter { buf: ref mut buf } => buf
}
}
fn inner(self) -> ~[u8] { self.buf }
fn inner_ref<'a>(&'a self) -> &'a ~[u8] { &self.buf }
fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] { &mut self.buf }
}
/// Reads from an owned byte vector
@ -208,6 +228,7 @@ pub fn with_mem_writer(writeFn:&fn(&mut MemWriter)) -> ~[u8] {
mod test {
use prelude::*;
use super::*;
use rt::io::*;
#[test]
fn test_mem_writer() {
@ -218,7 +239,24 @@ mod test {
writer.write([1, 2, 3]);
writer.write([4, 5, 6, 7]);
assert_eq!(writer.tell(), 8);
assert_eq!(writer.inner(), ~[0, 1, 2, 3, 4, 5 , 6, 7]);
assert_eq!(*writer.inner_ref(), ~[0, 1, 2, 3, 4, 5, 6, 7]);
writer.seek(0, SeekSet);
assert_eq!(writer.tell(), 0);
writer.write([3, 4]);
assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 3, 4, 5, 6, 7]);
writer.seek(1, SeekCur);
writer.write([0, 1]);
assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 0, 1, 5, 6, 7]);
writer.seek(-1, SeekEnd);
writer.write([1, 2]);
assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 0, 1, 5, 6, 1, 2]);
writer.seek(1, SeekEnd);
writer.write([1]);
assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]);
}
#[test]

View File

@ -17,7 +17,8 @@
extern mod extra;
use std::io;
use std::rt::io::mem::MemWriter;
use std::rt::io::Decorator;
use std::rand::{random, Rand};
use extra::serialize::{Encodable, Decodable};
use extra::ebml;
@ -55,11 +56,10 @@ struct G<T> {
fn roundtrip<T: Rand + Eq + Encodable<Encoder> + Decodable<Decoder>>() {
let obj: T = random();
let bytes = do io::with_bytes_writer |w| {
let mut e = Encoder(w);
obj.encode(&mut e);
};
let doc = ebml::reader::Doc(@bytes);
let w = @mut MemWriter::new();
let mut e = Encoder(w);
obj.encode(&mut e);
let doc = ebml::reader::Doc(@w.inner_ref().to_owned());
let mut dec = Decoder(doc);
let obj2 = Decodable::decode(&mut dec);
assert!(obj == obj2);