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::old_io::{IoError, IoResult, SeekStyle};
14 use std::iter::repeat;
16 const BUF_CAPACITY: uint = 128;
18 fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
19 // compute offset as signed and clamp to prevent overflow
20 let pos = match seek {
22 old_io::SeekEnd => end,
23 old_io::SeekCur => cur,
28 kind: old_io::InvalidInput,
29 desc: "invalid seek to a negative offset",
33 Ok((offset + pos) as u64)
37 /// Writes to an owned, growable byte vector that supports seeking.
42 /// # #![allow(unused_must_use)]
43 /// use rbml::io::SeekableMemWriter;
45 /// let mut w = SeekableMemWriter::new();
46 /// w.write(&[0, 1, 2]);
48 /// assert_eq!(w.unwrap(), [0, 1, 2]);
50 pub struct SeekableMemWriter {
55 impl SeekableMemWriter {
56 /// Create a new `SeekableMemWriter`.
58 pub fn new() -> SeekableMemWriter {
59 SeekableMemWriter::with_capacity(BUF_CAPACITY)
61 /// Create a new `SeekableMemWriter`, allocating at least `n` bytes for
62 /// the internal buffer.
64 pub fn with_capacity(n: uint) -> SeekableMemWriter {
65 SeekableMemWriter { buf: Vec::with_capacity(n), pos: 0 }
68 /// Acquires an immutable reference to the underlying buffer of this
69 /// `SeekableMemWriter`.
71 /// No method is exposed for acquiring a mutable reference to the buffer
72 /// because it could corrupt the state of this `MemWriter`.
74 pub fn get_ref<'a>(&'a self) -> &'a [u8] { &self.buf }
76 /// Unwraps this `SeekableMemWriter`, returning the underlying buffer
78 pub fn unwrap(self) -> Vec<u8> { self.buf }
81 impl Writer for SeekableMemWriter {
83 fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
84 if self.pos == self.buf.len() {
85 self.buf.push_all(buf)
87 // Make sure the internal buffer is as least as big as where we
89 let difference = self.pos as i64 - self.buf.len() as i64;
91 self.buf.extend(repeat(0).take(difference as uint));
94 // Figure out what bytes will be used to overwrite what's currently
95 // there (left), and what will be appended on the end (right)
96 let cap = self.buf.len() - self.pos;
97 let (left, right) = if cap <= buf.len() {
98 (&buf[..cap], &buf[cap..])
100 let result: (_, &[_]) = (buf, &[]);
104 // Do the necessary writes
106 slice::bytes::copy_memory(&mut self.buf[self.pos..], left);
109 self.buf.push_all(right);
114 self.pos += buf.len();
119 impl Seek for SeekableMemWriter {
121 fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
124 fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
125 let new = try!(combine(style, self.pos, self.buf.len(), pos));
126 self.pos = new as uint;
134 use super::SeekableMemWriter;
136 use std::iter::repeat;
140 fn test_seekable_mem_writer() {
141 let mut writer = SeekableMemWriter::new();
142 assert_eq!(writer.tell(), Ok(0));
143 writer.write_all(&[0]).unwrap();
144 assert_eq!(writer.tell(), Ok(1));
145 writer.write_all(&[1, 2, 3]).unwrap();
146 writer.write_all(&[4, 5, 6, 7]).unwrap();
147 assert_eq!(writer.tell(), Ok(8));
148 let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
149 assert_eq!(writer.get_ref(), b);
151 writer.seek(0, old_io::SeekSet).unwrap();
152 assert_eq!(writer.tell(), Ok(0));
153 writer.write_all(&[3, 4]).unwrap();
154 let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7];
155 assert_eq!(writer.get_ref(), b);
157 writer.seek(1, old_io::SeekCur).unwrap();
158 writer.write_all(&[0, 1]).unwrap();
159 let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7];
160 assert_eq!(writer.get_ref(), b);
162 writer.seek(-1, old_io::SeekEnd).unwrap();
163 writer.write_all(&[1, 2]).unwrap();
164 let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2];
165 assert_eq!(writer.get_ref(), b);
167 writer.seek(1, old_io::SeekEnd).unwrap();
168 writer.write_all(&[1]).unwrap();
169 let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1];
170 assert_eq!(writer.get_ref(), b);
175 let mut r = SeekableMemWriter::new();
176 r.seek(10, old_io::SeekSet).unwrap();
177 assert!(r.write_all(&[3]).is_ok());
182 let mut r = SeekableMemWriter::new();
183 assert!(r.seek(-1, old_io::SeekSet).is_err());
186 fn do_bench_seekable_mem_writer(b: &mut Bencher, times: uint, len: uint) {
187 let src: Vec<u8> = repeat(5).take(len).collect();
189 b.bytes = (times * len) as u64;
191 let mut wr = SeekableMemWriter::new();
193 wr.write_all(&src).unwrap();
197 assert_eq!(v.len(), times * len);
198 assert!(v.iter().all(|x| *x == 5));
203 fn bench_seekable_mem_writer_001_0000(b: &mut Bencher) {
204 do_bench_seekable_mem_writer(b, 1, 0)
208 fn bench_seekable_mem_writer_001_0010(b: &mut Bencher) {
209 do_bench_seekable_mem_writer(b, 1, 10)
213 fn bench_seekable_mem_writer_001_0100(b: &mut Bencher) {
214 do_bench_seekable_mem_writer(b, 1, 100)
218 fn bench_seekable_mem_writer_001_1000(b: &mut Bencher) {
219 do_bench_seekable_mem_writer(b, 1, 1000)
223 fn bench_seekable_mem_writer_100_0000(b: &mut Bencher) {
224 do_bench_seekable_mem_writer(b, 100, 0)
228 fn bench_seekable_mem_writer_100_0010(b: &mut Bencher) {
229 do_bench_seekable_mem_writer(b, 100, 10)
233 fn bench_seekable_mem_writer_100_0100(b: &mut Bencher) {
234 do_bench_seekable_mem_writer(b, 100, 100)
238 fn bench_seekable_mem_writer_100_1000(b: &mut Bencher) {
239 do_bench_seekable_mem_writer(b, 100, 1000)