Skip to content
Snippets Groups Projects
Commit 296cac26 authored by Carl Lerche's avatar Carl Lerche
Browse files

Implement buffer traits on Vec<u8>, &[u8], Cursor

parent 23ad12f8
No related branches found
No related tags found
No related merge requests found
...@@ -9,6 +9,9 @@ use std::{cmp, ptr}; ...@@ -9,6 +9,9 @@ use std::{cmp, ptr};
*/ */
/// A `Buf` backed by a contiguous region of memory. /// A `Buf` backed by a contiguous region of memory.
///
/// This `Buf` is better suited for cases where there is a clear delineation
/// between reading and writing.
pub struct ByteBuf { pub struct ByteBuf {
mem: alloc::MemRef, mem: alloc::MemRef,
cap: u32, cap: u32,
......
...@@ -9,7 +9,7 @@ pub use self::ring::RingBuf; ...@@ -9,7 +9,7 @@ pub use self::ring::RingBuf;
pub use self::slice::{SliceBuf, MutSliceBuf}; pub use self::slice::{SliceBuf, MutSliceBuf};
use {BufError, RopeBuf}; use {BufError, RopeBuf};
use std::{cmp, fmt, io, ptr}; use std::{cmp, fmt, io, ptr, usize};
/// A trait for values that provide sequential read access to bytes. /// A trait for values that provide sequential read access to bytes.
pub trait Buf { pub trait Buf {
...@@ -312,6 +312,77 @@ impl fmt::Debug for Box<Buf+'static> { ...@@ -312,6 +312,77 @@ impl fmt::Debug for Box<Buf+'static> {
} }
} }
impl Buf for io::Cursor<Vec<u8>> {
fn remaining(&self) -> usize {
self.get_ref().len() - self.position() as usize
}
fn bytes(&self) -> &[u8] {
let pos = self.position() as usize;
&(&self.get_ref())[pos..]
}
fn advance(&mut self, cnt: usize) {
let pos = self.position() as usize;
let pos = cmp::min(self.get_ref().len(), pos + cnt);
self.set_position(pos as u64);
}
}
impl MutBuf for Vec<u8> {
fn remaining(&self) -> usize {
usize::MAX - self.len()
}
fn advance(&mut self, cnt: usize) {
let len = self.len() + cnt;
if len > self.capacity() {
// Reserve additional
// TODO: Should this case panic?
let cap = self.capacity();
self.reserve(cap - len);
}
unsafe {
self.set_len(len);
}
}
fn mut_bytes(&mut self) -> &mut [u8] {
use std::slice;
if self.capacity() == self.len() {
self.reserve(64); // Grow the vec
}
let cap = self.capacity();
let len = self.len();
unsafe {
let ptr = self.as_mut_ptr();
&mut slice::from_raw_parts_mut(ptr, cap)[len..]
}
}
}
impl<'a> Buf for io::Cursor<&'a [u8]> {
fn remaining(&self) -> usize {
self.get_ref().len() - self.position() as usize
}
fn bytes(&self) -> &[u8] {
let pos = self.position() as usize;
&(&self.get_ref())[pos..]
}
fn advance(&mut self, cnt: usize) {
let pos = self.position() as usize;
let pos = cmp::min(self.get_ref().len(), pos + cnt);
self.set_position(pos as u64);
}
}
/* /*
* *
* ===== Read impls ===== * ===== Read impls =====
......
...@@ -9,6 +9,8 @@ enum Mark { ...@@ -9,6 +9,8 @@ enum Mark {
/// Buf backed by a continous chunk of memory. Maintains a read cursor and a /// Buf backed by a continous chunk of memory. Maintains a read cursor and a
/// write cursor. When reads and writes reach the end of the allocated buffer, /// write cursor. When reads and writes reach the end of the allocated buffer,
/// wraps around to the start. /// wraps around to the start.
///
/// This type is suited for use cases where reads and writes are intermixed.
pub struct RingBuf { pub struct RingBuf {
ptr: alloc::MemRef, // Pointer to the memory ptr: alloc::MemRef, // Pointer to the memory
cap: usize, // Capacity of the buffer cap: usize, // Capacity of the buffer
...@@ -19,6 +21,7 @@ pub struct RingBuf { ...@@ -19,6 +21,7 @@ pub struct RingBuf {
// TODO: There are most likely many optimizations that can be made // TODO: There are most likely many optimizations that can be made
impl RingBuf { impl RingBuf {
/// Allocates a new `RingBuf` with the specified capacity.
pub fn new(mut capacity: usize) -> RingBuf { pub fn new(mut capacity: usize) -> RingBuf {
// Handle the 0 length buffer case // Handle the 0 length buffer case
if capacity == 0 { if capacity == 0 {
...@@ -45,14 +48,17 @@ impl RingBuf { ...@@ -45,14 +48,17 @@ impl RingBuf {
} }
} }
/// Returns `true` if the buf cannot accept any further writes.
pub fn is_full(&self) -> bool { pub fn is_full(&self) -> bool {
self.cap == self.len self.cap == self.len
} }
/// Returns `true` if the buf cannot accept any further reads.
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.len == 0 self.len == 0
} }
/// Returns the number of bytes that the buf can hold.
pub fn capacity(&self) -> usize { pub fn capacity(&self) -> usize {
self.cap self.cap
} }
...@@ -85,10 +91,12 @@ impl RingBuf { ...@@ -85,10 +91,12 @@ impl RingBuf {
} }
} }
/// Returns the number of bytes remaining to read.
fn read_remaining(&self) -> usize { fn read_remaining(&self) -> usize {
self.len self.len
} }
/// Returns the remaining write capacity until which the buf becomes full.
fn write_remaining(&self) -> usize { fn write_remaining(&self) -> usize {
self.cap - self.len self.cap - self.len
} }
......
use bytes::{Buf, MutBuf, MutBufExt};
use std::usize;
use std::io::{Cursor};
#[test]
pub fn test_fresh_cursor_vec() {
let mut buf = Cursor::new(b"hello".to_vec());
assert_eq!(buf.remaining(), 5);
assert_eq!(buf.bytes(), b"hello");
buf.advance(2);
assert_eq!(buf.remaining(), 3);
assert_eq!(buf.bytes(), b"llo");
buf.advance(3);
assert_eq!(buf.remaining(), 0);
assert_eq!(buf.bytes(), b"");
buf.advance(1);
assert_eq!(buf.remaining(), 0);
assert_eq!(buf.bytes(), b"");
}
#[test]
pub fn test_vec_as_mut_buf() {
let mut buf = vec![];
assert_eq!(buf.remaining(), usize::MAX);
assert_eq!(buf.mut_bytes().len(), 64);
buf.write(&b"zomg"[..]).unwrap();
assert_eq!(&buf, b"zomg");
assert_eq!(buf.remaining(), usize::MAX - 4);
assert_eq!(buf.capacity(), 64);
for _ in 0..16 {
buf.write(&b"zomg"[..]).unwrap();
}
assert_eq!(buf.len(), 68);
assert_eq!(buf.capacity(), 128);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment