mirror of
https://github.com/tokio-rs/bytes.git
synced 2026-08-16 00:00:15 +02:00
Group files as buf or byte str related
This commit is contained in:
+269
@@ -0,0 +1,269 @@
|
||||
use {alloc, Bytes, SeqByteStr, MAX_CAPACITY};
|
||||
use traits::{Buf, MutBuf, MutBufExt, ByteStr};
|
||||
use std::{cmp, ptr};
|
||||
|
||||
/*
|
||||
*
|
||||
* ===== ByteBuf =====
|
||||
*
|
||||
*/
|
||||
|
||||
/// A `Buf` backed by a contiguous region of memory.
|
||||
pub struct ByteBuf {
|
||||
mem: alloc::MemRef,
|
||||
cap: u32,
|
||||
pos: u32,
|
||||
lim: u32
|
||||
}
|
||||
|
||||
impl ByteBuf {
|
||||
/// Create a new `ByteBuf` by copying the contents of the given slice.
|
||||
pub fn from_slice(bytes: &[u8]) -> ByteBuf {
|
||||
let mut buf = ByteBuf::mut_with_capacity(bytes.len());
|
||||
buf.write(bytes).ok().expect("unexpected failure");
|
||||
buf.flip()
|
||||
}
|
||||
|
||||
pub fn mut_with_capacity(capacity: usize) -> MutByteBuf {
|
||||
assert!(capacity <= MAX_CAPACITY);
|
||||
MutByteBuf { buf: ByteBuf::new(capacity as u32) }
|
||||
}
|
||||
|
||||
pub fn none() -> ByteBuf {
|
||||
ByteBuf {
|
||||
mem: alloc::MemRef::none(),
|
||||
cap: 0,
|
||||
pos: 0,
|
||||
lim: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn from_mem_ref(mem: alloc::MemRef, cap: u32, pos: u32, lim: u32) -> ByteBuf {
|
||||
debug_assert!(pos <= lim && lim <= cap, "invalid arguments; cap={}; pos={}; lim={}", cap, pos, lim);
|
||||
|
||||
ByteBuf {
|
||||
mem: mem,
|
||||
cap: cap,
|
||||
pos: pos,
|
||||
lim: lim,
|
||||
}
|
||||
}
|
||||
|
||||
fn new(mut capacity: u32) -> ByteBuf {
|
||||
// Handle 0 capacity case
|
||||
if capacity == 0 {
|
||||
return ByteBuf::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 ByteBuf::none();
|
||||
}
|
||||
|
||||
ByteBuf {
|
||||
mem: mem,
|
||||
cap: capacity,
|
||||
pos: 0,
|
||||
lim: capacity
|
||||
}
|
||||
}
|
||||
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.cap as usize
|
||||
}
|
||||
|
||||
pub fn flip(self) -> MutByteBuf {
|
||||
let mut buf = MutByteBuf { buf: self };
|
||||
buf.clear();
|
||||
buf
|
||||
}
|
||||
|
||||
pub fn read_slice(&mut self, dst: &mut [u8]) -> usize {
|
||||
let len = cmp::min(dst.len(), self.remaining());
|
||||
let cnt = len as u32;
|
||||
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(
|
||||
self.mem.ptr().offset(self.pos as isize),
|
||||
dst.as_mut_ptr(),
|
||||
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())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pos(&self) -> usize {
|
||||
self.pos as usize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lim(&self) -> usize {
|
||||
self.lim as usize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn remaining_u32(&self) -> u32 {
|
||||
self.lim - self.pos
|
||||
}
|
||||
}
|
||||
|
||||
impl Buf for ByteBuf {
|
||||
|
||||
#[inline]
|
||||
fn remaining(&self) -> usize {
|
||||
self.remaining_u32() as usize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn bytes<'a>(&'a self) -> &'a [u8] {
|
||||
&self.mem.bytes()[self.pos()..self.lim()]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn advance(&mut self, mut cnt: usize) {
|
||||
cnt = cmp::min(cnt, self.remaining());
|
||||
self.pos += cnt as u32;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_slice(&mut self, dst: &mut [u8]) -> usize {
|
||||
ByteBuf::read_slice(self, dst)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* ===== 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)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_seq_byte_str(self) -> SeqByteStr {
|
||||
self.buf.to_seq_byte_str()
|
||||
}
|
||||
|
||||
pub fn to_bytes(self) -> Bytes {
|
||||
self.buf.to_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* ===== MutByteBuf =====
|
||||
*
|
||||
*/
|
||||
|
||||
pub struct MutByteBuf {
|
||||
buf: ByteBuf,
|
||||
}
|
||||
|
||||
impl MutByteBuf {
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.buf.capacity() as usize
|
||||
}
|
||||
|
||||
pub fn flip(self) -> ByteBuf {
|
||||
let mut buf = self.buf;
|
||||
|
||||
buf.lim = buf.pos;
|
||||
buf.pos = 0;
|
||||
buf
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.buf.pos = 0;
|
||||
self.buf.lim = self.buf.cap;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_slice(&mut self, src: &[u8]) -> usize {
|
||||
let cnt = src.len() as u32;
|
||||
let rem = self.buf.remaining_u32();
|
||||
|
||||
if rem < cnt {
|
||||
self.write_ptr(src.as_ptr(), rem)
|
||||
} else {
|
||||
self.write_ptr(src.as_ptr(), cnt)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_ptr(&mut self, src: *const u8, len: u32) -> usize {
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(
|
||||
src,
|
||||
self.buf.mem.ptr().offset(self.buf.pos as isize),
|
||||
len as usize);
|
||||
|
||||
self.buf.pos += len;
|
||||
len as usize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MutBuf for MutByteBuf {
|
||||
fn remaining(&self) -> usize {
|
||||
self.buf.remaining()
|
||||
}
|
||||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
self.buf.advance(cnt)
|
||||
}
|
||||
|
||||
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]
|
||||
}
|
||||
}
|
||||
+364
@@ -0,0 +1,364 @@
|
||||
mod byte;
|
||||
mod ring;
|
||||
mod sink;
|
||||
mod slice;
|
||||
mod source;
|
||||
|
||||
pub use self::byte::{ByteBuf, MutByteBuf, ROByteBuf};
|
||||
pub use self::ring::RingBuf;
|
||||
pub use self::slice::{SliceBuf, MutSliceBuf};
|
||||
|
||||
use {BufError, RopeBuf};
|
||||
use std::{cmp, fmt, io, ptr};
|
||||
|
||||
/// A trait for values that provide sequential read access to bytes.
|
||||
pub trait Buf {
|
||||
|
||||
/// Returns the number of bytes that can be accessed from the Buf
|
||||
fn remaining(&self) -> usize;
|
||||
|
||||
/// Returns a slice starting at the current Buf position and of length
|
||||
/// between 0 and `Buf::remaining()`.
|
||||
fn bytes<'a>(&'a self) -> &'a [u8];
|
||||
|
||||
/// Advance the internal cursor of the Buf
|
||||
fn advance(&mut self, cnt: usize);
|
||||
|
||||
/// Returns true if there are any more bytes to consume
|
||||
fn has_remaining(&self) -> bool {
|
||||
self.remaining() > 0
|
||||
}
|
||||
|
||||
/// Read bytes from the `Buf` into the given slice and advance the cursor by
|
||||
/// the number of bytes read.
|
||||
///
|
||||
/// If there are fewer bytes remaining than is needed to satisfy the
|
||||
/// request (aka `dst.len()` > self.remaining()`), then
|
||||
/// `Err(BufError::Overflow)` is returned.
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{SliceBuf, Buf};
|
||||
///
|
||||
/// let mut buf = SliceBuf::wrap(b"hello world");
|
||||
/// let mut dst = [0; 5];
|
||||
///
|
||||
/// buf.read_slice(&mut dst);
|
||||
/// assert_eq!(b"hello", &dst);
|
||||
/// assert_eq!(6, buf.remaining());
|
||||
/// ```
|
||||
fn read_slice(&mut self, dst: &mut [u8]) -> usize {
|
||||
let mut off = 0;
|
||||
let len = cmp::min(dst.len(), self.remaining());
|
||||
|
||||
while off < len {
|
||||
let mut cnt;
|
||||
|
||||
unsafe {
|
||||
let src = self.bytes();
|
||||
cnt = cmp::min(src.len(), len - off);
|
||||
|
||||
ptr::copy_nonoverlapping(
|
||||
src.as_ptr(), dst[off..].as_mut_ptr(), cnt);
|
||||
|
||||
off += src.len();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Some(dst[0])
|
||||
}
|
||||
}
|
||||
|
||||
/// An extension trait providing extra functions applicable to all `Buf` values.
|
||||
pub trait BufExt {
|
||||
|
||||
/// Read bytes from this Buf into the given sink and advance the cursor by
|
||||
/// the number of bytes read.
|
||||
fn read<S: Sink>(&mut self, dst: S) -> Result<usize, S::Error>;
|
||||
}
|
||||
|
||||
/// A trait for values that provide sequential write access to bytes.
|
||||
pub trait MutBuf : Sized {
|
||||
|
||||
/// Returns the number of bytes that can be accessed from the Buf
|
||||
fn remaining(&self) -> usize;
|
||||
|
||||
/// Advance the internal cursor of the Buf
|
||||
fn advance(&mut self, cnt: usize);
|
||||
|
||||
/// Returns true if there are any more bytes to consume
|
||||
fn has_remaining(&self) -> bool {
|
||||
self.remaining() > 0
|
||||
}
|
||||
|
||||
/// Returns a mutable slice starting at the current Buf position and of
|
||||
/// length between 0 and `Buf::remaining()`.
|
||||
fn mut_bytes<'a>(&'a mut self) -> &'a mut [u8];
|
||||
|
||||
/// Read bytes from this Buf into the given slice and advance the cursor by
|
||||
/// the number of bytes read.
|
||||
///
|
||||
/// If there are fewer bytes remaining than is needed to satisfy the
|
||||
/// request (aka `dst.len()` > self.remaining()`), then
|
||||
/// `Err(BufError::Overflow)` is returned.
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{MutSliceBuf, Buf, MutBuf};
|
||||
///
|
||||
/// let mut dst = [0; 6];
|
||||
///
|
||||
/// {
|
||||
/// let mut buf = MutSliceBuf::wrap(&mut dst);
|
||||
/// buf.write_slice(b"hello");
|
||||
///
|
||||
/// assert_eq!(1, buf.remaining());
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(b"hello\0", &dst);
|
||||
/// ```
|
||||
fn write_slice(&mut self, src: &[u8]) -> usize {
|
||||
let mut off = 0;
|
||||
let len = cmp::min(src.len(), self.remaining());
|
||||
|
||||
while off < len {
|
||||
let mut cnt;
|
||||
|
||||
unsafe {
|
||||
let dst = self.mut_bytes();
|
||||
cnt = cmp::min(dst.len(), len - off);
|
||||
|
||||
ptr::copy_nonoverlapping(
|
||||
src[off..].as_ptr(),
|
||||
dst.as_mut_ptr(),
|
||||
cnt);
|
||||
|
||||
off += cnt;
|
||||
}
|
||||
|
||||
self.advance(cnt);
|
||||
}
|
||||
|
||||
len
|
||||
}
|
||||
|
||||
/// Write a single byte to the `MuBuf`
|
||||
fn write_byte(&mut self, byte: u8) -> bool {
|
||||
let src = [byte];
|
||||
|
||||
if self.write_slice(&src) == 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// An extension trait providing extra functions applicable to all `MutBuf` values.
|
||||
pub trait MutBufExt {
|
||||
|
||||
/// Write bytes from the given source into the current `MutBuf` and advance
|
||||
/// the cursor by the number of bytes written.
|
||||
fn write<S: Source>(&mut self, src: S) -> Result<usize, S::Error>;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* ===== *Ext impls =====
|
||||
*
|
||||
*/
|
||||
|
||||
impl<B: Buf> BufExt for B {
|
||||
fn read<S: Sink>(&mut self, dst: S) -> Result<usize, S::Error> {
|
||||
dst.sink(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: MutBuf> MutBufExt for B {
|
||||
fn write<S: Source>(&mut self, src: S) -> Result<usize, S::Error> {
|
||||
src.fill(self)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* ===== Sink / Source =====
|
||||
*
|
||||
*/
|
||||
|
||||
/// A value that reads bytes from a Buf into itself
|
||||
pub trait Sink {
|
||||
type Error;
|
||||
|
||||
fn sink<B: Buf>(self, buf: &mut B) -> Result<usize, Self::Error>;
|
||||
}
|
||||
|
||||
/// A value that writes bytes from itself into a `MutBuf`.
|
||||
pub trait Source {
|
||||
type Error;
|
||||
|
||||
fn fill<B: MutBuf>(self, buf: &mut B) -> Result<usize, Self::Error>;
|
||||
}
|
||||
|
||||
impl<'a> Sink for &'a mut [u8] {
|
||||
type Error = BufError;
|
||||
|
||||
fn sink<B: Buf>(self, buf: &mut B) -> Result<usize, BufError> {
|
||||
Ok(buf.read_slice(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Sink for &'a mut Vec<u8> {
|
||||
type Error = BufError;
|
||||
|
||||
fn sink<B: Buf>(self, buf: &mut B) -> Result<usize, BufError> {
|
||||
use std::slice;
|
||||
|
||||
self.clear();
|
||||
|
||||
let rem = buf.remaining();
|
||||
let cap = self.capacity();
|
||||
|
||||
// Ensure that the vec is big enough
|
||||
if rem > self.capacity() {
|
||||
self.reserve(rem - cap);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
{
|
||||
let dst = &mut self[..];
|
||||
let cnt = buf.read_slice(slice::from_raw_parts_mut(dst.as_mut_ptr(), rem));
|
||||
|
||||
debug_assert!(cnt == rem);
|
||||
}
|
||||
|
||||
self.set_len(rem);
|
||||
}
|
||||
|
||||
Ok(rem)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Source for &'a [u8] {
|
||||
type Error = BufError;
|
||||
|
||||
fn fill<B: MutBuf>(self, buf: &mut B) -> Result<usize, BufError> {
|
||||
Ok(buf.write_slice(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Source for &'a Vec<u8> {
|
||||
type Error = BufError;
|
||||
|
||||
fn fill<B: MutBuf>(self, buf: &mut B) -> Result<usize, BufError> {
|
||||
Ok(buf.write_slice(self.as_ref()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a, R: io::Read+'a> Source for &'a mut R {
|
||||
type Error = io::Error;
|
||||
|
||||
fn fill<B: MutBuf>(self, buf: &mut B) -> Result<usize, io::Error> {
|
||||
let mut cnt = 0;
|
||||
|
||||
while buf.has_remaining() {
|
||||
let i = try!(self.read(buf.mut_bytes()));
|
||||
|
||||
if i == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
buf.advance(i);
|
||||
cnt += i;
|
||||
}
|
||||
|
||||
Ok(cnt)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* ===== Buf impls =====
|
||||
*
|
||||
*/
|
||||
|
||||
impl Buf for Box<Buf+'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+'static> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "Box<Buf> {{ remaining: {} }}", self.remaining())
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* ===== Read 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);
|
||||
}
|
||||
|
||||
Ok(self.read_slice(buf))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_read!(ByteBuf);
|
||||
impl_read!(ROByteBuf);
|
||||
impl_read!(RopeBuf);
|
||||
impl_read!(Box<Buf+'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);
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
use {alloc, Buf, MutBuf};
|
||||
use std::{cmp, fmt, io, ptr};
|
||||
|
||||
/// 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,
|
||||
/// wraps around to the start.
|
||||
pub struct RingBuf {
|
||||
ptr: alloc::MemRef, // Pointer to the memory
|
||||
cap: usize, // Capacity of the buffer
|
||||
pos: usize, // Offset of read cursor
|
||||
len: usize // Number of bytes to read
|
||||
}
|
||||
|
||||
// TODO: There are most likely many optimizations that can be made
|
||||
impl RingBuf {
|
||||
pub fn new(mut capacity: usize) -> RingBuf {
|
||||
// Handle the 0 length buffer case
|
||||
if capacity == 0 {
|
||||
return RingBuf {
|
||||
ptr: alloc::MemRef::none(),
|
||||
cap: 0,
|
||||
pos: 0,
|
||||
len: 0
|
||||
}
|
||||
}
|
||||
|
||||
// Round to the next power of 2 for better alignment
|
||||
capacity = capacity.next_power_of_two();
|
||||
|
||||
let mem = alloc::heap(capacity as usize);
|
||||
|
||||
RingBuf {
|
||||
ptr: mem,
|
||||
cap: capacity,
|
||||
pos: 0,
|
||||
len: 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_full(&self) -> bool {
|
||||
self.cap == self.len
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len == 0
|
||||
}
|
||||
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.cap
|
||||
}
|
||||
|
||||
fn read_remaining(&self) -> usize {
|
||||
self.len
|
||||
}
|
||||
|
||||
fn write_remaining(&self) -> usize {
|
||||
self.cap - self.len
|
||||
}
|
||||
|
||||
fn advance_reader(&mut self, mut cnt: usize) {
|
||||
if self.cap == 0 {
|
||||
return;
|
||||
}
|
||||
cnt = cmp::min(cnt, self.read_remaining());
|
||||
|
||||
self.pos += cnt;
|
||||
self.pos %= self.cap;
|
||||
self.len -= cnt;
|
||||
}
|
||||
|
||||
fn advance_writer(&mut self, mut cnt: usize) {
|
||||
cnt = cmp::min(cnt, self.write_remaining());
|
||||
self.len += cnt;
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for RingBuf {
|
||||
fn clone(&self) -> RingBuf {
|
||||
use std::cmp;
|
||||
|
||||
let mut ret = RingBuf::new(self.cap);
|
||||
|
||||
ret.pos = self.pos;
|
||||
ret.len = self.len;
|
||||
|
||||
unsafe {
|
||||
let to = self.pos + self.len;
|
||||
|
||||
if to > self.cap {
|
||||
ptr::copy(self.ptr.ptr() as *const u8, ret.ptr.ptr(), to % self.cap);
|
||||
}
|
||||
|
||||
ptr::copy(
|
||||
self.ptr.ptr().offset(self.pos as isize) as *const u8,
|
||||
ret.ptr.ptr().offset(self.pos as isize),
|
||||
cmp::min(self.len, self.cap - self.pos));
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
// TODO: an improved version of clone_from is possible that potentially
|
||||
// re-uses the buffer
|
||||
}
|
||||
|
||||
impl fmt::Debug for RingBuf {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "RingBuf[.. {}]", self.len)
|
||||
}
|
||||
}
|
||||
|
||||
impl Buf for RingBuf {
|
||||
|
||||
fn remaining(&self) -> usize {
|
||||
self.read_remaining()
|
||||
}
|
||||
|
||||
fn bytes(&self) -> &[u8] {
|
||||
let mut to = self.pos + self.len;
|
||||
|
||||
if to > self.cap {
|
||||
to = self.cap
|
||||
}
|
||||
|
||||
&self.ptr.bytes()[self.pos .. to]
|
||||
}
|
||||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
self.advance_reader(cnt)
|
||||
}
|
||||
}
|
||||
|
||||
impl MutBuf for RingBuf {
|
||||
|
||||
fn remaining(&self) -> usize {
|
||||
self.write_remaining()
|
||||
}
|
||||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
self.advance_writer(cnt)
|
||||
}
|
||||
|
||||
fn mut_bytes(&mut self) -> &mut [u8] {
|
||||
if self.cap == 0 {
|
||||
return self.ptr.bytes_mut();
|
||||
}
|
||||
let mut from;
|
||||
let mut to;
|
||||
|
||||
from = self.pos + self.len;
|
||||
from %= self.cap;
|
||||
|
||||
to = from + <Self as MutBuf>::remaining(&self);
|
||||
|
||||
if to >= self.cap {
|
||||
to = self.cap;
|
||||
}
|
||||
|
||||
&mut self.ptr.bytes_mut()[from..to]
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Read for RingBuf {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
if !MutBuf::has_remaining(self) {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
Ok(self.read_slice(buf))
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for RingBuf {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
if !Buf::has_remaining(self) {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
Ok(self.write_slice(buf))
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for RingBuf { }
|
||||
@@ -0,0 +1,59 @@
|
||||
use std::cmp;
|
||||
use {Buf, MutBuf};
|
||||
|
||||
// TODO: Rename -> Cursor. Use as buf for various byte strings
|
||||
|
||||
pub struct SliceBuf<'a> {
|
||||
bytes: &'a [u8],
|
||||
pos: usize
|
||||
}
|
||||
|
||||
impl<'a> SliceBuf<'a> {
|
||||
pub fn wrap(bytes: &'a [u8]) -> SliceBuf<'a> {
|
||||
SliceBuf { bytes: bytes, pos: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Buf for SliceBuf<'a> {
|
||||
fn remaining(&self) -> usize {
|
||||
self.bytes.len() - self.pos
|
||||
}
|
||||
|
||||
fn bytes<'b>(&'b self) -> &'b [u8] {
|
||||
&self.bytes[self.pos..]
|
||||
}
|
||||
|
||||
fn advance(&mut self, mut cnt: usize) {
|
||||
cnt = cmp::min(cnt, self.remaining());
|
||||
self.pos += cnt;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MutSliceBuf<'a> {
|
||||
bytes: &'a mut [u8],
|
||||
pos: usize
|
||||
}
|
||||
|
||||
impl<'a> MutSliceBuf<'a> {
|
||||
pub fn wrap(bytes: &'a mut [u8]) -> MutSliceBuf<'a> {
|
||||
MutSliceBuf {
|
||||
bytes: bytes,
|
||||
pos: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MutBuf for MutSliceBuf<'a> {
|
||||
fn remaining(&self) -> usize {
|
||||
self.bytes.len() - self.pos
|
||||
}
|
||||
|
||||
fn advance(&mut self, mut cnt: usize) {
|
||||
cnt = cmp::min(cnt, self.remaining());
|
||||
self.pos += cnt;
|
||||
}
|
||||
|
||||
fn mut_bytes<'b>(&'b mut self) -> &'b mut [u8] {
|
||||
&mut self.bytes[self.pos..]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user