mirror of
https://github.com/tokio-rs/bytes.git
synced 2026-08-24 00:00:14 +02:00
Implement buffer traits on Vec<u8>, &[u8], Cursor
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
+72
-1
@@ -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> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
|||||||
/// 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 {
|
|||||||
|
|
||||||
// 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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user