/// assert_eq!(s.shift_char(), Some('o'));
/// assert_eq!(s.shift_char(), None);
/// ```
- pub fn shift_char (&mut self) -> Option<char> {
+ pub fn shift_char(&mut self) -> Option<char> {
let len = self.len();
if len == 0 {
return None
#[phase(plugin, link)] extern crate log;
#[phase(plugin, link)] extern crate syntax;
+#[cfg(test)]
+extern crate test;
+
mod diagnostics;
pub mod back {
pub mod common;
pub mod ppaux;
+ pub mod io;
pub mod nodemap;
}
use middle::typeck;
use middle::stability;
use middle;
+use util::io::SeekableMemWriter;
use util::nodemap::{NodeMap, NodeSet};
use serialize::Encodable;
use std::gc::Gc;
use std::hash::Hash;
use std::hash;
-use std::io::MemWriter;
use std::mem;
use std::collections::HashMap;
use syntax::abi;
IIForeignRef(&'a ast::ForeignItem)
}
-pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
+pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
ebml_w: &mut Encoder,
// Path and definition ID indexing
fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
- write_fn: |&mut MemWriter, &T|) {
+ write_fn: |&mut SeekableMemWriter, &T|) {
let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
for elt in index.move_iter() {
let h = hash::hash(&elt.val) as uint;
ebml_w.start_tag(tag_index_buckets_bucket_elt);
assert!(elt.pos < 0xffff_ffff);
{
- let wr: &mut MemWriter = ebml_w.writer;
+ let wr: &mut SeekableMemWriter = ebml_w.writer;
wr.write_be_u32(elt.pos as u32);
}
write_fn(ebml_w.writer, &elt.val);
ebml_w.start_tag(tag_index_table);
for pos in bucket_locs.iter() {
assert!(*pos < 0xffff_ffff);
- let wr: &mut MemWriter = ebml_w.writer;
+ let wr: &mut SeekableMemWriter = ebml_w.writer;
wr.write_be_u32(*pos as u32);
}
ebml_w.end_tag();
ebml_w.end_tag();
}
-fn write_i64(writer: &mut MemWriter, &n: &i64) {
- let wr: &mut MemWriter = writer;
+fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) {
+ let wr: &mut SeekableMemWriter = writer;
assert!(n < 0x7fff_ffff);
wr.write_be_u32(n as u32);
}
ebml_w.start_tag(tag_lang_items_item_id);
{
- let wr: &mut MemWriter = ebml_w.writer;
+ let wr: &mut SeekableMemWriter = 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);
{
- let wr: &mut MemWriter = ebml_w.writer;
+ let wr: &mut SeekableMemWriter = ebml_w.writer;
wr.write_be_u32(id.node as u32);
}
ebml_w.end_tag(); // tag_lang_items_item_node_id
0, 0, 0, 1 ];
pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
- let mut wr = MemWriter::new();
+ let mut wr = SeekableMemWriter::new();
encode_metadata_inner(&mut wr, parms, krate);
wr.unwrap().move_iter().collect()
}
-fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
+fn encode_metadata_inner(wr: &mut SeekableMemWriter, parms: EncodeParams, krate: &Crate) {
struct Stats {
attr_bytes: u64,
dep_bytes: u64,
// Get the encoded string for a type
pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> String {
- let mut wr = MemWriter::new();
+ let mut wr = SeekableMemWriter::new();
tyencode::enc_ty(&mut wr, &tyencode::ctxt {
diag: tcx.sess.diagnostic(),
ds: def_to_string,
use std::cell::RefCell;
use std::collections::HashMap;
-use std::io::MemWriter;
use middle::subst;
use middle::subst::VecPerParamSpace;
use syntax::diagnostic::SpanHandler;
use syntax::parse::token;
+use util::io::SeekableMemWriter;
+
macro_rules! mywrite( ($($arg:tt)*) => ({ write!($($arg)*); }) )
pub struct ctxt<'a> {
pub type abbrev_map = RefCell<HashMap<ty::t, ty_abbrev>>;
-pub fn enc_ty(w: &mut MemWriter, cx: &ctxt, t: ty::t) {
+pub fn enc_ty(w: &mut SeekableMemWriter, cx: &ctxt, t: ty::t) {
match cx.abbrevs.borrow_mut().find(&t) {
Some(a) => { w.write(a.s.as_bytes()); return; }
None => {}
}
}
-fn enc_mutability(w: &mut MemWriter, mt: ast::Mutability) {
+fn enc_mutability(w: &mut SeekableMemWriter, mt: ast::Mutability) {
match mt {
MutImmutable => (),
MutMutable => mywrite!(w, "m"),
}
}
-fn enc_mt(w: &mut MemWriter, cx: &ctxt, mt: ty::mt) {
+fn enc_mt(w: &mut SeekableMemWriter, cx: &ctxt, mt: ty::mt) {
enc_mutability(w, mt.mutbl);
enc_ty(w, cx, mt.ty);
}
-fn enc_opt<T>(w: &mut MemWriter, t: Option<T>, enc_f: |&mut MemWriter, T|) {
+fn enc_opt<T>(w: &mut SeekableMemWriter, t: Option<T>, enc_f: |&mut SeekableMemWriter, T|) {
match t {
None => mywrite!(w, "n"),
Some(v) => {
}
}
-fn enc_vec_per_param_space<T>(w: &mut MemWriter,
+fn enc_vec_per_param_space<T>(w: &mut SeekableMemWriter,
cx: &ctxt,
v: &VecPerParamSpace<T>,
- op: |&mut MemWriter, &ctxt, &T|) {
+ op: |&mut SeekableMemWriter, &ctxt, &T|) {
for &space in subst::ParamSpace::all().iter() {
mywrite!(w, "[");
for t in v.get_slice(space).iter() {
}
}
-pub fn enc_substs(w: &mut MemWriter, cx: &ctxt, substs: &subst::Substs) {
+pub fn enc_substs(w: &mut SeekableMemWriter, cx: &ctxt, substs: &subst::Substs) {
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 MemWriter, cx: &ctxt, substs: &subst::RegionSubsts) {
+fn enc_region_substs(w: &mut SeekableMemWriter, cx: &ctxt, substs: &subst::RegionSubsts) {
match *substs {
subst::ErasedRegions => {
mywrite!(w, "e");
}
}
-fn enc_region(w: &mut MemWriter, cx: &ctxt, r: ty::Region) {
+fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) {
match r {
ty::ReLateBound(id, br) => {
mywrite!(w, "b[{}|", id);
}
}
-fn enc_bound_region(w: &mut MemWriter, cx: &ctxt, br: ty::BoundRegion) {
+fn enc_bound_region(w: &mut SeekableMemWriter, cx: &ctxt, br: ty::BoundRegion) {
match br {
ty::BrAnon(idx) => {
mywrite!(w, "a{}|", idx);
}
}
-pub fn enc_trait_ref(w: &mut MemWriter, cx: &ctxt, s: &ty::TraitRef) {
+pub fn enc_trait_ref(w: &mut SeekableMemWriter, cx: &ctxt, s: &ty::TraitRef) {
mywrite!(w, "{}|", (cx.ds)(s.def_id));
enc_substs(w, cx, &s.substs);
}
-pub fn enc_trait_store(w: &mut MemWriter, cx: &ctxt, s: ty::TraitStore) {
+pub fn enc_trait_store(w: &mut SeekableMemWriter, cx: &ctxt, s: ty::TraitStore) {
match s {
ty::UniqTraitStore => mywrite!(w, "~"),
ty::RegionTraitStore(re, m) => {
}
}
-fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) {
+fn enc_sty(w: &mut SeekableMemWriter, cx: &ctxt, st: &ty::sty) {
match *st {
ty::ty_nil => mywrite!(w, "n"),
ty::ty_bot => mywrite!(w, "z"),
}
}
-fn enc_fn_style(w: &mut MemWriter, p: FnStyle) {
+fn enc_fn_style(w: &mut SeekableMemWriter, p: FnStyle) {
match p {
NormalFn => mywrite!(w, "n"),
UnsafeFn => mywrite!(w, "u"),
}
}
-fn enc_abi(w: &mut MemWriter, abi: Abi) {
+fn enc_abi(w: &mut SeekableMemWriter, abi: Abi) {
mywrite!(w, "[");
mywrite!(w, "{}", abi.name());
mywrite!(w, "]")
}
-fn enc_onceness(w: &mut MemWriter, o: Onceness) {
+fn enc_onceness(w: &mut SeekableMemWriter, o: Onceness) {
match o {
Once => mywrite!(w, "o"),
Many => mywrite!(w, "m")
}
}
-pub fn enc_bare_fn_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::BareFnTy) {
+pub fn enc_bare_fn_ty(w: &mut SeekableMemWriter, cx: &ctxt, ft: &ty::BareFnTy) {
enc_fn_style(w, ft.fn_style);
enc_abi(w, ft.abi);
enc_fn_sig(w, cx, &ft.sig);
}
-pub fn enc_closure_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::ClosureTy) {
+pub fn enc_closure_ty(w: &mut SeekableMemWriter, cx: &ctxt, ft: &ty::ClosureTy) {
enc_fn_style(w, ft.fn_style);
enc_onceness(w, ft.onceness);
enc_trait_store(w, cx, ft.store);
enc_abi(w, ft.abi);
}
-fn enc_fn_sig(w: &mut MemWriter, cx: &ctxt, fsig: &ty::FnSig) {
+fn enc_fn_sig(w: &mut SeekableMemWriter, cx: &ctxt, fsig: &ty::FnSig) {
mywrite!(w, "[{}|", fsig.binder_id);
for ty in fsig.inputs.iter() {
enc_ty(w, cx, *ty);
enc_ty(w, cx, fsig.output);
}
-fn enc_bounds(w: &mut MemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
+fn enc_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
for bound in bs.builtin_bounds.iter() {
match bound {
ty::BoundSend => mywrite!(w, "S"),
mywrite!(w, ".");
}
-pub fn enc_type_param_def(w: &mut MemWriter, cx: &ctxt, v: &ty::TypeParameterDef) {
+pub fn enc_type_param_def(w: &mut SeekableMemWriter, cx: &ctxt, v: &ty::TypeParameterDef) {
mywrite!(w, "{}:{}|{}|{}|",
token::get_ident(v.ident), (cx.ds)(v.def_id),
v.space.to_uint(), v.index);
use middle::subst::VecPerParamSpace;
use middle::typeck::{MethodCall, MethodCallee, MethodOrigin};
use middle::{ty, typeck};
+use util::io::SeekableMemWriter;
use util::ppaux::ty_to_string;
use syntax::{ast, ast_map, ast_util, codemap, fold};
use libc;
use std::io::Seek;
-use std::io::MemWriter;
use std::mem;
use std::gc::GC;
fn tr_intern(&self, xcx: &ExtendedDecodeContext) -> ast::DefId;
}
-pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
+pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
// ______________________________________________________________________
// Top-level methods.
#[cfg(test)]
fn roundtrip(in_item: Option<Gc<ast::Item>>) {
- use std::io::MemWriter;
-
let in_item = in_item.unwrap();
- let mut wr = MemWriter::new();
+ let mut wr = SeekableMemWriter::new();
{
let mut ebml_w = writer::Encoder::new(&mut wr);
encode_item_ast(&mut ebml_w, in_item);
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::io::{IoError, IoResult, SeekStyle};
+use std::io;
+use std::slice;
+
+static BUF_CAPACITY: uint = 128;
+
+fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
+ // compute offset as signed and clamp to prevent overflow
+ let pos = match seek {
+ io::SeekSet => 0,
+ io::SeekEnd => end,
+ io::SeekCur => cur,
+ } as i64;
+
+ if offset + pos < 0 {
+ Err(IoError {
+ kind: io::InvalidInput,
+ desc: "invalid seek to a negative offset",
+ detail: None
+ })
+ } else {
+ Ok((offset + pos) as u64)
+ }
+}
+
+/// Writes to an owned, growable byte vector that supports seeking.
+///
+/// # Example
+///
+/// ```rust
+/// # #![allow(unused_must_use)]
+/// use std::io::SeekableMemWriter;
+///
+/// let mut w = SeekableMemWriter::new();
+/// w.write([0, 1, 2]);
+///
+/// assert_eq!(w.unwrap(), vec!(0, 1, 2));
+/// ```
+pub struct SeekableMemWriter {
+ buf: Vec<u8>,
+ pos: uint,
+}
+
+impl SeekableMemWriter {
+ /// Create a new `SeekableMemWriter`.
+ #[inline]
+ pub fn new() -> SeekableMemWriter {
+ SeekableMemWriter::with_capacity(BUF_CAPACITY)
+ }
+ /// Create a new `SeekableMemWriter`, allocating at least `n` bytes for
+ /// the internal buffer.
+ #[inline]
+ pub fn with_capacity(n: uint) -> SeekableMemWriter {
+ SeekableMemWriter { buf: Vec::with_capacity(n), pos: 0 }
+ }
+
+ /// Acquires an immutable reference to the underlying buffer of this
+ /// `SeekableMemWriter`.
+ ///
+ /// No method is exposed for acquiring a mutable reference to the buffer
+ /// because it could corrupt the state of this `MemWriter`.
+ #[inline]
+ pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
+
+ /// Unwraps this `SeekableMemWriter`, returning the underlying buffer
+ #[inline]
+ pub fn unwrap(self) -> Vec<u8> { self.buf }
+}
+
+impl Writer for SeekableMemWriter {
+ #[inline]
+ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
+ if self.pos == self.buf.len() {
+ self.buf.push_all(buf)
+ } else {
+ // 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 {
+ slice::bytes::copy_memory(self.buf.mut_slice_from(self.pos), left);
+ }
+ if right.len() > 0 {
+ self.buf.push_all(right);
+ }
+ }
+
+ // Bump us forward
+ self.pos += buf.len();
+ Ok(())
+ }
+}
+
+impl Seek for SeekableMemWriter {
+ #[inline]
+ fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
+
+ #[inline]
+ fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
+ let new = try!(combine(style, self.pos, self.buf.len(), pos));
+ self.pos = new as uint;
+ Ok(())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::SeekableMemWriter;
+ use std::io;
+ use test::Bencher;
+
+ #[test]
+ fn test_seekable_mem_writer() {
+ let mut writer = SeekableMemWriter::new();
+ assert_eq!(writer.tell(), Ok(0));
+ writer.write([0]).unwrap();
+ assert_eq!(writer.tell(), Ok(1));
+ writer.write([1, 2, 3]).unwrap();
+ writer.write([4, 5, 6, 7]).unwrap();
+ assert_eq!(writer.tell(), Ok(8));
+ assert_eq!(writer.get_ref(), &[0, 1, 2, 3, 4, 5, 6, 7]);
+
+ writer.seek(0, io::SeekSet).unwrap();
+ assert_eq!(writer.tell(), Ok(0));
+ writer.write([3, 4]).unwrap();
+ assert_eq!(writer.get_ref(), &[3, 4, 2, 3, 4, 5, 6, 7]);
+
+ writer.seek(1, io::SeekCur).unwrap();
+ writer.write([0, 1]).unwrap();
+ assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 7]);
+
+ writer.seek(-1, io::SeekEnd).unwrap();
+ writer.write([1, 2]).unwrap();
+ assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 1, 2]);
+
+ writer.seek(1, io::SeekEnd).unwrap();
+ writer.write([1]).unwrap();
+ assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]);
+ }
+
+ #[test]
+ fn seek_past_end() {
+ let mut r = SeekableMemWriter::new();
+ r.seek(10, io::SeekSet).unwrap();
+ assert!(r.write([3]).is_ok());
+ }
+
+ #[test]
+ fn seek_before_0() {
+ let mut r = SeekableMemWriter::new();
+ assert!(r.seek(-1, io::SeekSet).is_err());
+ }
+
+ fn do_bench_seekable_mem_writer(b: &mut Bencher, times: uint, len: uint) {
+ let src: Vec<u8> = Vec::from_elem(len, 5);
+
+ b.bytes = (times * len) as u64;
+ b.iter(|| {
+ let mut wr = SeekableMemWriter::new();
+ for _ in range(0, times) {
+ wr.write(src.as_slice()).unwrap();
+ }
+
+ let v = wr.unwrap();
+ assert_eq!(v.len(), times * len);
+ assert!(v.iter().all(|x| *x == 5));
+ });
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_001_0000(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 1, 0)
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_001_0010(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 1, 10)
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_001_0100(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 1, 100)
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_001_1000(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 1, 1000)
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_100_0000(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 100, 0)
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_100_0010(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 100, 10)
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_100_0100(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 100, 100)
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_100_1000(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 100, 1000)
+ }
+}
use ebml::writer;
use {Encodable, Decodable};
- use std::io::MemWriter;
+ use std::io::{IoError, IoResult, SeekStyle};
+ use std::io;
use std::option::{None, Option, Some};
+ use std::slice;
+
+ static BUF_CAPACITY: uint = 128;
+
+ fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
+ // compute offset as signed and clamp to prevent overflow
+ let pos = match seek {
+ io::SeekSet => 0,
+ io::SeekEnd => end,
+ io::SeekCur => cur,
+ } as i64;
+
+ if offset + pos < 0 {
+ Err(IoError {
+ kind: io::InvalidInput,
+ desc: "invalid seek to a negative offset",
+ detail: None
+ })
+ } else {
+ Ok((offset + pos) as u64)
+ }
+ }
+
+ /// Writes to an owned, growable byte vector that supports seeking.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # #![allow(unused_must_use)]
+ /// use std::io::SeekableMemWriter;
+ ///
+ /// let mut w = SeekableMemWriter::new();
+ /// w.write([0, 1, 2]);
+ ///
+ /// assert_eq!(w.unwrap(), vec!(0, 1, 2));
+ /// ```
+ pub struct SeekableMemWriter {
+ buf: Vec<u8>,
+ pos: uint,
+ }
+
+ impl SeekableMemWriter {
+ /// Create a new `SeekableMemWriter`.
+ #[inline]
+ pub fn new() -> SeekableMemWriter {
+ SeekableMemWriter::with_capacity(BUF_CAPACITY)
+ }
+ /// Create a new `SeekableMemWriter`, allocating at least `n` bytes for
+ /// the internal buffer.
+ #[inline]
+ pub fn with_capacity(n: uint) -> SeekableMemWriter {
+ SeekableMemWriter { buf: Vec::with_capacity(n), pos: 0 }
+ }
+
+ /// Acquires an immutable reference to the underlying buffer of this
+ /// `SeekableMemWriter`.
+ ///
+ /// No method is exposed for acquiring a mutable reference to the buffer
+ /// because it could corrupt the state of this `MemWriter`.
+ #[inline]
+ pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
+
+ /// Unwraps this `SeekableMemWriter`, returning the underlying buffer
+ #[inline]
+ pub fn unwrap(self) -> Vec<u8> { self.buf }
+ }
+
+ impl Writer for SeekableMemWriter {
+ #[inline]
+ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
+ if self.pos == self.buf.len() {
+ self.buf.push_all(buf)
+ } else {
+ // 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 {
+ slice::bytes::copy_memory(self.buf.mut_slice_from(self.pos), left);
+ }
+ if right.len() > 0 {
+ self.buf.push_all(right);
+ }
+ }
+
+ // Bump us forward
+ self.pos += buf.len();
+ Ok(())
+ }
+ }
+
+ impl Seek for SeekableMemWriter {
+ #[inline]
+ fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
+
+ #[inline]
+ fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
+ let new = try!(combine(style, self.pos, self.buf.len(), pos));
+ self.pos = new as uint;
+ Ok(())
+ }
+ }
#[test]
fn test_vuint_at() {
fn test_option_int() {
fn test_v(v: Option<int>) {
debug!("v == {}", v);
- let mut wr = MemWriter::new();
+ let mut wr = SeekableMemWriter::new();
{
let mut ebml_w = writer::Encoder::new(&mut wr);
let _ = v.encode(&mut ebml_w);
Some(e) => e,
None => { break; }
};
- let (ref expected_evt, ref expected_stack) = *expected.get(i);
+ let (ref expected_evt, ref expected_stack) = expected[i];
if !parser.stack().is_equal_to(expected_stack.as_slice()) {
fail!("Parser stack is not equal to {}", expected_stack);
}
}
) )
- struct TempDir(Path);
+ pub struct TempDir(Path);
impl TempDir {
fn join(&self, path: &str) -> Path {
use slice::{Vector, ImmutableVector, MutableVector};
use vec::Vec;
+static BUF_CAPACITY: uint = 128;
+
fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
// compute offset as signed and clamp to prevent overflow
let pos = match seek {
///
/// assert_eq!(w.unwrap(), vec!(0, 1, 2));
/// ```
+#[deriving(Clone)]
pub struct MemWriter {
buf: Vec<u8>,
- pos: uint,
}
impl MemWriter {
/// Create a new `MemWriter`.
#[inline]
pub fn new() -> MemWriter {
- MemWriter::with_capacity(128)
+ MemWriter::with_capacity(BUF_CAPACITY)
}
/// Create a new `MemWriter`, allocating at least `n` bytes for
/// the internal buffer.
#[inline]
pub fn with_capacity(n: uint) -> MemWriter {
- MemWriter { buf: Vec::with_capacity(n), pos: 0 }
+ MemWriter { buf: Vec::with_capacity(n) }
}
/// Acquires an immutable reference to the underlying buffer of this
/// `MemWriter`.
- ///
- /// No method is exposed for acquiring a mutable reference to the buffer
- /// because it could corrupt the state of this `MemWriter`.
#[inline]
pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
impl Writer for MemWriter {
#[inline]
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
- // 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 {
- slice::bytes::copy_memory(self.buf.mut_slice_from(self.pos), left);
- }
- if right.len() > 0 {
- self.buf.push_all(right);
- }
-
- // Bump us forward
- self.pos += buf.len();
- Ok(())
- }
-}
-
-impl Seek for MemWriter {
- #[inline]
- fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
-
- #[inline]
- fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
- let new = try!(combine(style, self.pos, self.buf.len(), pos));
- self.pos = new as uint;
+ self.buf.push_all(buf);
Ok(())
}
}
#[test]
fn test_mem_writer() {
let mut writer = MemWriter::new();
- assert_eq!(writer.tell(), Ok(0));
writer.write([0]).unwrap();
- assert_eq!(writer.tell(), Ok(1));
writer.write([1, 2, 3]).unwrap();
writer.write([4, 5, 6, 7]).unwrap();
- assert_eq!(writer.tell(), Ok(8));
assert_eq!(writer.get_ref(), &[0, 1, 2, 3, 4, 5, 6, 7]);
-
- writer.seek(0, SeekSet).unwrap();
- assert_eq!(writer.tell(), Ok(0));
- writer.write([3, 4]).unwrap();
- assert_eq!(writer.get_ref(), &[3, 4, 2, 3, 4, 5, 6, 7]);
-
- writer.seek(1, SeekCur).unwrap();
- writer.write([0, 1]).unwrap();
- assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 7]);
-
- writer.seek(-1, SeekEnd).unwrap();
- writer.write([1, 2]).unwrap();
- assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 1, 2]);
-
- writer.seek(1, SeekEnd).unwrap();
- writer.write([1]).unwrap();
- assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]);
}
#[test]
r.seek(10, SeekSet).unwrap();
assert!(r.read(&mut []).is_err());
- let mut r = MemWriter::new();
- r.seek(10, SeekSet).unwrap();
- assert!(r.write([3]).is_ok());
-
let mut buf = [0];
let mut r = BufWriter::new(buf);
r.seek(10, SeekSet).unwrap();
let mut r = MemReader::new(vec!(10));
assert!(r.seek(-1, SeekSet).is_err());
- let mut r = MemWriter::new();
- assert!(r.seek(-1, SeekSet).is_err());
-
let mut buf = [0];
let mut r = BufWriter::new(buf);
assert!(r.seek(-1, SeekSet).is_err());
fn do_bench_mem_writer(b: &mut Bencher, times: uint, len: uint) {
let src: Vec<u8> = Vec::from_elem(len, 5);
+ b.bytes = (times * len) as u64;
b.iter(|| {
let mut wr = MemWriter::new();
for _ in range(0, times) {
// downcasts.
let (_, wr): (uint, Box<MemWriter>) = mem::transmute_copy(&s.s.out);
let result =
- String::from_utf8(Vec::from_slice(wr.get_ref())).unwrap();
+ String::from_utf8(Vec::from_slice(wr.get_ref().as_slice())).unwrap();
mem::forget(wr);
result.to_string()
}
#[test]
fn test_serialize_round_trip() {
- use serialize::ebml::Doc;
- use serialize::ebml::writer::Encoder;
- use serialize::ebml::reader::Decoder;
+ use serialize::json;
use serialize::{Encodable, Decodable};
let u = Uuid::new_v4();
- let mut wr = MemWriter::new();
- let _ = u.encode(&mut Encoder::new(&mut wr));
- let doc = Doc::new(wr.get_ref());
- let u2 = Decodable::decode(&mut Decoder::new(doc)).unwrap();
+ let s = json::encode(&u);
+ let u2 = json::decode(s.as_slice()).unwrap();
assert_eq!(u, u2);
}
use std::cell::{Cell, RefCell};
use std::io::MemWriter;
use serialize::{Encodable, Decodable};
-use serialize::ebml;
-use serialize::ebml::writer::Encoder;
-use serialize::ebml::reader::Decoder;
+use serialize::json;
#[deriving(Encodable, Decodable)]
struct A {
foo: Cell::new(true),
bar: RefCell::new( A { baz: 2 } )
};
- let mut w = MemWriter::new();
- {
- let mut e = Encoder::new(&mut w);
- match obj.encode(&mut e) {
- Ok(()) => (),
- Err(e) => fail!("Failed to encode: {}", e)
- };
- }
- let doc = ebml::Doc::new(w.get_ref());
- let mut dec = Decoder::new(doc);
- let obj2: B = match Decodable::decode(&mut dec) {
- Ok(v) => v,
- Err(e) => fail!("Failed to decode: {}", e)
- };
+ let s = json::encode(&obj);
+ let obj2: B = json::decode(s.as_slice()).unwrap();
assert!(obj.foo.get() == obj2.foo.get());
assert!(obj.bar.borrow().baz == obj2.bar.borrow().baz);
}
extern crate serialize;
+use std::io;
+use std::io::{IoError, IoResult, SeekStyle};
+use std::slice;
+
use serialize::{Encodable, Encoder};
use serialize::json;
use serialize::ebml::writer;
-use std::io::MemWriter;
+
+static BUF_CAPACITY: uint = 128;
+
+fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
+ // compute offset as signed and clamp to prevent overflow
+ let pos = match seek {
+ io::SeekSet => 0,
+ io::SeekEnd => end,
+ io::SeekCur => cur,
+ } as i64;
+
+ if offset + pos < 0 {
+ Err(IoError {
+ kind: io::InvalidInput,
+ desc: "invalid seek to a negative offset",
+ detail: None
+ })
+ } else {
+ Ok((offset + pos) as u64)
+ }
+}
+
+/// Writes to an owned, growable byte vector that supports seeking.
+///
+/// # Example
+///
+/// ```rust
+/// # #![allow(unused_must_use)]
+/// use std::io::SeekableMemWriter;
+///
+/// let mut w = SeekableMemWriter::new();
+/// w.write([0, 1, 2]);
+///
+/// assert_eq!(w.unwrap(), vec!(0, 1, 2));
+/// ```
+pub struct SeekableMemWriter {
+ buf: Vec<u8>,
+ pos: uint,
+}
+
+impl SeekableMemWriter {
+ /// Create a new `SeekableMemWriter`.
+ #[inline]
+ pub fn new() -> SeekableMemWriter {
+ SeekableMemWriter::with_capacity(BUF_CAPACITY)
+ }
+ /// Create a new `SeekableMemWriter`, allocating at least `n` bytes for
+ /// the internal buffer.
+ #[inline]
+ pub fn with_capacity(n: uint) -> SeekableMemWriter {
+ SeekableMemWriter { buf: Vec::with_capacity(n), pos: 0 }
+ }
+
+ /// Acquires an immutable reference to the underlying buffer of this
+ /// `SeekableMemWriter`.
+ ///
+ /// No method is exposed for acquiring a mutable reference to the buffer
+ /// because it could corrupt the state of this `MemWriter`.
+ #[inline]
+ pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
+
+ /// Unwraps this `SeekableMemWriter`, returning the underlying buffer
+ #[inline]
+ pub fn unwrap(self) -> Vec<u8> { self.buf }
+}
+
+impl Writer for SeekableMemWriter {
+ #[inline]
+ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
+ if self.pos == self.buf.len() {
+ self.buf.push_all(buf)
+ } else {
+ // 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 {
+ slice::bytes::copy_memory(self.buf.mut_slice_from(self.pos), left);
+ }
+ if right.len() > 0 {
+ self.buf.push_all(right);
+ }
+ }
+
+ // Bump us forward
+ self.pos += buf.len();
+ Ok(())
+ }
+}
+
+impl Seek for SeekableMemWriter {
+ #[inline]
+ fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
+
+ #[inline]
+ fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
+ let new = try!(combine(style, self.pos, self.buf.len(), pos));
+ self.pos = new as uint;
+ Ok(())
+ }
+}
#[deriving(Encodable)]
struct Foo {
fn encode_json<'a,
T: Encodable<json::Encoder<'a>,
std::io::IoError>>(val: &T,
- wr: &'a mut MemWriter) {
+ wr: &'a mut SeekableMemWriter) {
let mut encoder = json::Encoder::new(wr);
val.encode(&mut encoder);
}
fn encode_ebml<'a,
- T: Encodable<writer::Encoder<'a, MemWriter>,
+ T: Encodable<writer::Encoder<'a, SeekableMemWriter>,
std::io::IoError>>(val: &T,
- wr: &'a mut MemWriter) {
+ wr: &'a mut SeekableMemWriter) {
let mut encoder = writer::Encoder::new(wr);
val.encode(&mut encoder);
}
pub fn main() {
let target = Foo{baz: false,};
- let mut wr = MemWriter::new();
+ let mut wr = SeekableMemWriter::new();
let proto = JSON;
match proto {
JSON => encode_json(&target, &mut wr),