std: inline many of the Writer/Reader methods
This allows llvm to optimize away much of the overhead from using the MemReader/MemWriters. My benchmarks showed it to shave 15% off of my in progress serialization/json encoding.
This commit is contained in:
parent
76371d1ff1
commit
0f39dc7b78
@ -59,11 +59,13 @@ pub struct MemWriter {
|
||||
|
||||
impl MemWriter {
|
||||
/// Create a new `MemWriter`.
|
||||
#[inline]
|
||||
pub fn new() -> MemWriter {
|
||||
MemWriter::with_capacity(128)
|
||||
}
|
||||
/// 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 }
|
||||
}
|
||||
@ -73,13 +75,16 @@ impl 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() }
|
||||
|
||||
/// Unwraps this `MemWriter`, returning the underlying buffer
|
||||
#[inline]
|
||||
pub fn unwrap(self) -> Vec<u8> { self.buf }
|
||||
}
|
||||
|
||||
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
|
||||
@ -112,7 +117,10 @@ impl Writer for MemWriter {
|
||||
}
|
||||
|
||||
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;
|
||||
@ -140,6 +148,7 @@ pub struct MemReader {
|
||||
impl MemReader {
|
||||
/// Creates a new `MemReader` which will read the buffer given. The buffer
|
||||
/// can be re-acquired through `unwrap`
|
||||
#[inline]
|
||||
pub fn new(buf: Vec<u8>) -> MemReader {
|
||||
MemReader {
|
||||
buf: buf,
|
||||
@ -150,6 +159,7 @@ impl MemReader {
|
||||
/// Tests whether this reader has read all bytes in its buffer.
|
||||
///
|
||||
/// If `true`, then this will no longer return bytes from `read`.
|
||||
#[inline]
|
||||
pub fn eof(&self) -> bool { self.pos >= self.buf.len() }
|
||||
|
||||
/// Acquires an immutable reference to the underlying buffer of this
|
||||
@ -157,13 +167,16 @@ impl MemReader {
|
||||
///
|
||||
/// No method is exposed for acquiring a mutable reference to the buffer
|
||||
/// because it could corrupt the state of this `MemReader`.
|
||||
#[inline]
|
||||
pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
|
||||
|
||||
/// Unwraps this `MemReader`, returning the underlying buffer
|
||||
#[inline]
|
||||
pub fn unwrap(self) -> Vec<u8> { self.buf }
|
||||
}
|
||||
|
||||
impl Reader for MemReader {
|
||||
#[inline]
|
||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
||||
if self.eof() { return Err(io::standard_error(io::EndOfFile)) }
|
||||
|
||||
@ -182,7 +195,10 @@ impl Reader for MemReader {
|
||||
}
|
||||
|
||||
impl Seek for MemReader {
|
||||
#[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;
|
||||
@ -191,6 +207,7 @@ impl Seek for MemReader {
|
||||
}
|
||||
|
||||
impl Buffer for MemReader {
|
||||
#[inline]
|
||||
fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> {
|
||||
if self.pos < self.buf.len() {
|
||||
Ok(self.buf.slice_from(self.pos))
|
||||
@ -198,6 +215,8 @@ impl Buffer for MemReader {
|
||||
Err(io::standard_error(io::EndOfFile))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn consume(&mut self, amt: uint) { self.pos += amt; }
|
||||
}
|
||||
|
||||
@ -227,6 +246,7 @@ pub struct BufWriter<'a> {
|
||||
impl<'a> BufWriter<'a> {
|
||||
/// Creates a new `BufWriter` which will wrap the specified buffer. The
|
||||
/// writer initially starts at position 0.
|
||||
#[inline]
|
||||
pub fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> {
|
||||
BufWriter {
|
||||
buf: buf,
|
||||
@ -236,6 +256,7 @@ impl<'a> BufWriter<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Writer for BufWriter<'a> {
|
||||
#[inline]
|
||||
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||
// return an error if the entire write does not fit in the buffer
|
||||
let max_size = self.buf.len();
|
||||
@ -254,7 +275,10 @@ impl<'a> Writer for BufWriter<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Seek for BufWriter<'a> {
|
||||
#[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;
|
||||
@ -282,6 +306,7 @@ pub struct BufReader<'a> {
|
||||
|
||||
impl<'a> BufReader<'a> {
|
||||
/// Creates a new buffered reader which will read the specified buffer
|
||||
#[inline]
|
||||
pub fn new<'a>(buf: &'a [u8]) -> BufReader<'a> {
|
||||
BufReader {
|
||||
buf: buf,
|
||||
@ -292,10 +317,12 @@ impl<'a> BufReader<'a> {
|
||||
/// Tests whether this reader has read all bytes in its buffer.
|
||||
///
|
||||
/// If `true`, then this will no longer return bytes from `read`.
|
||||
#[inline]
|
||||
pub fn eof(&self) -> bool { self.pos >= self.buf.len() }
|
||||
}
|
||||
|
||||
impl<'a> Reader for BufReader<'a> {
|
||||
#[inline]
|
||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
||||
if self.eof() { return Err(io::standard_error(io::EndOfFile)) }
|
||||
|
||||
@ -314,7 +341,10 @@ impl<'a> Reader for BufReader<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Seek for BufReader<'a> {
|
||||
#[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;
|
||||
@ -323,6 +353,7 @@ impl<'a> Seek for BufReader<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Buffer for BufReader<'a> {
|
||||
#[inline]
|
||||
fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> {
|
||||
if self.pos < self.buf.len() {
|
||||
Ok(self.buf.slice_from(self.pos))
|
||||
@ -330,15 +361,19 @@ impl<'a> Buffer for BufReader<'a> {
|
||||
Err(io::standard_error(io::EndOfFile))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn consume(&mut self, amt: uint) { self.pos += amt; }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
extern crate test;
|
||||
use prelude::*;
|
||||
use super::*;
|
||||
use io::*;
|
||||
use io;
|
||||
use self::test::Bencher;
|
||||
use str::StrSlice;
|
||||
|
||||
#[test]
|
||||
@ -571,4 +606,59 @@ mod test {
|
||||
assert!(r.read_at_least(buf.len(), buf).is_err());
|
||||
assert_eq!(buf.as_slice(), &[7, 8, 6]);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_mem_writer(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let mut wr = MemWriter::new();
|
||||
for _i in range(0, 10) {
|
||||
wr.write([5, .. 10]).unwrap();
|
||||
}
|
||||
assert_eq!(wr.unwrap().as_slice(), [5, .. 100].as_slice());
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_mem_reader(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let buf = Vec::from_slice([5 as u8, ..100]);
|
||||
{
|
||||
let mut rdr = MemReader::new(buf);
|
||||
for _i in range(0, 10) {
|
||||
let mut buf = [0 as u8, .. 10];
|
||||
rdr.read(buf).unwrap();
|
||||
assert_eq!(buf.as_slice(), [5, .. 10].as_slice());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_buf_writer(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let mut buf = [0 as u8, ..100];
|
||||
{
|
||||
let mut wr = BufWriter::new(buf);
|
||||
for _i in range(0, 10) {
|
||||
wr.write([5, .. 10]).unwrap();
|
||||
}
|
||||
}
|
||||
assert_eq!(buf.as_slice(), [5, .. 100].as_slice());
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_buf_reader(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let buf = [5 as u8, ..100];
|
||||
{
|
||||
let mut rdr = BufReader::new(buf);
|
||||
for _i in range(0, 10) {
|
||||
let mut buf = [0 as u8, .. 10];
|
||||
rdr.read(buf).unwrap();
|
||||
assert_eq!(buf.as_slice(), [5, .. 10].as_slice());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1084,6 +1084,7 @@ pub trait Writer {
|
||||
/// If other encodings are desired, it is recommended to compose this stream
|
||||
/// with another performing the conversion, or to use `write` with a
|
||||
/// converted byte-array instead.
|
||||
#[inline]
|
||||
fn write_str(&mut self, s: &str) -> IoResult<()> {
|
||||
self.write(s.as_bytes())
|
||||
}
|
||||
@ -1095,11 +1096,13 @@ pub trait Writer {
|
||||
///
|
||||
/// If other encodings or line ending flavors are desired, it is recommended
|
||||
/// that the `write` method is used specifically instead.
|
||||
#[inline]
|
||||
fn write_line(&mut self, s: &str) -> IoResult<()> {
|
||||
self.write_str(s).and_then(|()| self.write(['\n' as u8]))
|
||||
}
|
||||
|
||||
/// Write a single char, encoded as UTF-8.
|
||||
#[inline]
|
||||
fn write_char(&mut self, c: char) -> IoResult<()> {
|
||||
let mut buf = [0u8, ..4];
|
||||
let n = c.encode_utf8(buf.as_mut_slice());
|
||||
@ -1107,66 +1110,79 @@ pub trait Writer {
|
||||
}
|
||||
|
||||
/// Write the result of passing n through `int::to_str_bytes`.
|
||||
#[inline]
|
||||
fn write_int(&mut self, n: int) -> IoResult<()> {
|
||||
write!(self, "{:d}", n)
|
||||
}
|
||||
|
||||
/// Write the result of passing n through `uint::to_str_bytes`.
|
||||
#[inline]
|
||||
fn write_uint(&mut self, n: uint) -> IoResult<()> {
|
||||
write!(self, "{:u}", n)
|
||||
}
|
||||
|
||||
/// Write a little-endian uint (number of bytes depends on system).
|
||||
#[inline]
|
||||
fn write_le_uint(&mut self, n: uint) -> IoResult<()> {
|
||||
extensions::u64_to_le_bytes(n as u64, uint::BYTES, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a little-endian int (number of bytes depends on system).
|
||||
#[inline]
|
||||
fn write_le_int(&mut self, n: int) -> IoResult<()> {
|
||||
extensions::u64_to_le_bytes(n as u64, int::BYTES, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a big-endian uint (number of bytes depends on system).
|
||||
#[inline]
|
||||
fn write_be_uint(&mut self, n: uint) -> IoResult<()> {
|
||||
extensions::u64_to_be_bytes(n as u64, uint::BYTES, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a big-endian int (number of bytes depends on system).
|
||||
#[inline]
|
||||
fn write_be_int(&mut self, n: int) -> IoResult<()> {
|
||||
extensions::u64_to_be_bytes(n as u64, int::BYTES, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a big-endian u64 (8 bytes).
|
||||
#[inline]
|
||||
fn write_be_u64(&mut self, n: u64) -> IoResult<()> {
|
||||
extensions::u64_to_be_bytes(n, 8u, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a big-endian u32 (4 bytes).
|
||||
#[inline]
|
||||
fn write_be_u32(&mut self, n: u32) -> IoResult<()> {
|
||||
extensions::u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a big-endian u16 (2 bytes).
|
||||
#[inline]
|
||||
fn write_be_u16(&mut self, n: u16) -> IoResult<()> {
|
||||
extensions::u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a big-endian i64 (8 bytes).
|
||||
#[inline]
|
||||
fn write_be_i64(&mut self, n: i64) -> IoResult<()> {
|
||||
extensions::u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a big-endian i32 (4 bytes).
|
||||
#[inline]
|
||||
fn write_be_i32(&mut self, n: i32) -> IoResult<()> {
|
||||
extensions::u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a big-endian i16 (2 bytes).
|
||||
#[inline]
|
||||
fn write_be_i16(&mut self, n: i16) -> IoResult<()> {
|
||||
extensions::u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a big-endian IEEE754 double-precision floating-point (8 bytes).
|
||||
#[inline]
|
||||
fn write_be_f64(&mut self, f: f64) -> IoResult<()> {
|
||||
unsafe {
|
||||
self.write_be_u64(transmute(f))
|
||||
@ -1174,6 +1190,7 @@ pub trait Writer {
|
||||
}
|
||||
|
||||
/// Write a big-endian IEEE754 single-precision floating-point (4 bytes).
|
||||
#[inline]
|
||||
fn write_be_f32(&mut self, f: f32) -> IoResult<()> {
|
||||
unsafe {
|
||||
self.write_be_u32(transmute(f))
|
||||
@ -1181,37 +1198,44 @@ pub trait Writer {
|
||||
}
|
||||
|
||||
/// Write a little-endian u64 (8 bytes).
|
||||
#[inline]
|
||||
fn write_le_u64(&mut self, n: u64) -> IoResult<()> {
|
||||
extensions::u64_to_le_bytes(n, 8u, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a little-endian u32 (4 bytes).
|
||||
#[inline]
|
||||
fn write_le_u32(&mut self, n: u32) -> IoResult<()> {
|
||||
extensions::u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a little-endian u16 (2 bytes).
|
||||
#[inline]
|
||||
fn write_le_u16(&mut self, n: u16) -> IoResult<()> {
|
||||
extensions::u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a little-endian i64 (8 bytes).
|
||||
#[inline]
|
||||
fn write_le_i64(&mut self, n: i64) -> IoResult<()> {
|
||||
extensions::u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a little-endian i32 (4 bytes).
|
||||
#[inline]
|
||||
fn write_le_i32(&mut self, n: i32) -> IoResult<()> {
|
||||
extensions::u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a little-endian i16 (2 bytes).
|
||||
#[inline]
|
||||
fn write_le_i16(&mut self, n: i16) -> IoResult<()> {
|
||||
extensions::u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
|
||||
}
|
||||
|
||||
/// Write a little-endian IEEE754 double-precision floating-point
|
||||
/// (8 bytes).
|
||||
#[inline]
|
||||
fn write_le_f64(&mut self, f: f64) -> IoResult<()> {
|
||||
unsafe {
|
||||
self.write_le_u64(transmute(f))
|
||||
@ -1220,6 +1244,7 @@ pub trait Writer {
|
||||
|
||||
/// Write a little-endian IEEE754 single-precision floating-point
|
||||
/// (4 bytes).
|
||||
#[inline]
|
||||
fn write_le_f32(&mut self, f: f32) -> IoResult<()> {
|
||||
unsafe {
|
||||
self.write_le_u32(transmute(f))
|
||||
@ -1227,11 +1252,13 @@ pub trait Writer {
|
||||
}
|
||||
|
||||
/// Write a u8 (1 byte).
|
||||
#[inline]
|
||||
fn write_u8(&mut self, n: u8) -> IoResult<()> {
|
||||
self.write([n])
|
||||
}
|
||||
|
||||
/// Write an i8 (1 byte).
|
||||
#[inline]
|
||||
fn write_i8(&mut self, n: i8) -> IoResult<()> {
|
||||
self.write([n as u8])
|
||||
}
|
||||
@ -1240,18 +1267,25 @@ pub trait Writer {
|
||||
///
|
||||
/// This is useful to allow applying wrappers while still
|
||||
/// retaining ownership of the original value.
|
||||
#[inline]
|
||||
fn by_ref<'a>(&'a mut self) -> RefWriter<'a, Self> {
|
||||
RefWriter { inner: self }
|
||||
}
|
||||
}
|
||||
|
||||
impl Writer for Box<Writer> {
|
||||
#[inline]
|
||||
fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.write(buf) }
|
||||
|
||||
#[inline]
|
||||
fn flush(&mut self) -> IoResult<()> { self.flush() }
|
||||
}
|
||||
|
||||
impl<'a> Writer for &'a mut Writer {
|
||||
#[inline]
|
||||
fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.write(buf) }
|
||||
|
||||
#[inline]
|
||||
fn flush(&mut self) -> IoResult<()> { self.flush() }
|
||||
}
|
||||
|
||||
@ -1285,7 +1319,10 @@ pub struct RefWriter<'a, W> {
|
||||
}
|
||||
|
||||
impl<'a, W: Writer> Writer for RefWriter<'a, W> {
|
||||
#[inline]
|
||||
fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.inner.write(buf) }
|
||||
|
||||
#[inline]
|
||||
fn flush(&mut self) -> IoResult<()> { self.inner.flush() }
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user