1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use std::io::{IoError, IoResult, SeekStyle};
15 static BUF_CAPACITY: uint = 128;
17 fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
18 // compute offset as signed and clamp to prevent overflow
19 let pos = match seek {
27 kind: io::InvalidInput,
28 desc: "invalid seek to a negative offset",
32 Ok((offset + pos) as u64)
36 /// Writes to an owned, growable byte vector that supports seeking.
41 /// # #![allow(unused_must_use)]
42 /// use rbml::io::SeekableMemWriter;
44 /// let mut w = SeekableMemWriter::new();
45 /// w.write([0, 1, 2]);
47 /// assert_eq!(w.unwrap(), vec!(0, 1, 2));
49 pub struct SeekableMemWriter {
54 impl SeekableMemWriter {
55 /// Create a new `SeekableMemWriter`.
57 pub fn new() -> SeekableMemWriter {
58 SeekableMemWriter::with_capacity(BUF_CAPACITY)
60 /// Create a new `SeekableMemWriter`, allocating at least `n` bytes for
61 /// the internal buffer.
63 pub fn with_capacity(n: uint) -> SeekableMemWriter {
64 SeekableMemWriter { buf: Vec::with_capacity(n), pos: 0 }
67 /// Acquires an immutable reference to the underlying buffer of this
68 /// `SeekableMemWriter`.
70 /// No method is exposed for acquiring a mutable reference to the buffer
71 /// because it could corrupt the state of this `MemWriter`.
73 pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
75 /// Unwraps this `SeekableMemWriter`, returning the underlying buffer
77 pub fn unwrap(self) -> Vec<u8> { self.buf }
80 impl Writer for SeekableMemWriter {
82 fn write(&mut self, buf: &[u8]) -> IoResult<()> {
83 if self.pos == self.buf.len() {
84 self.buf.push_all(buf)
86 // Make sure the internal buffer is as least as big as where we
88 let difference = self.pos as i64 - self.buf.len() as i64;
90 self.buf.grow(difference as uint, &0);
93 // Figure out what bytes will be used to overwrite what's currently
94 // there (left), and what will be appended on the end (right)
95 let cap = self.buf.len() - self.pos;
96 let (left, right) = if cap <= buf.len() {
97 (buf.slice_to(cap), buf.slice_from(cap))
99 let result: (_, &[_]) = (buf, &[]);
103 // Do the necessary writes
105 slice::bytes::copy_memory(self.buf.mut_slice_from(self.pos), left);
108 self.buf.push_all(right);
113 self.pos += buf.len();
118 impl Seek for SeekableMemWriter {
120 fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
123 fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
124 let new = try!(combine(style, self.pos, self.buf.len(), pos));
125 self.pos = new as uint;
133 use super::SeekableMemWriter;
138 fn test_seekable_mem_writer() {
139 let mut writer = SeekableMemWriter::new();
140 assert_eq!(writer.tell(), Ok(0));
141 writer.write([0]).unwrap();
142 assert_eq!(writer.tell(), Ok(1));
143 writer.write([1, 2, 3]).unwrap();
144 writer.write([4, 5, 6, 7]).unwrap();
145 assert_eq!(writer.tell(), Ok(8));
146 let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
147 assert_eq!(writer.get_ref(), b);
149 writer.seek(0, io::SeekSet).unwrap();
150 assert_eq!(writer.tell(), Ok(0));
151 writer.write([3, 4]).unwrap();
152 let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7];
153 assert_eq!(writer.get_ref(), b);
155 writer.seek(1, io::SeekCur).unwrap();
156 writer.write([0, 1]).unwrap();
157 let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7];
158 assert_eq!(writer.get_ref(), b);
160 writer.seek(-1, io::SeekEnd).unwrap();
161 writer.write([1, 2]).unwrap();
162 let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2];
163 assert_eq!(writer.get_ref(), b);
165 writer.seek(1, io::SeekEnd).unwrap();
166 writer.write([1]).unwrap();
167 let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1];
168 assert_eq!(writer.get_ref(), b);
173 let mut r = SeekableMemWriter::new();
174 r.seek(10, io::SeekSet).unwrap();
175 assert!(r.write([3]).is_ok());
180 let mut r = SeekableMemWriter::new();
181 assert!(r.seek(-1, io::SeekSet).is_err());
184 fn do_bench_seekable_mem_writer(b: &mut Bencher, times: uint, len: uint) {
185 let src: Vec<u8> = Vec::from_elem(len, 5);
187 b.bytes = (times * len) as u64;
189 let mut wr = SeekableMemWriter::new();
190 for _ in range(0, times) {
191 wr.write(src.as_slice()).unwrap();
195 assert_eq!(v.len(), times * len);
196 assert!(v.iter().all(|x| *x == 5));
201 fn bench_seekable_mem_writer_001_0000(b: &mut Bencher) {
202 do_bench_seekable_mem_writer(b, 1, 0)
206 fn bench_seekable_mem_writer_001_0010(b: &mut Bencher) {
207 do_bench_seekable_mem_writer(b, 1, 10)
211 fn bench_seekable_mem_writer_001_0100(b: &mut Bencher) {
212 do_bench_seekable_mem_writer(b, 1, 100)
216 fn bench_seekable_mem_writer_001_1000(b: &mut Bencher) {
217 do_bench_seekable_mem_writer(b, 1, 1000)
221 fn bench_seekable_mem_writer_100_0000(b: &mut Bencher) {
222 do_bench_seekable_mem_writer(b, 100, 0)
226 fn bench_seekable_mem_writer_100_0010(b: &mut Bencher) {
227 do_bench_seekable_mem_writer(b, 100, 10)
231 fn bench_seekable_mem_writer_100_0100(b: &mut Bencher) {
232 do_bench_seekable_mem_writer(b, 100, 100)
236 fn bench_seekable_mem_writer_100_1000(b: &mut Bencher) {
237 do_bench_seekable_mem_writer(b, 100, 1000)