mirror of
https://github.com/tokio-rs/bytes.git
synced 2026-08-13 00:00:32 +02:00
Huge overhaul of bytes
* Get rid of `ByteStr` trait * `Bytes` is not a concrete type * Add `BlockBuf` * Delete lots of cruft * Performance work
This commit is contained in:
+40
-21
@@ -1,8 +1,7 @@
|
||||
use alloc;
|
||||
use buf::{MutBuf};
|
||||
use str::{ByteStr, Bytes, SeqByteStr, SmallByteStr};
|
||||
use bytes::Bytes;
|
||||
use std::cell::Cell;
|
||||
use std::cmp;
|
||||
|
||||
/// A `Buf` backed by a contiguous region of memory.
|
||||
///
|
||||
@@ -33,12 +32,7 @@ impl AppendBuf {
|
||||
return AppendBuf::none();
|
||||
}
|
||||
|
||||
AppendBuf {
|
||||
mem: mem,
|
||||
rd: Cell::new(0),
|
||||
wr: 0,
|
||||
cap: capacity,
|
||||
}
|
||||
unsafe { AppendBuf::from_mem_ref(mem, capacity, 0) }
|
||||
}
|
||||
|
||||
/// Returns an AppendBuf with no capacity
|
||||
@@ -60,10 +54,20 @@ impl AppendBuf {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
(self.wr - self.rd.get()) as usize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn capacity(&self) -> usize {
|
||||
(self.cap - self.rd.get()) as usize
|
||||
}
|
||||
|
||||
pub fn bytes(&self) -> &[u8] {
|
||||
let rd = self.rd.get() as usize;
|
||||
let wr = self.wr as usize;
|
||||
unsafe { &self.mem.bytes()[rd..wr] }
|
||||
unsafe { &self.mem.bytes_slice(rd, wr) }
|
||||
}
|
||||
|
||||
pub fn shift(&self, n: usize) -> Bytes {
|
||||
@@ -72,29 +76,37 @@ impl AppendBuf {
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn drop(&self, n: usize) {
|
||||
assert!(n <= self.len());
|
||||
self.rd.set(self.rd.get() + n as u32);
|
||||
}
|
||||
|
||||
pub fn slice(&self, begin: usize, end: usize) -> Bytes {
|
||||
if end <= begin {
|
||||
return Bytes::of(SmallByteStr::zero());
|
||||
}
|
||||
let rd = self.rd.get() as usize;
|
||||
let wr = self.wr as usize;
|
||||
|
||||
if let Some(bytes) = SmallByteStr::from_slice(&self.bytes()[begin..end]) {
|
||||
return Bytes::of(bytes);
|
||||
}
|
||||
assert!(begin <= end && end <= wr - rd, "invalid range");
|
||||
|
||||
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 begin = (begin + rd) as u32;
|
||||
let end = (end + rd) as u32;
|
||||
|
||||
let bytes = unsafe { SeqByteStr::from_mem_ref(self.mem.clone(), begin, end - begin) };
|
||||
|
||||
Bytes::of(bytes)
|
||||
unsafe { Bytes::from_mem_ref(self.mem.clone(), begin, end - begin) }
|
||||
}
|
||||
}
|
||||
|
||||
impl MutBuf for AppendBuf {
|
||||
#[inline]
|
||||
fn remaining(&self) -> usize {
|
||||
(self.cap - self.wr) as usize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn has_remaining(&self) -> bool {
|
||||
// Implemented as an equality for the perfz
|
||||
self.cap != self.wr
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn advance(&mut self, cnt: usize) {
|
||||
self.wr += cnt as u32;
|
||||
|
||||
@@ -103,9 +115,16 @@ impl MutBuf for AppendBuf {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
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]
|
||||
self.mem.mut_bytes_slice(wr, cap)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for AppendBuf {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.bytes()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
#![allow(warnings)]
|
||||
|
||||
use {Buf, MutBuf, AppendBuf, Bytes};
|
||||
use alloc::{self, Pool};
|
||||
use std::{cmp, ptr, slice};
|
||||
use std::io::Cursor;
|
||||
use std::rc::Rc;
|
||||
use std::collections::{vec_deque, VecDeque};
|
||||
|
||||
/// Append only buffer backed by a chain of `AppendBuf` buffers.
|
||||
///
|
||||
/// Each `AppendBuf` block is of a fixed size and allocated on demand. This
|
||||
/// makes the total capacity of a `BlockBuf` potentially much larger than what
|
||||
/// is currently allocated.
|
||||
pub struct BlockBuf {
|
||||
len: usize,
|
||||
cap: usize,
|
||||
blocks: VecDeque<AppendBuf>,
|
||||
new_block: NewBlock,
|
||||
}
|
||||
|
||||
pub enum NewBlock {
|
||||
Heap(usize),
|
||||
Pool(Rc<Pool>),
|
||||
}
|
||||
|
||||
pub struct BlockBufCursor<'a> {
|
||||
rem: usize,
|
||||
blocks: vec_deque::Iter<'a, AppendBuf>,
|
||||
curr: Option<Cursor<&'a [u8]>>,
|
||||
}
|
||||
|
||||
// TODO:
|
||||
//
|
||||
// - Add `comapct` fn which moves all buffered data into one block.
|
||||
// - Add `slice` fn which returns `Bytes` for arbitrary views into the Buf
|
||||
//
|
||||
impl BlockBuf {
|
||||
/// Create BlockBuf
|
||||
pub fn new(max_blocks: usize, new_block: NewBlock) -> BlockBuf {
|
||||
assert!(max_blocks > 1, "at least 2 blocks required");
|
||||
|
||||
BlockBuf {
|
||||
len: 0,
|
||||
cap: max_blocks * new_block.block_size(),
|
||||
blocks: VecDeque::with_capacity(max_blocks),
|
||||
new_block: new_block,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of buffered bytes
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
debug_assert!(self.len == self.blocks.iter().map(|b| b.len()).fold(0, |a, b| a+b));
|
||||
self.len
|
||||
}
|
||||
|
||||
/// Returns true if there are no buffered bytes
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
return self.len() == 0
|
||||
}
|
||||
|
||||
/// Returns a `Buf` for the currently buffered bytes.
|
||||
#[inline]
|
||||
pub fn buf(&self) -> BlockBufCursor {
|
||||
let mut iter = self.blocks.iter();
|
||||
|
||||
// Get the next leaf node buffer
|
||||
let block = iter.next()
|
||||
.map(|block| Cursor::new(block.bytes()));
|
||||
|
||||
BlockBufCursor {
|
||||
rem: self.len(),
|
||||
blocks: iter,
|
||||
curr: block,
|
||||
}
|
||||
}
|
||||
|
||||
/// Consumes `n` buffered bytes, returning them as an immutable `Bytes`
|
||||
/// value.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `n` is greater than the number of buffered bytes.
|
||||
pub fn shift(&mut self, mut n: usize) -> Bytes {
|
||||
trace!("BlockBuf::shift; n={}", n);
|
||||
|
||||
let mut ret: Option<Bytes> = None;
|
||||
|
||||
while n > 0 {
|
||||
if !self.have_buffered_data() {
|
||||
panic!("shift len out of buffered range");
|
||||
}
|
||||
|
||||
let (segment, pop) = {
|
||||
let block = self.blocks.front().expect("unexpected state");
|
||||
|
||||
let segment_n = cmp::min(n, block.len());
|
||||
n -= segment_n;
|
||||
self.len -= segment_n;
|
||||
|
||||
(block.shift(segment_n), !MutBuf::has_remaining(block))
|
||||
};
|
||||
|
||||
if pop {
|
||||
let _ = self.blocks.pop_front();
|
||||
}
|
||||
|
||||
ret = Some(match ret.take() {
|
||||
Some(curr) => curr.concat(&segment),
|
||||
None => segment,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
ret.unwrap_or(Bytes::empty())
|
||||
}
|
||||
|
||||
/// Drop the first `n` buffered bytes
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `n` is greater than the number of buffered bytes.
|
||||
pub fn drop(&mut self, mut n: usize) {
|
||||
while n > 0 {
|
||||
if !self.have_buffered_data() {
|
||||
panic!("shift len out of buffered range");
|
||||
}
|
||||
|
||||
let pop = {
|
||||
let block = self.blocks.front().expect("unexpected state");
|
||||
|
||||
let segment_n = cmp::min(n, block.len());
|
||||
n -= segment_n;
|
||||
self.len -= segment_n;
|
||||
|
||||
block.drop(segment_n);
|
||||
|
||||
!MutBuf::has_remaining(block)
|
||||
};
|
||||
|
||||
if pop {
|
||||
let _ = self.blocks.pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Moves all buffered bytes into a single block.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the buffered bytes cannot fit in a single block.
|
||||
pub fn compact(&mut self) {
|
||||
trace!("BlockBuf::compact; attempting compaction");
|
||||
|
||||
if self.can_compact() {
|
||||
trace!("BlockBuf::compact; data not aligned at start -- compacting");
|
||||
|
||||
let mut compacted = self.new_block.new_block()
|
||||
.expect("unable to allocate block");
|
||||
|
||||
for block in self.blocks.drain(..) {
|
||||
compacted.write_slice(block.bytes());
|
||||
}
|
||||
|
||||
assert!(self.blocks.is_empty(), "blocks not removed");
|
||||
|
||||
self.blocks.push_back(compacted);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn can_compact(&self) -> bool {
|
||||
if self.blocks.len() > 1 {
|
||||
return true;
|
||||
}
|
||||
|
||||
self.blocks.front()
|
||||
.map(|b| b.capacity() != self.new_block.block_size())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Return byte slice if bytes are in sequential memory
|
||||
#[inline]
|
||||
pub fn bytes(&self) -> Option<&[u8]> {
|
||||
match self.blocks.len() {
|
||||
0 => Some(unsafe { slice::from_raw_parts(ptr::null(), 0) }),
|
||||
1 => self.blocks.front().map(|b| b.bytes()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn block_size(&self) -> usize {
|
||||
self.new_block.block_size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn allocate_block(&mut self) {
|
||||
if let Some(block) = self.new_block.new_block() {
|
||||
// Store the block
|
||||
self.blocks.push_back(block);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn have_buffered_data(&self) -> bool {
|
||||
self.len() > 0
|
||||
}
|
||||
}
|
||||
|
||||
impl MutBuf for BlockBuf {
|
||||
#[inline]
|
||||
fn remaining(&self) -> usize {
|
||||
// TODO: Ensure that the allocator has enough capacity to provide the
|
||||
// remaining bytes
|
||||
self.cap - self.len
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn has_remaining(&self) -> bool {
|
||||
// TODO: Ensure that the allocator has enough capacity to provide the
|
||||
// remaining bytes
|
||||
self.cap != self.len
|
||||
}
|
||||
|
||||
unsafe fn advance(&mut self, cnt: usize) {
|
||||
trace!("BlockBuf::advance; cnt={:?}", cnt);
|
||||
|
||||
// `mut_bytes` only returns bytes from the last block, thus it should
|
||||
// only be possible to advance the last block
|
||||
if let Some(buf) = self.blocks.back_mut() {
|
||||
self.len += cnt;
|
||||
buf.advance(cnt);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn mut_bytes(&mut self) -> &mut [u8] {
|
||||
let mut need_alloc = true;
|
||||
|
||||
if let Some(buf) = self.blocks.back() {
|
||||
// `unallocated_blocks` is checked here because if further blocks
|
||||
// cannot be allocated, an empty slice should be returned.
|
||||
if MutBuf::has_remaining(buf) {
|
||||
need_alloc = false
|
||||
}
|
||||
}
|
||||
|
||||
if need_alloc {
|
||||
if self.blocks.len() != self.blocks.capacity() {
|
||||
self.allocate_block()
|
||||
}
|
||||
}
|
||||
|
||||
self.blocks.back_mut()
|
||||
.map(|buf| buf.mut_bytes())
|
||||
.unwrap_or(slice::from_raw_parts_mut(ptr::null_mut(), 0))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for BlockBuf {
|
||||
fn default() -> BlockBuf {
|
||||
BlockBuf::new(16, NewBlock::Heap(8_192))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Buf for BlockBufCursor<'a> {
|
||||
fn remaining(&self) -> usize {
|
||||
self.rem
|
||||
}
|
||||
|
||||
fn bytes(&self) -> &[u8] {
|
||||
self.curr.as_ref()
|
||||
.map(|buf| Buf::bytes(buf))
|
||||
.unwrap_or(unsafe { slice::from_raw_parts(ptr::null(), 0)})
|
||||
}
|
||||
|
||||
fn advance(&mut self, mut cnt: usize) {
|
||||
cnt = cmp::min(cnt, self.rem);
|
||||
|
||||
// Advance the internal cursor
|
||||
self.rem -= cnt;
|
||||
|
||||
// Advance the leaf buffer
|
||||
while cnt > 0 {
|
||||
{
|
||||
let curr = self.curr.as_mut()
|
||||
.expect("expected a value");
|
||||
|
||||
if curr.remaining() > cnt {
|
||||
curr.advance(cnt);
|
||||
break;
|
||||
}
|
||||
|
||||
cnt -= curr.remaining();
|
||||
}
|
||||
|
||||
self.curr = self.blocks.next()
|
||||
.map(|block| Cursor::new(block.bytes()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NewBlock {
|
||||
#[inline]
|
||||
fn block_size(&self) -> usize {
|
||||
match *self {
|
||||
NewBlock::Heap(size) => size,
|
||||
NewBlock::Pool(ref pool) => pool.buffer_len(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn new_block(&self) -> Option<AppendBuf> {
|
||||
match *self {
|
||||
NewBlock::Heap(size) => Some(AppendBuf::with_capacity(size as u32)),
|
||||
NewBlock::Pool(ref pool) => pool.new_append_buf(),
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
-90
@@ -1,4 +1,4 @@
|
||||
use {alloc, Buf, Bytes, MutBuf, SeqByteStr, MAX_CAPACITY};
|
||||
use {alloc, Buf, MutBuf, Bytes, MAX_CAPACITY};
|
||||
use std::{cmp, fmt};
|
||||
|
||||
/*
|
||||
@@ -98,30 +98,17 @@ impl ByteBuf {
|
||||
MutByteBuf { buf: self }
|
||||
}
|
||||
|
||||
pub fn read_slice(&mut self, dst: &mut [u8]) -> usize {
|
||||
let len = cmp::min(dst.len(), self.remaining());
|
||||
pub fn read_slice(&mut self, dst: &mut [u8]) {
|
||||
assert!(self.remaining() >= dst.len());
|
||||
let len = dst.len();
|
||||
let cnt = len as u32;
|
||||
let pos = self.pos as usize;
|
||||
|
||||
unsafe {
|
||||
dst[0..len].copy_from_slice(&self.mem.bytes()[pos..pos+len]);
|
||||
dst.copy_from_slice(&self.mem.bytes()[pos..pos+len]);
|
||||
}
|
||||
|
||||
self.pos += cnt;
|
||||
len
|
||||
}
|
||||
|
||||
pub fn to_seq_byte_str(self) -> SeqByteStr {
|
||||
unsafe {
|
||||
let ByteBuf { mem, pos, lim, .. } = self;
|
||||
SeqByteStr::from_mem_ref(
|
||||
mem, pos, lim - pos)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_bytes(self) -> Bytes {
|
||||
Bytes::of(self.to_seq_byte_str())
|
||||
}
|
||||
|
||||
/// Marks the current read location.
|
||||
@@ -180,84 +167,21 @@ impl Buf for ByteBuf {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_slice(&mut self, dst: &mut [u8]) -> usize {
|
||||
fn read_slice(&mut self, dst: &mut [u8]) {
|
||||
ByteBuf::read_slice(self, dst)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ByteBuf {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.bytes().fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* ===== ROByteBuf =====
|
||||
*
|
||||
*/
|
||||
|
||||
/// Same as `ByteBuf` but cannot be flipped to a `MutByteBuf`.
|
||||
pub struct ROByteBuf {
|
||||
buf: ByteBuf,
|
||||
}
|
||||
|
||||
impl ROByteBuf {
|
||||
pub unsafe fn from_mem_ref(mem: alloc::MemRef, cap: u32, pos: u32, lim: u32) -> ROByteBuf {
|
||||
ROByteBuf {
|
||||
buf: ByteBuf::from_mem_ref(mem, cap, pos, lim)
|
||||
impl From<ByteBuf> for Bytes {
|
||||
fn from(src: ByteBuf) -> Bytes {
|
||||
unsafe {
|
||||
let ByteBuf { mem, pos, lim, .. } = src;
|
||||
Bytes::from_mem_ref(mem, pos, lim - pos)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_seq_byte_str(self) -> SeqByteStr {
|
||||
self.buf.to_seq_byte_str()
|
||||
}
|
||||
|
||||
pub fn to_bytes(self) -> Bytes {
|
||||
self.buf.to_bytes()
|
||||
}
|
||||
|
||||
/// Marks the current read location.
|
||||
///
|
||||
/// Together with `reset`, this can be used to read from a section of the
|
||||
/// buffer multiple times.
|
||||
pub fn mark(&mut self) {
|
||||
self.buf.mark = Some(self.buf.pos);
|
||||
}
|
||||
|
||||
/// Resets the read position to the previously marked position.
|
||||
///
|
||||
/// Together with `mark`, this can be used to read from a section of the
|
||||
/// buffer multiple times.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This method will panic if no mark has been set.
|
||||
pub fn reset(&mut self) {
|
||||
self.buf.pos = self.buf.mark.take().expect("no mark set");
|
||||
}
|
||||
}
|
||||
|
||||
impl Buf for ROByteBuf {
|
||||
|
||||
fn remaining(&self) -> usize {
|
||||
self.buf.remaining()
|
||||
}
|
||||
|
||||
fn bytes<'a>(&'a self) -> &'a [u8] {
|
||||
self.buf.bytes()
|
||||
}
|
||||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
self.buf.advance(cnt)
|
||||
}
|
||||
|
||||
fn read_slice(&mut self, dst: &mut [u8]) -> usize {
|
||||
self.buf.read_slice(dst)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ROByteBuf {
|
||||
impl fmt::Debug for ByteBuf {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.bytes().fmt(fmt)
|
||||
}
|
||||
@@ -297,7 +221,7 @@ impl MutByteBuf {
|
||||
let pos = self.buf.pos as usize;
|
||||
|
||||
unsafe {
|
||||
self.buf.mem.bytes_mut()[pos..pos+cnt]
|
||||
self.buf.mem.mut_bytes()[pos..pos+cnt]
|
||||
.copy_from_slice(&src[0..cnt]);
|
||||
}
|
||||
|
||||
@@ -323,7 +247,7 @@ impl MutBuf for MutByteBuf {
|
||||
unsafe fn mut_bytes<'a>(&'a mut self) -> &'a mut [u8] {
|
||||
let pos = self.buf.pos();
|
||||
let lim = self.buf.lim();
|
||||
&mut self.buf.mem.bytes_mut()[pos..lim]
|
||||
&mut self.buf.mem.mut_bytes()[pos..lim]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+76
-117
@@ -1,16 +1,10 @@
|
||||
mod append;
|
||||
mod byte;
|
||||
mod ring;
|
||||
mod sink;
|
||||
mod source;
|
||||
mod take;
|
||||
pub mod append;
|
||||
pub mod block;
|
||||
pub mod byte;
|
||||
pub mod ring;
|
||||
pub mod take;
|
||||
|
||||
pub use self::append::AppendBuf;
|
||||
pub use self::byte::{ByteBuf, MutByteBuf, ROByteBuf};
|
||||
pub use self::ring::RingBuf;
|
||||
pub use self::take::Take;
|
||||
|
||||
use {ByteStr, RopeBuf};
|
||||
use {Bytes};
|
||||
use std::{cmp, fmt, io, ptr, usize};
|
||||
|
||||
/// A trait for values that provide sequential read access to bytes.
|
||||
@@ -21,7 +15,7 @@ pub trait Buf {
|
||||
|
||||
/// Returns a slice starting at the current Buf position and of length
|
||||
/// between 0 and `Buf::remaining()`.
|
||||
fn bytes<'a>(&'a self) -> &'a [u8];
|
||||
fn bytes(&self) -> &[u8];
|
||||
|
||||
/// Advance the internal cursor of the Buf
|
||||
fn advance(&mut self, cnt: usize);
|
||||
@@ -33,7 +27,9 @@ pub trait Buf {
|
||||
|
||||
fn copy_to<S: Sink>(&mut self, dst: S) -> usize
|
||||
where Self: Sized {
|
||||
dst.copy_from(self)
|
||||
let rem = self.remaining();
|
||||
dst.copy_from(self);
|
||||
rem - self.remaining()
|
||||
}
|
||||
|
||||
/// Read bytes from the `Buf` into the given slice and advance the cursor by
|
||||
@@ -51,16 +47,17 @@ pub trait Buf {
|
||||
/// assert_eq!(b"hello", &dst);
|
||||
/// assert_eq!(6, buf.remaining());
|
||||
/// ```
|
||||
fn read_slice(&mut self, dst: &mut [u8]) -> usize {
|
||||
fn read_slice(&mut self, dst: &mut [u8]) {
|
||||
let mut off = 0;
|
||||
let len = cmp::min(dst.len(), self.remaining());
|
||||
|
||||
while off < len {
|
||||
assert!(self.remaining() >= dst.len());
|
||||
|
||||
while off < dst.len() {
|
||||
let cnt;
|
||||
|
||||
unsafe {
|
||||
let src = self.bytes();
|
||||
cnt = cmp::min(src.len(), len - off);
|
||||
cnt = cmp::min(src.len(), dst.len() - off);
|
||||
|
||||
ptr::copy_nonoverlapping(
|
||||
src.as_ptr(), dst[off..].as_mut_ptr(), cnt);
|
||||
@@ -70,24 +67,30 @@ pub trait Buf {
|
||||
|
||||
self.advance(cnt);
|
||||
}
|
||||
|
||||
len
|
||||
}
|
||||
|
||||
/// Read a single byte from the `Buf`
|
||||
fn read_byte(&mut self) -> Option<u8> {
|
||||
let mut dst = [0];
|
||||
|
||||
if self.read_slice(&mut dst) == 0 {
|
||||
return None;
|
||||
if self.has_remaining() {
|
||||
let mut dst = [0];
|
||||
self.read_slice(&mut dst);
|
||||
Some(dst[0])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
Some(dst[0])
|
||||
fn peek_byte(&self) -> Option<u8> {
|
||||
if self.has_remaining() {
|
||||
Some(self.bytes()[0])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for values that provide sequential write access to bytes.
|
||||
pub trait MutBuf : Sized {
|
||||
pub trait MutBuf {
|
||||
|
||||
/// Returns the number of bytes that can be written to the MutBuf
|
||||
fn remaining(&self) -> usize;
|
||||
@@ -108,7 +111,9 @@ pub trait MutBuf : Sized {
|
||||
|
||||
fn copy_from<S: Source>(&mut self, src: S) -> usize
|
||||
where Self: Sized {
|
||||
src.copy_to(self)
|
||||
let rem = self.remaining();
|
||||
src.copy_to(self);
|
||||
rem - self.remaining()
|
||||
}
|
||||
|
||||
/// Write bytes from the given slice into the `MutBuf` and advance the
|
||||
@@ -130,16 +135,17 @@ pub trait MutBuf : Sized {
|
||||
///
|
||||
/// assert_eq!(b"hello\0", &dst);
|
||||
/// ```
|
||||
fn write_slice(&mut self, src: &[u8]) -> usize {
|
||||
fn write_slice(&mut self, src: &[u8]) {
|
||||
let mut off = 0;
|
||||
let len = cmp::min(src.len(), self.remaining());
|
||||
|
||||
while off < len {
|
||||
assert!(self.remaining() >= src.len(), "buffer overflow");
|
||||
|
||||
while off < src.len() {
|
||||
let cnt;
|
||||
|
||||
unsafe {
|
||||
let dst = self.mut_bytes();
|
||||
cnt = cmp::min(dst.len(), len - off);
|
||||
cnt = cmp::min(dst.len(), src.len() - off);
|
||||
|
||||
ptr::copy_nonoverlapping(
|
||||
src[off..].as_ptr(),
|
||||
@@ -152,8 +158,10 @@ pub trait MutBuf : Sized {
|
||||
|
||||
unsafe { self.advance(cnt); }
|
||||
}
|
||||
}
|
||||
|
||||
len
|
||||
fn write_str(&mut self, src: &str) {
|
||||
self.write_slice(src.as_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,32 +174,41 @@ pub trait MutBuf : Sized {
|
||||
|
||||
/// A value that writes bytes from itself into a `MutBuf`.
|
||||
pub trait Source {
|
||||
fn copy_to<B: MutBuf>(self, buf: &mut B) -> usize;
|
||||
fn copy_to<B: MutBuf>(self, buf: &mut B);
|
||||
}
|
||||
|
||||
impl<'a> Source for &'a [u8] {
|
||||
fn copy_to<B: MutBuf>(self, buf: &mut B) -> usize {
|
||||
buf.write_slice(self)
|
||||
fn copy_to<B: MutBuf>(self, buf: &mut B) {
|
||||
buf.write_slice(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for u8 {
|
||||
fn copy_to<B: MutBuf>(self, buf: &mut B) -> usize {
|
||||
fn copy_to<B: MutBuf>(self, buf: &mut B) {
|
||||
let src = [self];
|
||||
buf.write_slice(&src)
|
||||
buf.write_slice(&src);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ByteStr> Source for &'a T {
|
||||
fn copy_to<B: MutBuf>(self, buf: &mut B) -> usize {
|
||||
let mut src = ByteStr::buf(self);
|
||||
let mut res = 0;
|
||||
impl Source for Bytes {
|
||||
fn copy_to<B: MutBuf>(self, buf: &mut B) {
|
||||
Source::copy_to(&self, buf);
|
||||
}
|
||||
}
|
||||
|
||||
while src.has_remaining() && buf.has_remaining() {
|
||||
impl<'a> Source for &'a Bytes {
|
||||
fn copy_to<B: MutBuf>(self, buf: &mut B) {
|
||||
Source::copy_to(self.buf(), buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Buf> Source for T {
|
||||
fn copy_to<B: MutBuf>(mut self, buf: &mut B) {
|
||||
while self.has_remaining() && buf.has_remaining() {
|
||||
let l;
|
||||
|
||||
unsafe {
|
||||
let s = src.bytes();
|
||||
let s = self.bytes();
|
||||
let d = buf.mut_bytes();
|
||||
l = cmp::min(s.len(), d.len());
|
||||
|
||||
@@ -201,28 +218,24 @@ impl<'a, T: ByteStr> Source for &'a T {
|
||||
l);
|
||||
}
|
||||
|
||||
src.advance(l);
|
||||
self.advance(l);
|
||||
unsafe { buf.advance(l); }
|
||||
|
||||
res += l;
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Sink {
|
||||
fn copy_from<B: Buf>(self, buf: &mut B) -> usize;
|
||||
fn copy_from<B: Buf>(self, buf: &mut B);
|
||||
}
|
||||
|
||||
impl<'a> Sink for &'a mut [u8] {
|
||||
fn copy_from<B: Buf>(self, buf: &mut B) -> usize {
|
||||
buf.read_slice(self)
|
||||
fn copy_from<B: Buf>(self, buf: &mut B) {
|
||||
buf.read_slice(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Sink for &'a mut Vec<u8> {
|
||||
fn copy_from<B: Buf>(self, buf: &mut B) -> usize {
|
||||
fn copy_from<B: Buf>(self, buf: &mut B) {
|
||||
use std::slice;
|
||||
|
||||
self.clear();
|
||||
@@ -238,15 +251,11 @@ impl<'a> Sink for &'a mut Vec<u8> {
|
||||
unsafe {
|
||||
{
|
||||
let dst = &mut self[..];
|
||||
let cnt = buf.read_slice(slice::from_raw_parts_mut(dst.as_mut_ptr(), rem));
|
||||
|
||||
debug_assert!(cnt == rem);
|
||||
buf.read_slice(slice::from_raw_parts_mut(dst.as_mut_ptr(), rem));
|
||||
}
|
||||
|
||||
self.set_len(rem);
|
||||
}
|
||||
|
||||
rem
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,30 +306,6 @@ impl<T: io::Write> WriteExt for T {
|
||||
*
|
||||
*/
|
||||
|
||||
impl Buf for Box<Buf+Send+'static> {
|
||||
fn remaining(&self) -> usize {
|
||||
(**self).remaining()
|
||||
}
|
||||
|
||||
fn bytes(&self) -> &[u8] {
|
||||
(**self).bytes()
|
||||
}
|
||||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
(**self).advance(cnt);
|
||||
}
|
||||
|
||||
fn read_slice(&mut self, dst: &mut [u8]) -> usize {
|
||||
(**self).read_slice(dst)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Box<Buf+Send+'static> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "Box<Buf> {{ remaining: {} }}", self.remaining())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<[u8]>> Buf for io::Cursor<T> {
|
||||
fn remaining(&self) -> usize {
|
||||
self.get_ref().as_ref().len() - self.position() as usize
|
||||
@@ -396,45 +381,19 @@ impl MutBuf for Vec<u8> {
|
||||
|
||||
/*
|
||||
*
|
||||
* ===== Read impls =====
|
||||
* ===== fmt impls =====
|
||||
*
|
||||
*/
|
||||
|
||||
macro_rules! impl_read {
|
||||
($ty:ty) => {
|
||||
impl io::Read for $ty {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
if !self.has_remaining() {
|
||||
return Ok(0);
|
||||
}
|
||||
pub struct Fmt<'a, B: 'a>(pub &'a mut B);
|
||||
|
||||
Ok(self.read_slice(buf))
|
||||
}
|
||||
}
|
||||
impl<'a, B: MutBuf> fmt::Write for Fmt<'a, B> {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
self.0.write_str(s);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
|
||||
fmt::write(self, args)
|
||||
}
|
||||
}
|
||||
|
||||
impl_read!(ByteBuf);
|
||||
impl_read!(ROByteBuf);
|
||||
impl_read!(RopeBuf);
|
||||
impl_read!(Box<Buf+Send+'static>);
|
||||
|
||||
macro_rules! impl_write {
|
||||
($ty:ty) => {
|
||||
impl io::Write for $ty {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
if !self.has_remaining() {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
Ok(self.write_slice(buf))
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_write!(MutByteBuf);
|
||||
|
||||
+2
-3
@@ -144,7 +144,6 @@ impl fmt::Debug for RingBuf {
|
||||
}
|
||||
|
||||
impl Buf for RingBuf {
|
||||
|
||||
fn remaining(&self) -> usize {
|
||||
self.read_remaining()
|
||||
}
|
||||
@@ -176,7 +175,7 @@ impl MutBuf for RingBuf {
|
||||
|
||||
unsafe fn mut_bytes(&mut self) -> &mut [u8] {
|
||||
if self.cap == 0 {
|
||||
return self.ptr.bytes_mut();
|
||||
return self.ptr.mut_bytes();
|
||||
}
|
||||
let mut from;
|
||||
let mut to;
|
||||
@@ -190,7 +189,7 @@ impl MutBuf for RingBuf {
|
||||
to = self.cap;
|
||||
}
|
||||
|
||||
&mut self.ptr.bytes_mut()[from..to]
|
||||
&mut self.ptr.mut_bytes()[from..to]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
use buf::{Buf, MutBuf};
|
||||
use std::{cmp, io};
|
||||
use std::{cmp};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Take<T> {
|
||||
@@ -52,16 +52,6 @@ impl<T: Buf> Buf for Take<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Buf> io::Read for Take<T> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
if !self.has_remaining() {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
Ok(self.read_slice(buf))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MutBuf> MutBuf for Take<T> {
|
||||
fn remaining(&self) -> usize {
|
||||
cmp::min(self.inner.remaining(), self.limit)
|
||||
|
||||
Reference in New Issue
Block a user