mirror of
https://github.com/tokio-rs/bytes.git
synced 2026-08-22 00:00:15 +02:00
Add an AppendBuf
This commit is contained in:
+4
-9
@@ -49,20 +49,15 @@ impl MemRef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn bytes(&self) -> &[u8] {
|
pub unsafe fn bytes(&self) -> &[u8] {
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
slice::from_raw_parts(self.bytes_ptr(), self.len())
|
||||||
unsafe {
|
|
||||||
slice::from_raw_parts(self.bytes_ptr(), self.len())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn bytes_mut(&mut self) -> &mut [u8] {
|
pub unsafe fn bytes_mut(&mut self) -> &mut [u8] {
|
||||||
use std::slice;
|
use std::slice;
|
||||||
unsafe {
|
slice::from_raw_parts_mut(self.bytes_ptr(), self.len())
|
||||||
slice::from_raw_parts_mut(self.bytes_ptr(), self.len())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
use alloc;
|
||||||
|
use buf::{MutBuf};
|
||||||
|
use str::{ByteStr, Bytes, SeqByteStr, SmallByteStr};
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::cmp;
|
||||||
|
|
||||||
|
/// A `Buf` backed by a contiguous region of memory.
|
||||||
|
///
|
||||||
|
/// This buffer can only be written to once. Byte strings (immutable views) can
|
||||||
|
/// be created at any time, not just when the writing is complete.
|
||||||
|
pub struct AppendBuf {
|
||||||
|
mem: alloc::MemRef,
|
||||||
|
rd: Cell<u32>, // Read cursor
|
||||||
|
wr: u32, // Write cursor
|
||||||
|
cap: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppendBuf {
|
||||||
|
pub fn with_capacity(mut capacity: u32) -> AppendBuf {
|
||||||
|
// Handle 0 capacity case
|
||||||
|
if capacity == 0 {
|
||||||
|
return AppendBuf::none();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round the capacity to the closest power of 2
|
||||||
|
capacity = capacity.next_power_of_two();
|
||||||
|
|
||||||
|
// Allocate the memory
|
||||||
|
let mem = alloc::heap(capacity as usize);
|
||||||
|
|
||||||
|
// If the allocation failed, return a blank buf
|
||||||
|
if mem.is_none() {
|
||||||
|
return AppendBuf::none();
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendBuf {
|
||||||
|
mem: mem,
|
||||||
|
rd: Cell::new(0),
|
||||||
|
wr: 0,
|
||||||
|
cap: capacity,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an AppendBuf with no capacity
|
||||||
|
pub fn none() -> AppendBuf {
|
||||||
|
AppendBuf {
|
||||||
|
mem: alloc::MemRef::none(),
|
||||||
|
rd: Cell::new(0),
|
||||||
|
wr: 0,
|
||||||
|
cap: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn from_mem_ref(mem: alloc::MemRef, cap: u32, pos: u32) -> AppendBuf {
|
||||||
|
AppendBuf {
|
||||||
|
mem: mem,
|
||||||
|
rd: Cell::new(pos),
|
||||||
|
wr: pos,
|
||||||
|
cap: cap,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bytes(&self) -> &[u8] {
|
||||||
|
let rd = self.rd.get() as usize;
|
||||||
|
let wr = self.wr as usize;
|
||||||
|
unsafe { &self.mem.bytes()[rd..wr] }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shift(&self, n: usize) -> Bytes {
|
||||||
|
let ret = self.slice(0, n);
|
||||||
|
self.rd.set(self.rd.get() + ret.len() as u32);
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn slice(&self, begin: usize, end: usize) -> Bytes {
|
||||||
|
if end <= begin {
|
||||||
|
return Bytes::of(SmallByteStr::zero());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(bytes) = SmallByteStr::from_slice(&self.bytes()[begin..end]) {
|
||||||
|
return Bytes::of(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
let begin = cmp::min(self.wr, begin as u32 + self.rd.get());
|
||||||
|
let end = cmp::min(self.wr, end as u32 + self.rd.get());
|
||||||
|
|
||||||
|
let bytes = unsafe { SeqByteStr::from_mem_ref(self.mem.clone(), begin, end - begin) };
|
||||||
|
|
||||||
|
Bytes::of(bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MutBuf for AppendBuf {
|
||||||
|
fn remaining(&self) -> usize {
|
||||||
|
(self.cap - self.wr) as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn advance(&mut self, cnt: usize) {
|
||||||
|
self.wr += cnt as u32;
|
||||||
|
|
||||||
|
if self.wr > self.cap {
|
||||||
|
self.wr = self.cap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn mut_bytes<'a>(&'a mut self) -> &'a mut [u8] {
|
||||||
|
let wr = self.wr as usize;
|
||||||
|
let cap = self.cap as usize;
|
||||||
|
&mut self.mem.bytes_mut()[wr..cap]
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-5
@@ -103,7 +103,9 @@ impl ByteBuf {
|
|||||||
let cnt = len as u32;
|
let cnt = len as u32;
|
||||||
let pos = self.pos as usize;
|
let pos = self.pos as usize;
|
||||||
|
|
||||||
dst[0..len].copy_from_slice(&self.mem.bytes()[pos..pos+len]);
|
unsafe {
|
||||||
|
dst[0..len].copy_from_slice(&self.mem.bytes()[pos..pos+len]);
|
||||||
|
}
|
||||||
|
|
||||||
self.pos += cnt;
|
self.pos += cnt;
|
||||||
len
|
len
|
||||||
@@ -168,7 +170,7 @@ impl Buf for ByteBuf {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bytes<'a>(&'a self) -> &'a [u8] {
|
fn bytes<'a>(&'a self) -> &'a [u8] {
|
||||||
&self.mem.bytes()[self.pos()..self.lim()]
|
unsafe { &self.mem.bytes()[self.pos()..self.lim()] }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -294,8 +296,10 @@ impl MutByteBuf {
|
|||||||
let cnt = cmp::min(src.len(), self.buf.remaining());
|
let cnt = cmp::min(src.len(), self.buf.remaining());
|
||||||
let pos = self.buf.pos as usize;
|
let pos = self.buf.pos as usize;
|
||||||
|
|
||||||
self.buf.mem.bytes_mut()[pos..pos+cnt]
|
unsafe {
|
||||||
.copy_from_slice(&src[0..cnt]);
|
self.buf.mem.bytes_mut()[pos..pos+cnt]
|
||||||
|
.copy_from_slice(&src[0..cnt]);
|
||||||
|
}
|
||||||
|
|
||||||
self.buf.pos += cnt as u32;
|
self.buf.pos += cnt as u32;
|
||||||
|
|
||||||
@@ -303,7 +307,7 @@ impl MutByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn bytes<'a>(&'a self) -> &'a [u8] {
|
pub fn bytes<'a>(&'a self) -> &'a [u8] {
|
||||||
&self.buf.mem.bytes()[..self.buf.pos()]
|
unsafe { &self.buf.mem.bytes()[..self.buf.pos()] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
mod append;
|
||||||
mod byte;
|
mod byte;
|
||||||
mod ring;
|
mod ring;
|
||||||
mod sink;
|
mod sink;
|
||||||
@@ -5,6 +6,7 @@ mod slice;
|
|||||||
mod source;
|
mod source;
|
||||||
mod take;
|
mod take;
|
||||||
|
|
||||||
|
pub use self::append::AppendBuf;
|
||||||
pub use self::byte::{ByteBuf, MutByteBuf, ROByteBuf};
|
pub use self::byte::{ByteBuf, MutByteBuf, ROByteBuf};
|
||||||
pub use self::ring::RingBuf;
|
pub use self::ring::RingBuf;
|
||||||
pub use self::slice::{SliceBuf, MutSliceBuf};
|
pub use self::slice::{SliceBuf, MutSliceBuf};
|
||||||
|
|||||||
+1
-1
@@ -156,7 +156,7 @@ impl Buf for RingBuf {
|
|||||||
to = self.cap
|
to = self.cap
|
||||||
}
|
}
|
||||||
|
|
||||||
&self.ptr.bytes()[self.pos .. to]
|
unsafe { &self.ptr.bytes()[self.pos .. to] }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn advance(&mut self, cnt: usize) {
|
fn advance(&mut self, cnt: usize) {
|
||||||
|
|||||||
+1
-1
@@ -81,7 +81,7 @@ impl ops::Index<usize> for SeqByteStr {
|
|||||||
|
|
||||||
fn index(&self, index: usize) -> &u8 {
|
fn index(&self, index: usize) -> &u8 {
|
||||||
assert!(index < self.len());
|
assert!(index < self.len());
|
||||||
self.mem.bytes().index(index + self.pos as usize)
|
unsafe { self.mem.bytes().index(index + self.pos as usize) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ extern crate bytes;
|
|||||||
extern crate rand;
|
extern crate rand;
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
|
|
||||||
|
mod test_append;
|
||||||
mod test_buf;
|
mod test_buf;
|
||||||
mod test_buf_fill;
|
mod test_buf_fill;
|
||||||
mod test_buf_take;
|
mod test_buf_take;
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
use bytes::{ByteStr, Buf, MutBuf};
|
||||||
|
use bytes::buf::AppendBuf;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn test_initial_buf_empty() {
|
||||||
|
// Run in a loop a bunch in hope that if there is a memory issue, it will
|
||||||
|
// be exposed
|
||||||
|
for _ in 0..1000 {
|
||||||
|
let mut buf = AppendBuf::with_capacity(100);
|
||||||
|
let mut dst: Vec<u8> = vec![];
|
||||||
|
|
||||||
|
assert_eq!(buf.remaining(), 128);
|
||||||
|
|
||||||
|
buf.write_slice(b"hello world");
|
||||||
|
assert_eq!(buf.remaining(), 117);
|
||||||
|
assert_eq!(buf.bytes(), b"hello world");
|
||||||
|
|
||||||
|
let view1 = buf.slice(0, 11);
|
||||||
|
view1.buf().copy_to(&mut dst).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(dst, b"hello world");
|
||||||
|
assert_eq!(view1, buf.slice(0, 11));
|
||||||
|
|
||||||
|
drop(buf);
|
||||||
|
let mut buf = AppendBuf::with_capacity(100);
|
||||||
|
buf.write_slice(b"zomg no no no no");
|
||||||
|
|
||||||
|
assert_eq!(dst, b"hello world");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user