]> git.lizzy.rs Git - rust.git/commitdiff
Remove std::io from ebml
authorAlex Crichton <alex@alexcrichton.com>
Tue, 22 Oct 2013 00:11:42 +0000 (17:11 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Thu, 24 Oct 2013 21:21:58 +0000 (14:21 -0700)
src/libextra/ebml.rs
src/libextra/uuid.rs
src/librustc/metadata/encoder.rs
src/librustc/metadata/tyencode.rs
src/librustc/middle/astencode.rs
src/libstd/rt/io/mem.rs
src/test/run-pass/deriving-encodable-decodable.rs

index 34515a2b955cb0b7ebe600fa38c5511821bd9f47..1a21150d11b5939e3864052c53d42b9ed8378bdc 100644 (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 @@ fn vuint_at_slow(data: &[u8], start: uint) -> Res {
     #[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 fn vuint_at(data: &[u8], start: uint) -> Res {
         }
     }
 
-    #[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 fn doc_as_u8(d: Doc) -> u8 {
 
     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 @@ fn clone(&self) -> Encoder {
         }
     }
 
-    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 @@ fn write_sized_vuint(w: @io::Writer, n: uint, size: uint) {
         };
     }
 
-    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 @@ fn write_vuint(w: @io::Writer, n: uint) {
         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 fn start_tag(&mut self, tag_id: uint) {
             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 fn start_tag(&mut self, tag_id: uint) {
         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 fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) {
         }
 
         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 fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) {
         }
 
         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);
index 345cf64f1281aa856d707b9f0a6f560029c27c63..b94b74a696cc26552ca2ec07fcc7a49b2558c16d 100644 (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 @@ fn test_serialize_round_trip() {
         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);
     }
 }
index e6d6b282572184213d54ac313bbfe408f905f225..d64820332a5d959ef96cd5e1e389e6adce393db9 100644 (file)
 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 @@ fn encode_hash(ebml_w: &mut writer::Encoder, hash: &str) {
       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())
 }
index 33be1be8955561639b3bb184deefdc494a209f15..7fb33c881156b17ff0d334e63e276d0ed3fed942 100644 (file)
 
 // 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 @@ fn estimate_sz(u: uint) -> uint {
     }
 }
 
-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);
 }
index 3d7f28b8b30b1503fa57df1d27e84ca6ddce9efd..cb8c7b3262fbf2ecfb195cfbe60cf7556b9bb585 100644 (file)
 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;
 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);
index 5f6b4398c22f72be83aac931ab8fba5191b05e64..0ec37cd3c07894f46906fca2bb3e069ad2d82417 100644 (file)
 
 /// 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 seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
-}
-
-impl Decorator<~[u8]> for MemWriter {
-
-    fn inner(self) -> ~[u8] {
-        match self {
-            MemWriter { buf: buf } => buf
-        }
-    }
+    fn tell(&self) -> u64 { self.pos as u64 }
 
-    fn inner_ref<'a>(&'a self) -> &'a ~[u8] {
-        match *self {
-            MemWriter { buf: ref buf } => buf
+    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; }
         }
     }
+}
 
-    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] {
-        match *self {
-            MemWriter { buf: ref mut buf } => buf
-        }
-    }
+impl Decorator<~[u8]> for MemWriter {
+    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 @@ fn test_mem_writer() {
         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]
index b1c5f2f0f2d729365a1206eba7f7c05c259ed190..8d3ad26764281ee52d68784e491e94268f86b81e 100644 (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);