mirror of
https://github.com/tokio-rs/bytes.git
synced 2026-08-25 00:00:22 +02:00
Group files as buf or byte str related
This commit is contained in:
@@ -4,14 +4,8 @@ use std::ops::DerefMut;
|
|||||||
|
|
||||||
const MAX_ALLOC_SIZE: usize = usize::MAX;
|
const MAX_ALLOC_SIZE: usize = usize::MAX;
|
||||||
|
|
||||||
pub fn allocate(len: usize) -> MemRef {
|
|
||||||
HEAP.allocate(len)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Heap;
|
pub struct Heap;
|
||||||
|
|
||||||
pub static HEAP: Heap = Heap;
|
|
||||||
|
|
||||||
impl Heap {
|
impl Heap {
|
||||||
pub fn allocate(&self, len: usize) -> MemRef {
|
pub fn allocate(&self, len: usize) -> MemRef {
|
||||||
// Make sure that the allocation is within the permitted range
|
// Make sure that the allocation is within the permitted range
|
||||||
@@ -1,6 +1,14 @@
|
|||||||
|
mod heap;
|
||||||
|
|
||||||
|
pub use self::heap::{Heap};
|
||||||
|
|
||||||
use std::{mem, ptr};
|
use std::{mem, ptr};
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
|
pub fn heap(len: usize) -> MemRef {
|
||||||
|
Heap.allocate(len)
|
||||||
|
}
|
||||||
|
|
||||||
/// Allocates memory to be used by Bufs or Bytes. Allows allocating memory
|
/// Allocates memory to be used by Bufs or Bytes. Allows allocating memory
|
||||||
/// using alternate stratgies than the default Rust heap allocator. Also does
|
/// using alternate stratgies than the default Rust heap allocator. Also does
|
||||||
/// not require that allocations are continuous in memory.
|
/// not require that allocations are continuous in memory.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use {alloc, heap, Bytes, SeqByteStr, MAX_CAPACITY};
|
use {alloc, Bytes, SeqByteStr, MAX_CAPACITY};
|
||||||
use traits::{Buf, MutBuf, MutBufExt, ByteStr};
|
use traits::{Buf, MutBuf, MutBufExt, ByteStr};
|
||||||
use std::{cmp, ptr};
|
use std::{cmp, ptr};
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ impl ByteBuf {
|
|||||||
capacity = capacity.next_power_of_two();
|
capacity = capacity.next_power_of_two();
|
||||||
|
|
||||||
// Allocate the memory
|
// Allocate the memory
|
||||||
let mem = heap::allocate(capacity as usize);
|
let mem = alloc::heap(capacity as usize);
|
||||||
|
|
||||||
// If the allocation failed, return a blank buf
|
// If the allocation failed, return a blank buf
|
||||||
if mem.is_none() {
|
if mem.is_none() {
|
||||||
+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);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use {alloc, heap, Buf, MutBuf};
|
use {alloc, Buf, MutBuf};
|
||||||
use std::{cmp, fmt, io, ptr};
|
use std::{cmp, fmt, io, ptr};
|
||||||
|
|
||||||
/// 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
|
||||||
@@ -27,7 +27,7 @@ impl RingBuf {
|
|||||||
// Round to the next power of 2 for better alignment
|
// Round to the next power of 2 for better alignment
|
||||||
capacity = capacity.next_power_of_two();
|
capacity = capacity.next_power_of_two();
|
||||||
|
|
||||||
let mem = heap::allocate(capacity as usize);
|
let mem = alloc::heap(capacity as usize);
|
||||||
|
|
||||||
RingBuf {
|
RingBuf {
|
||||||
ptr: mem,
|
ptr: mem,
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
use std::cmp;
|
use std::cmp;
|
||||||
use {Buf, MutBuf};
|
use {Buf, MutBuf};
|
||||||
|
|
||||||
|
// TODO: Rename -> Cursor. Use as buf for various byte strings
|
||||||
|
|
||||||
pub struct SliceBuf<'a> {
|
pub struct SliceBuf<'a> {
|
||||||
bytes: &'a [u8],
|
bytes: &'a [u8],
|
||||||
pos: usize
|
pos: usize
|
||||||
+28
-577
@@ -1,24 +1,36 @@
|
|||||||
#![crate_name = "bytes"]
|
#![crate_name = "bytes"]
|
||||||
#![unstable]
|
#![unstable]
|
||||||
|
|
||||||
pub use byte_buf::{ByteBuf, ROByteBuf, MutByteBuf};
|
pub mod alloc;
|
||||||
pub use byte_str::{SeqByteStr, SmallByteStr, SmallByteStrBuf};
|
mod buf;
|
||||||
pub use bytes::Bytes;
|
mod str;
|
||||||
pub use ring::RingBuf;
|
|
||||||
pub use rope::{Rope, RopeBuf};
|
|
||||||
pub use slice::{SliceBuf, MutSliceBuf};
|
|
||||||
|
|
||||||
use std::{cmp, fmt, io, ops, ptr, u32};
|
pub use buf::{
|
||||||
use std::any::Any;
|
Buf,
|
||||||
|
BufExt,
|
||||||
|
MutBuf,
|
||||||
|
MutBufExt,
|
||||||
|
ByteBuf,
|
||||||
|
MutByteBuf,
|
||||||
|
RingBuf,
|
||||||
|
ROByteBuf,
|
||||||
|
SliceBuf,
|
||||||
|
MutSliceBuf,
|
||||||
|
Source,
|
||||||
|
Sink
|
||||||
|
};
|
||||||
|
pub use str::{
|
||||||
|
ByteStr,
|
||||||
|
Bytes,
|
||||||
|
Rope,
|
||||||
|
RopeBuf,
|
||||||
|
SeqByteStr,
|
||||||
|
SmallByteStr,
|
||||||
|
SmallByteStrBuf,
|
||||||
|
ToBytes,
|
||||||
|
};
|
||||||
|
|
||||||
mod alloc;
|
use std::u32;
|
||||||
mod byte_buf;
|
|
||||||
mod byte_str;
|
|
||||||
mod bytes;
|
|
||||||
mod heap;
|
|
||||||
mod ring;
|
|
||||||
mod rope;
|
|
||||||
mod slice;
|
|
||||||
|
|
||||||
pub mod traits {
|
pub mod traits {
|
||||||
//! All traits are re-exported here to allow glob imports.
|
//! All traits are re-exported here to allow glob imports.
|
||||||
@@ -27,527 +39,6 @@ pub mod traits {
|
|||||||
|
|
||||||
const MAX_CAPACITY: usize = u32::MAX as usize;
|
const MAX_CAPACITY: usize = u32::MAX as usize;
|
||||||
|
|
||||||
/// 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>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* ===== ByteStr =====
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// An immutable sequence of bytes. Operations will not mutate the original
|
|
||||||
/// value. Since only immutable access is permitted, operations do not require
|
|
||||||
/// copying (though, sometimes copying will happen as an optimization).
|
|
||||||
pub trait ByteStr : Clone + Sized + Send + Sync + Any + ToBytes + ops::Index<usize, Output=u8> + 'static {
|
|
||||||
|
|
||||||
// Until HKT lands, the buf must be bound by 'static
|
|
||||||
type Buf: Buf+'static;
|
|
||||||
|
|
||||||
/// Returns a read-only `Buf` for accessing the byte contents of the
|
|
||||||
/// `ByteStr`.
|
|
||||||
fn buf(&self) -> Self::Buf;
|
|
||||||
|
|
||||||
/// Returns a new `Bytes` value representing the concatenation of `self`
|
|
||||||
/// with the given `Bytes`.
|
|
||||||
fn concat<B: ByteStr+'static>(&self, other: &B) -> Bytes;
|
|
||||||
|
|
||||||
/// Returns the number of bytes in the ByteStr
|
|
||||||
fn len(&self) -> usize;
|
|
||||||
|
|
||||||
/// Returns true if the length of the `ByteStr` is 0
|
|
||||||
fn is_empty(&self) -> bool {
|
|
||||||
self.len() == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a new ByteStr value containing the byte range between `begin`
|
|
||||||
/// (inclusive) and `end` (exclusive)
|
|
||||||
fn slice(&self, begin: usize, end: usize) -> Bytes;
|
|
||||||
|
|
||||||
/// Returns a new ByteStr value containing the byte range starting from
|
|
||||||
/// `begin` (inclusive) to the end of the byte str.
|
|
||||||
///
|
|
||||||
/// Equivalent to `bytes.slice(begin, bytes.len())`
|
|
||||||
fn slice_from(&self, begin: usize) -> Bytes {
|
|
||||||
self.slice(begin, self.len())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a new ByteStr value containing the byte range from the start up
|
|
||||||
/// to `end` (exclusive).
|
|
||||||
///
|
|
||||||
/// Equivalent to `bytes.slice(0, end)`
|
|
||||||
fn slice_to(&self, end: usize) -> Bytes {
|
|
||||||
self.slice(0, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Divides the value into two `Bytes` at the given index.
|
|
||||||
///
|
|
||||||
/// The first will contain all bytes from `[0, mid]` (excluding the index
|
|
||||||
/// `mid` itself) and the second will contain all indices from `[mid, len)`
|
|
||||||
/// (excluding the index `len` itself).
|
|
||||||
///
|
|
||||||
/// Panics if `mid > len`.
|
|
||||||
fn split_at(&self, mid: usize) -> (Bytes, Bytes) {
|
|
||||||
(self.slice_to(mid), self.slice_from(mid))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_parteq {
|
|
||||||
($ty:ty) => {
|
|
||||||
impl<B: ByteStr> cmp::PartialEq<B> for $ty {
|
|
||||||
fn eq(&self, other: &B) -> bool {
|
|
||||||
if self.len() != other.len() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut buf1 = self.buf();
|
|
||||||
let mut buf2 = self.buf();
|
|
||||||
|
|
||||||
while buf1.has_remaining() {
|
|
||||||
let len;
|
|
||||||
|
|
||||||
{
|
|
||||||
let b1 = buf1.bytes();
|
|
||||||
let b2 = buf2.bytes();
|
|
||||||
|
|
||||||
len = cmp::min(b1.len(), b2.len());
|
|
||||||
|
|
||||||
if b1[..len] != b2[..len] {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf1.advance(len);
|
|
||||||
buf2.advance(len);
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ne(&self, other: &B) -> bool {
|
|
||||||
return !self.eq(other)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_parteq!(SeqByteStr);
|
|
||||||
impl_parteq!(SmallByteStr);
|
|
||||||
impl_parteq!(Bytes);
|
|
||||||
impl_parteq!(Rope);
|
|
||||||
|
|
||||||
macro_rules! impl_eq {
|
|
||||||
($ty:ty) => {
|
|
||||||
impl cmp::Eq for $ty {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_eq!(Bytes);
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* ===== ToBytes =====
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
pub trait ToBytes {
|
|
||||||
/// Consumes the value and returns a `Bytes` instance containing
|
|
||||||
/// identical bytes
|
|
||||||
fn to_bytes(self) -> Bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ToBytes for &'a [u8] {
|
|
||||||
fn to_bytes(self) -> Bytes {
|
|
||||||
Bytes::from_slice(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ToBytes for &'a Vec<u8> {
|
|
||||||
fn to_bytes(self) -> Bytes {
|
|
||||||
(&self[..]).to_bytes()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* ===== *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> Source for &'a Bytes {
|
|
||||||
type Error = BufError;
|
|
||||||
|
|
||||||
fn fill<B: MutBuf>(self, dst: &mut B) -> Result<usize, BufError> {
|
|
||||||
let mut src = self.buf();
|
|
||||||
let mut res = 0;
|
|
||||||
|
|
||||||
while src.has_remaining() && dst.has_remaining() {
|
|
||||||
let mut l;
|
|
||||||
|
|
||||||
{
|
|
||||||
let s = src.bytes();
|
|
||||||
let d = dst.mut_bytes();
|
|
||||||
l = cmp::min(s.len(), d.len());
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
ptr::copy_nonoverlapping(
|
|
||||||
s.as_ptr(),
|
|
||||||
d.as_mut_ptr(),
|
|
||||||
l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
src.advance(l);
|
|
||||||
dst.advance(l);
|
|
||||||
|
|
||||||
res += l;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
@@ -560,43 +51,3 @@ pub enum BufError {
|
|||||||
Underflow,
|
Underflow,
|
||||||
Overflow,
|
Overflow,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* ===== Internal utilities =====
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
fn debug<B: ByteStr>(bytes: &B, name: &str, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
let mut buf = bytes.buf();
|
|
||||||
|
|
||||||
try!(write!(fmt, "{}[len={}; ", name, bytes.len()));
|
|
||||||
|
|
||||||
let mut rem = 128;
|
|
||||||
|
|
||||||
while let Some(byte) = buf.read_byte() {
|
|
||||||
if rem > 0 {
|
|
||||||
if is_ascii(byte) {
|
|
||||||
try!(write!(fmt, "{}", byte as char));
|
|
||||||
} else {
|
|
||||||
try!(write!(fmt, "\\x{:02X}", byte));
|
|
||||||
}
|
|
||||||
|
|
||||||
rem -= 1;
|
|
||||||
} else {
|
|
||||||
try!(write!(fmt, " ... "));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try!(write!(fmt, "]"));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_ascii(byte: u8) -> bool {
|
|
||||||
match byte {
|
|
||||||
10 | 13 | 32...126 => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use {ByteBuf, SmallByteStr};
|
use {ByteBuf, MutBuf, SmallByteStr, Source, BufError};
|
||||||
use traits::{Buf, ByteStr, ToBytes};
|
use traits::{Buf, ByteStr, ToBytes};
|
||||||
use std::{fmt, mem, ops, ptr};
|
use std::{cmp, fmt, mem, ops, ptr};
|
||||||
use std::any::{Any, TypeId};
|
use std::any::{Any, TypeId};
|
||||||
|
|
||||||
const INLINE: usize = 1;
|
const INLINE: usize = 1;
|
||||||
@@ -194,6 +194,39 @@ impl Drop for Bytes {
|
|||||||
unsafe impl Send for Bytes { }
|
unsafe impl Send for Bytes { }
|
||||||
unsafe impl Sync for Bytes { }
|
unsafe impl Sync for Bytes { }
|
||||||
|
|
||||||
|
impl<'a> Source for &'a Bytes {
|
||||||
|
type Error = BufError;
|
||||||
|
|
||||||
|
fn fill<B: MutBuf>(self, dst: &mut B) -> Result<usize, BufError> {
|
||||||
|
let mut src = ByteStr::buf(self);
|
||||||
|
let mut res = 0;
|
||||||
|
|
||||||
|
while src.has_remaining() && dst.has_remaining() {
|
||||||
|
let mut l;
|
||||||
|
|
||||||
|
{
|
||||||
|
let s = src.bytes();
|
||||||
|
let d = dst.mut_bytes();
|
||||||
|
l = cmp::min(s.len(), d.len());
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ptr::copy_nonoverlapping(
|
||||||
|
s.as_ptr(),
|
||||||
|
d.as_mut_ptr(),
|
||||||
|
l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
src.advance(l);
|
||||||
|
dst.advance(l);
|
||||||
|
|
||||||
|
res += l;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
trait ByteStrPriv {
|
trait ByteStrPriv {
|
||||||
|
|
||||||
fn buf(&self) -> Box<Buf+'static>;
|
fn buf(&self) -> Box<Buf+'static>;
|
||||||
+185
@@ -0,0 +1,185 @@
|
|||||||
|
mod byte_str;
|
||||||
|
mod bytes;
|
||||||
|
mod rope;
|
||||||
|
|
||||||
|
pub use self::byte_str::{SeqByteStr, SmallByteStr, SmallByteStrBuf};
|
||||||
|
pub use self::bytes::Bytes;
|
||||||
|
pub use self::rope::{Rope, RopeBuf};
|
||||||
|
|
||||||
|
use {Buf};
|
||||||
|
use std::{cmp, fmt, ops};
|
||||||
|
use std::any::Any;
|
||||||
|
|
||||||
|
/// An immutable sequence of bytes. Operations will not mutate the original
|
||||||
|
/// value. Since only immutable access is permitted, operations do not require
|
||||||
|
/// copying (though, sometimes copying will happen as an optimization).
|
||||||
|
pub trait ByteStr : Clone + Sized + Send + Sync + Any + ToBytes + ops::Index<usize, Output=u8> + 'static {
|
||||||
|
|
||||||
|
// Until HKT lands, the buf must be bound by 'static
|
||||||
|
type Buf: Buf+'static;
|
||||||
|
|
||||||
|
/// Returns a read-only `Buf` for accessing the byte contents of the
|
||||||
|
/// `ByteStr`.
|
||||||
|
fn buf(&self) -> Self::Buf;
|
||||||
|
|
||||||
|
/// Returns a new `Bytes` value representing the concatenation of `self`
|
||||||
|
/// with the given `Bytes`.
|
||||||
|
fn concat<B: ByteStr+'static>(&self, other: &B) -> Bytes;
|
||||||
|
|
||||||
|
/// Returns the number of bytes in the ByteStr
|
||||||
|
fn len(&self) -> usize;
|
||||||
|
|
||||||
|
/// Returns true if the length of the `ByteStr` is 0
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.len() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new ByteStr value containing the byte range between `begin`
|
||||||
|
/// (inclusive) and `end` (exclusive)
|
||||||
|
fn slice(&self, begin: usize, end: usize) -> Bytes;
|
||||||
|
|
||||||
|
/// Returns a new ByteStr value containing the byte range starting from
|
||||||
|
/// `begin` (inclusive) to the end of the byte str.
|
||||||
|
///
|
||||||
|
/// Equivalent to `bytes.slice(begin, bytes.len())`
|
||||||
|
fn slice_from(&self, begin: usize) -> Bytes {
|
||||||
|
self.slice(begin, self.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new ByteStr value containing the byte range from the start up
|
||||||
|
/// to `end` (exclusive).
|
||||||
|
///
|
||||||
|
/// Equivalent to `bytes.slice(0, end)`
|
||||||
|
fn slice_to(&self, end: usize) -> Bytes {
|
||||||
|
self.slice(0, end)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Divides the value into two `Bytes` at the given index.
|
||||||
|
///
|
||||||
|
/// The first will contain all bytes from `[0, mid]` (excluding the index
|
||||||
|
/// `mid` itself) and the second will contain all indices from `[mid, len)`
|
||||||
|
/// (excluding the index `len` itself).
|
||||||
|
///
|
||||||
|
/// Panics if `mid > len`.
|
||||||
|
fn split_at(&self, mid: usize) -> (Bytes, Bytes) {
|
||||||
|
(self.slice_to(mid), self.slice_from(mid))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_parteq {
|
||||||
|
($ty:ty) => {
|
||||||
|
impl<B: ByteStr> cmp::PartialEq<B> for $ty {
|
||||||
|
fn eq(&self, other: &B) -> bool {
|
||||||
|
if self.len() != other.len() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buf1 = self.buf();
|
||||||
|
let mut buf2 = self.buf();
|
||||||
|
|
||||||
|
while buf1.has_remaining() {
|
||||||
|
let len;
|
||||||
|
|
||||||
|
{
|
||||||
|
let b1 = buf1.bytes();
|
||||||
|
let b2 = buf2.bytes();
|
||||||
|
|
||||||
|
len = cmp::min(b1.len(), b2.len());
|
||||||
|
|
||||||
|
if b1[..len] != b2[..len] {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf1.advance(len);
|
||||||
|
buf2.advance(len);
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ne(&self, other: &B) -> bool {
|
||||||
|
return !self.eq(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_parteq!(SeqByteStr);
|
||||||
|
impl_parteq!(SmallByteStr);
|
||||||
|
impl_parteq!(Bytes);
|
||||||
|
impl_parteq!(Rope);
|
||||||
|
|
||||||
|
macro_rules! impl_eq {
|
||||||
|
($ty:ty) => {
|
||||||
|
impl cmp::Eq for $ty {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_eq!(Bytes);
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ===== ToBytes =====
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub trait ToBytes {
|
||||||
|
/// Consumes the value and returns a `Bytes` instance containing
|
||||||
|
/// identical bytes
|
||||||
|
fn to_bytes(self) -> Bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ToBytes for &'a [u8] {
|
||||||
|
fn to_bytes(self) -> Bytes {
|
||||||
|
Bytes::from_slice(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ToBytes for &'a Vec<u8> {
|
||||||
|
fn to_bytes(self) -> Bytes {
|
||||||
|
(&self[..]).to_bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ===== Internal utilities =====
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
fn debug<B: ByteStr>(bytes: &B, name: &str, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let mut buf = bytes.buf();
|
||||||
|
|
||||||
|
try!(write!(fmt, "{}[len={}; ", name, bytes.len()));
|
||||||
|
|
||||||
|
let mut rem = 128;
|
||||||
|
|
||||||
|
while let Some(byte) = buf.read_byte() {
|
||||||
|
if rem > 0 {
|
||||||
|
if is_ascii(byte) {
|
||||||
|
try!(write!(fmt, "{}", byte as char));
|
||||||
|
} else {
|
||||||
|
try!(write!(fmt, "\\x{:02X}", byte));
|
||||||
|
}
|
||||||
|
|
||||||
|
rem -= 1;
|
||||||
|
} else {
|
||||||
|
try!(write!(fmt, " ... "));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try!(write!(fmt, "]"));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_ascii(byte: u8) -> bool {
|
||||||
|
match byte {
|
||||||
|
10 | 13 | 32...126 => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user