Polish API surface

This commit is contained in:
Carl Lerche
2017-02-16 11:15:46 -08:00
parent bababa8797
commit 646624c130
6 changed files with 474 additions and 243 deletions
+51 -48
View File
@@ -2,9 +2,30 @@ use {Bytes};
use byteorder::ByteOrder;
use std::{cmp, io, ptr, usize};
/// A trait for values that provide sequential read access to bytes.
/// Read bytes from a buffer.
///
/// A buffer stores bytes in memory such that read access is infallible. The
/// underlying storage may or may not be in contiguous memory. A `Buf` value is
/// a cursor into the buffer. Reading from `Buf` advances the cursor position.
///
/// The simplest `Buf` is a `Cursor` wrapping a `[u8]`.
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"hello world");
///
/// assert_eq!(b'h', buf.get_u8());
/// assert_eq!(b'e', buf.get_u8());
/// assert_eq!(b'l', buf.get_u8());
///
/// let mut rest = vec![];
/// buf.copy_to(&mut rest);
///
/// assert_eq!(&rest[..], b"lo world");
/// ```
pub trait Buf {
/// Returns the number of bytes that can be accessed from the Buf
fn remaining(&self) -> usize;
@@ -70,16 +91,6 @@ pub trait Buf {
}
}
/// Gets an unsigned 8 bit integer from the `Buf` without advancing the
/// buffer cursor
fn peek_u8(&self) -> Option<u8> {
if self.has_remaining() {
Some(self.bytes()[0])
} else {
None
}
}
/// Gets an unsigned 8 bit integer from the `Buf`.
fn get_u8(&mut self) -> u8 {
let mut buf = [0; 1];
@@ -203,7 +214,7 @@ pub trait BufMut {
///
/// Panics if `self` does not have enough capacity to copy all the data
/// from `src`
fn copy_from<S: Source>(&mut self, src: S) where Self: Sized {
fn put<S: Source>(&mut self, src: S) where Self: Sized {
src.source(self);
}
@@ -219,14 +230,14 @@ pub trait BufMut {
///
/// {
/// let mut buf = Cursor::new(&mut dst);
/// buf.copy_from_slice(b"hello");
/// buf.put_slice(b"hello");
///
/// assert_eq!(1, buf.remaining_mut());
/// }
///
/// assert_eq!(b"hello\0", &dst);
/// ```
fn copy_from_slice(&mut self, src: &[u8]) {
fn put_slice(&mut self, src: &[u8]) {
let mut off = 0;
assert!(self.remaining_mut() >= src.len(), "buffer overflow");
@@ -251,66 +262,46 @@ pub trait BufMut {
}
}
/// Writes the given string into self.
///
/// # Panics
///
/// The function panics if `self` does not have enough remaining capacity
/// to write the full string.
fn put_str(&mut self, src: &str) {
self.copy_from_slice(src.as_bytes());
}
/// Writes an unsigned 8 bit integer to the BufMut.
fn put_u8(&mut self, n: u8) {
self.copy_from_slice(&[n])
}
/// Writes a signed 8 bit integer to the BufMut.
fn put_i8(&mut self, n: i8) {
self.copy_from_slice(&[n as u8])
}
/// Writes an unsigned 16 bit integer to the BufMut.
fn put_u16<T: ByteOrder>(&mut self, n: u16) {
let mut buf = [0; 2];
T::write_u16(&mut buf, n);
self.copy_from_slice(&buf)
self.put_slice(&buf)
}
/// Writes a signed 16 bit integer to the BufMut.
fn put_i16<T: ByteOrder>(&mut self, n: i16) {
let mut buf = [0; 2];
T::write_i16(&mut buf, n);
self.copy_from_slice(&buf)
self.put_slice(&buf)
}
/// Writes an unsigned 32 bit integer to the BufMut.
fn put_u32<T: ByteOrder>(&mut self, n: u32) {
let mut buf = [0; 4];
T::write_u32(&mut buf, n);
self.copy_from_slice(&buf)
self.put_slice(&buf)
}
/// Writes a signed 32 bit integer to the BufMut.
fn put_i32<T: ByteOrder>(&mut self, n: i32) {
let mut buf = [0; 4];
T::write_i32(&mut buf, n);
self.copy_from_slice(&buf)
self.put_slice(&buf)
}
/// Writes an unsigned 64 bit integer to the BufMut.
fn put_u64<T: ByteOrder>(&mut self, n: u64) {
let mut buf = [0; 8];
T::write_u64(&mut buf, n);
self.copy_from_slice(&buf)
self.put_slice(&buf)
}
/// Writes a signed 64 bit integer to the BufMut.
fn put_i64<T: ByteOrder>(&mut self, n: i64) {
let mut buf = [0; 8];
T::write_i64(&mut buf, n);
self.copy_from_slice(&buf)
self.put_slice(&buf)
}
/// Writes an unsigned n-bytes integer to the BufMut.
@@ -320,7 +311,7 @@ pub trait BufMut {
fn put_uint<T: ByteOrder>(&mut self, n: u64, nbytes: usize) {
let mut buf = [0; 8];
T::write_uint(&mut buf, n, nbytes);
self.copy_from_slice(&buf[0..nbytes])
self.put_slice(&buf[0..nbytes])
}
/// Writes a signed n-bytes integer to the BufMut.
@@ -330,7 +321,7 @@ pub trait BufMut {
fn put_int<T: ByteOrder>(&mut self, n: i64, nbytes: usize) {
let mut buf = [0; 8];
T::write_int(&mut buf, n, nbytes);
self.copy_from_slice(&buf[0..nbytes])
self.put_slice(&buf[0..nbytes])
}
/// Writes a IEEE754 single-precision (4 bytes) floating point number to
@@ -338,7 +329,7 @@ pub trait BufMut {
fn put_f32<T: ByteOrder>(&mut self, n: f32) {
let mut buf = [0; 4];
T::write_f32(&mut buf, n);
self.copy_from_slice(&buf)
self.put_slice(&buf)
}
/// Writes a IEEE754 double-precision (8 bytes) floating point number to
@@ -346,7 +337,7 @@ pub trait BufMut {
fn put_f64<T: ByteOrder>(&mut self, n: f64) {
let mut buf = [0; 8];
T::write_f64(&mut buf, n);
self.copy_from_slice(&buf)
self.put_slice(&buf)
}
/// Creates a "by reference" adaptor for this instance of BufMut
@@ -446,14 +437,26 @@ pub trait Source {
impl<'a> Source for &'a [u8] {
fn source<B: BufMut>(self, buf: &mut B) {
buf.copy_from_slice(self);
buf.put_slice(self);
}
}
impl<'a> Source for &'a str {
fn source<B: BufMut>(self, buf: &mut B) {
buf.put_slice(self.as_bytes());
}
}
impl Source for u8 {
fn source<B: BufMut>(self, buf: &mut B) {
let src = [self];
buf.copy_from_slice(&src);
buf.put_slice(&src);
}
}
impl Source for i8 {
fn source<B: BufMut>(self, buf: &mut B) {
buf.put_slice(&[self as u8])
}
}
@@ -584,7 +587,7 @@ impl<B: BufMut + Sized> io::Write for Writer<B> {
fn write(&mut self, src: &[u8]) -> io::Result<usize> {
let n = cmp::min(self.buf.remaining_mut(), src.len());
self.buf.copy_from(&src[0..n]);
self.buf.put(&src[0..n]);
Ok(n)
}
-182
View File
@@ -1,182 +0,0 @@
use {Buf, BufMut};
use std::{cmp, fmt};
/// A buffer adapter which limits the bytes read from an underlying value.
#[derive(Debug)]
pub struct Take<T> {
inner: T,
limit: usize,
}
/// A buffer adapter which limits the bytes written from an underlying value.
#[derive(Debug)]
pub struct TakeMut<T> {
inner: T,
limit: usize,
}
pub fn new<T>(inner: T, limit: usize) -> Take<T> {
Take {
inner: inner,
limit: limit,
}
}
pub fn new_mut<T>(inner: T, limit: usize) -> TakeMut<T> {
TakeMut {
inner: inner,
limit: limit,
}
}
/*
*
* ===== impl Take =====
*
*/
impl<T> Take<T> {
/// Consumes this `Take`, returning the underlying value.
pub fn into_inner(self) -> T {
self.inner
}
/// Gets a reference to the underlying value in this `Take`.
pub fn get_ref(&self) -> &T {
&self.inner
}
/// Gets a mutable reference to the underlying value in this `Take`.
pub fn get_mut(&mut self) -> &mut T {
&mut self.inner
}
/// Returns the maximum number of bytes that are made available from the
/// underlying value.
pub fn limit(&self) -> usize {
self.limit
}
/// Sets the maximum number of bytes that are made available from the
/// underlying value.
pub fn set_limit(&mut self, lim: usize) {
self.limit = lim
}
}
impl<T: Buf> Buf for Take<T> {
fn remaining(&self) -> usize {
cmp::min(self.inner.remaining(), self.limit)
}
fn bytes(&self) -> &[u8] {
&self.inner.bytes()[..self.limit]
}
fn advance(&mut self, cnt: usize) {
let cnt = cmp::min(cnt, self.limit);
self.limit -= cnt;
self.inner.advance(cnt);
}
}
impl<T: BufMut> BufMut for Take<T> {
fn remaining_mut(&self) -> usize {
self.inner.remaining_mut()
}
unsafe fn bytes_mut(&mut self) -> &mut [u8] {
self.inner.bytes_mut()
}
unsafe fn advance_mut(&mut self, cnt: usize) {
self.inner.advance_mut(cnt)
}
}
impl<T: BufMut> fmt::Write for Take<T> {
fn write_str(&mut self, s: &str) -> fmt::Result {
BufMut::put_str(self, s);
Ok(())
}
fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
fmt::write(self, args)
}
}
/*
*
* ===== impl TakeMut =====
*
*/
impl<T> TakeMut<T> {
/// Consumes this `TakeMut`, returning the underlying value.
pub fn into_inner(self) -> T {
self.inner
}
/// Gets a reference to the underlying value in this `TakeMut`.
pub fn get_ref(&self) -> &T {
&self.inner
}
/// Gets a mutable reference to the underlying value in this `TakeMut`.
pub fn get_mut(&mut self) -> &mut T {
&mut self.inner
}
/// Returns the maximum number of bytes that are made available from the
/// underlying value.
pub fn limit(&self) -> usize {
self.limit
}
/// Sets the maximum number of bytes that are made available from the
/// underlying value.
pub fn set_limit(&mut self, lim: usize) {
self.limit = lim
}
}
impl<T: Buf> Buf for TakeMut<T> {
fn remaining(&self) -> usize {
self.inner.remaining()
}
fn bytes(&self) -> &[u8] {
self.inner.bytes()
}
fn advance(&mut self, cnt: usize) {
self.inner.advance(cnt)
}
}
impl<T: BufMut> BufMut for TakeMut<T> {
fn remaining_mut(&self) -> usize {
cmp::min(self.inner.remaining_mut(), self.limit)
}
unsafe fn bytes_mut(&mut self) -> &mut [u8] {
&mut self.inner.bytes_mut()[..self.limit]
}
unsafe fn advance_mut(&mut self, cnt: usize) {
let cnt = cmp::min(cnt, self.limit);
self.limit -= cnt;
self.inner.advance_mut(cnt);
}
}
impl<T: BufMut> fmt::Write for TakeMut<T> {
fn write_str(&mut self, s: &str) -> fmt::Result {
BufMut::put_str(self, s);
Ok(())
}
fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
fmt::write(self, args)
}
}
+287 -8
View File
@@ -114,9 +114,9 @@ pub struct Bytes {
///
/// let mut buf = BytesMut::with_capacity(64);
///
/// buf.put_u8(b'h');
/// buf.put_u8(b'e');
/// buf.put_str("llo");
/// buf.put(b'h');
/// buf.put(b'e');
/// buf.put("llo");
///
/// assert_eq!(&buf[..], b"hello");
///
@@ -489,12 +489,24 @@ impl From<Vec<u8>> for Bytes {
}
}
impl From<String> for Bytes {
fn from(src: String) -> Bytes {
BytesMut::from(src).freeze()
}
}
impl<'a> From<&'a [u8]> for Bytes {
fn from(src: &'a [u8]) -> Bytes {
BytesMut::from(src).freeze()
}
}
impl<'a> From<&'a str> for Bytes {
fn from(src: &'a str) -> Bytes {
BytesMut::from(src).freeze()
}
}
impl PartialEq for Bytes {
fn eq(&self, other: &Bytes) -> bool {
self.inner.as_ref() == other.inner.as_ref()
@@ -538,7 +550,7 @@ impl BytesMut {
/// // `bytes` contains no data, even though there is capacity
/// assert_eq!(bytes.len(), 0);
///
/// bytes.copy_from_slice(b"hello world");
/// bytes.put(&b"hello world"[..]);
///
/// assert_eq!(&bytes[..], b"hello world");
/// ```
@@ -618,7 +630,7 @@ impl BytesMut {
/// use std::thread;
///
/// let mut b = BytesMut::with_capacity(64);
/// b.put_str("hello world");
/// b.put("hello world");
/// let b1 = b.freeze();
/// let b2 = b1.clone();
///
@@ -785,6 +797,63 @@ impl BytesMut {
pub unsafe fn set_len(&mut self, len: usize) {
self.inner.set_len(len)
}
/// Reserves capacity for at least `additional` more bytes to be inserted
/// into the given `BytesMut`.
///
/// More than `additional` bytes may be reserved in order to avoid frequent
/// reallocations. A call to `reserve` may result in an allocation.
///
/// # Examples
///
/// ```
/// use bytes::BytesMut;
///
/// let mut b = BytesMut::from(&b"hello"[..]);
/// b.reserve(64);
/// assert!(b.capacity() >= 69);
/// ```
///
/// # Panics
///
/// Panics if the new capacity overflows usize.
pub fn reserve(&mut self, additional: usize) {
self.inner.reserve(additional)
}
/// Attempts to reclaim ownership of the full buffer.
///
/// Returns `true` if the reclaim is successful.
///
/// If the `BytesMut` handle is the only outstanding handle pointing to the
/// memory slice, the handle's view will be set to the full memory slice,
/// enabling reusing buffer space without allocating.
///
/// Any data in the `BytesMut` handle will be copied to the start of the
/// memory region.
///
/// ```rust
/// use bytes::BytesMut;
///
/// let mut bytes = BytesMut::from(
/// "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
///
/// // Create a new handle to the shared memory region
/// let a = bytes.drain_to(5);
///
/// // Attempting to reclaim here will fail due to `a` still being in
/// // existence.
/// assert!(!bytes.try_reclaim());
/// assert_eq!(bytes.capacity(), 51);
///
/// // Dropping the handle will allow reclaim to succeed.
/// drop(a);
/// assert!(bytes.try_reclaim());
/// assert_eq!(bytes.capacity(), 56);
/// ```
pub fn try_reclaim(&mut self) -> bool {
self.inner.try_reclaim()
}
}
impl BufMut for BytesMut {
@@ -806,7 +875,7 @@ impl BufMut for BytesMut {
}
#[inline]
fn copy_from_slice(&mut self, src: &[u8]) {
fn put_slice(&mut self, src: &[u8]) {
assert!(self.remaining_mut() >= src.len());
let len = src.len();
@@ -875,6 +944,12 @@ impl From<Vec<u8>> for BytesMut {
}
}
impl From<String> for BytesMut {
fn from(src: String) -> BytesMut {
BytesMut::from(src.into_bytes())
}
}
impl<'a> From<&'a [u8]> for BytesMut {
fn from(src: &'a [u8]) -> BytesMut {
if src.len() <= INLINE_CAP {
@@ -894,12 +969,18 @@ impl<'a> From<&'a [u8]> for BytesMut {
}
} else {
let mut buf = BytesMut::with_capacity(src.len());
buf.copy_from_slice(src.as_ref());
buf.put(src.as_ref());
buf
}
}
}
impl<'a> From<&'a str> for BytesMut {
fn from(src: &'a str) -> BytesMut {
BytesMut::from(src.as_bytes())
}
}
impl From<Bytes> for BytesMut {
fn from(src: Bytes) -> BytesMut {
src.try_mut()
@@ -924,7 +1005,7 @@ impl fmt::Debug for BytesMut {
impl fmt::Write for BytesMut {
fn write_str(&mut self, s: &str) -> fmt::Result {
BufMut::put_str(self, s);
BufMut::put(self, s);
Ok(())
}
@@ -1220,6 +1301,150 @@ impl Inner {
}
}
#[inline]
fn reserve(&mut self, additional: usize) {
let len = self.len();
let rem = self.capacity() - len;
if additional <= rem {
// Nothing more to do
return;
}
match self.kind() {
Kind::Vec => {
unsafe {
let d = &mut *self.data.get();
// Promote this `Bytes` to an arc, and clone it
let mut v = Vec::from_raw_parts(d.ptr, d.len, d.cap);
v.reserve(additional);
// Update the info
d.ptr = v.as_mut_ptr();
d.len = v.len();
d.cap = v.capacity();
// Drop the vec reference
mem::forget(v);
}
}
Kind::Arc => {
unsafe {
// Compute the new capacity
let new_cap = len + additional;
// Create a new vector to store the data
let mut v = Vec::with_capacity(new_cap);
// Copy the bytes
v.extend_from_slice(self.as_ref());
let d = &mut *self.data.get();
d.ptr = v.as_mut_ptr();
d.len = v.len();
d.cap = v.capacity();
mem::forget(v);
// Drop the arc reference
let _: Arc<UnsafeCell<Vec<u8>>> = mem::transmute(self.arc.get());
self.arc.set(0);
}
}
Kind::Inline => {
let new_cap = len + additional;
unsafe {
if new_cap <= INLINE_CAP {
let dst = &mut self.data as *mut _ as *mut u8;
let src = self.inline_ptr();
ptr::copy(src, dst, len);
let mut a = KIND_INLINE;
a |= len << INLINE_LEN_OFFSET;
self.arc.set(a);
} else {
let mut v = Vec::with_capacity(new_cap);
// Copy the bytes
v.extend_from_slice(self.as_ref());
let d = &mut *self.data.get();
d.ptr = v.as_mut_ptr();
d.len = v.len();
d.cap = v.capacity();
mem::forget(v);
self.arc.set(0);
}
}
}
Kind::Static => unreachable!(),
}
}
/// This must take `&mut self` in order to be able to copy memory in the
/// inline case.
#[inline]
fn try_reclaim(&mut self) -> bool {
match self.kind() {
Kind::Inline => {
if self.inline_start() > 0 {
// Shift the data back to the front
unsafe {
let len = self.inline_len();
let dst = &mut self.data as *mut _ as *mut u8;
let src = self.inline_ptr();
ptr::copy(src, dst, len);
let mut a = KIND_INLINE;
a |= len << INLINE_LEN_OFFSET;
self.arc.set(a);
}
}
true
}
Kind::Arc => {
unsafe {
let arc: &mut Shared = mem::transmute(&mut self.arc);
// Check if mut safe
if Arc::get_mut(arc).is_none() {
return false;
}
let v = &mut *arc.get();
let d = &mut *self.data.get();
let len = v.len();
let ptr = v.as_mut_ptr();
ptr::copy(d.ptr, ptr, len);
d.ptr = ptr;
d.len = len;
d.cap = v.capacity();
true
}
}
Kind::Vec => {
true
}
Kind::Static => unreachable!(),
}
}
#[inline]
fn kind(&self) -> Kind {
let arc = self.arc.get();
@@ -1283,6 +1508,12 @@ impl PartialEq<[u8]> for BytesMut {
}
}
impl PartialEq<str> for BytesMut {
fn eq(&self, other: &str) -> bool {
&**self == other.as_bytes()
}
}
impl PartialEq<BytesMut> for [u8] {
fn eq(&self, other: &BytesMut) -> bool {
*other == *self
@@ -1295,12 +1526,24 @@ impl PartialEq<Vec<u8>> for BytesMut {
}
}
impl PartialEq<String> for BytesMut {
fn eq(&self, other: &String) -> bool {
*self == &other[..]
}
}
impl PartialEq<BytesMut> for Vec<u8> {
fn eq(&self, other: &BytesMut) -> bool {
*other == *self
}
}
impl PartialEq<BytesMut> for String {
fn eq(&self, other: &BytesMut) -> bool {
*other == *self
}
}
impl<'a, T: ?Sized> PartialEq<&'a T> for BytesMut
where BytesMut: PartialEq<T>
{
@@ -1315,36 +1558,72 @@ impl<'a> PartialEq<BytesMut> for &'a [u8] {
}
}
impl<'a> PartialEq<BytesMut> for &'a str {
fn eq(&self, other: &BytesMut) -> bool {
*other == *self
}
}
impl PartialEq<[u8]> for Bytes {
fn eq(&self, other: &[u8]) -> bool {
self.inner.as_ref() == other
}
}
impl PartialEq<str> for Bytes {
fn eq(&self, other: &str) -> bool {
self.inner.as_ref() == other.as_bytes()
}
}
impl PartialEq<Bytes> for [u8] {
fn eq(&self, other: &Bytes) -> bool {
*other == *self
}
}
impl PartialEq<Bytes> for str {
fn eq(&self, other: &Bytes) -> bool {
*other == *self
}
}
impl PartialEq<Vec<u8>> for Bytes {
fn eq(&self, other: &Vec<u8>) -> bool {
*self == &other[..]
}
}
impl PartialEq<String> for Bytes {
fn eq(&self, other: &String) -> bool {
*self == &other[..]
}
}
impl PartialEq<Bytes> for Vec<u8> {
fn eq(&self, other: &Bytes) -> bool {
*other == *self
}
}
impl PartialEq<Bytes> for String {
fn eq(&self, other: &Bytes) -> bool {
*other == *self
}
}
impl<'a> PartialEq<Bytes> for &'a [u8] {
fn eq(&self, other: &Bytes) -> bool {
*other == *self
}
}
impl<'a> PartialEq<Bytes> for &'a str {
fn eq(&self, other: &Bytes) -> bool {
*other == *self
}
}
impl<'a, T: ?Sized> PartialEq<&'a T> for Bytes
where Bytes: PartialEq<T>
{
+63
View File
@@ -1,4 +1,67 @@
//! Provides abstractions for working with bytes.
//!
//! The `bytes` crate provides an efficient byte buffer structure
//! ([`Bytes`](struct.Bytes.html)) and traits for working with buffer
//! implementations ([`Buf`](trait.Buf.html), [`BufMut`](trait.BufMut.html)).
//!
//! # `Bytes`
//!
//! `Bytes` is an efficient container for storing and operating on continguous
//! slices of memory. It is intended for use primarily in networking code, but
//! could have applications elsewhere as well.
//!
//! `Bytes` values facilitate zero-copy network programming by allowing multiple
//! `Bytes` objects to point to the same underlying memory. This is managed by
//! using a reference count to track when the memory is no longer needed and can
//! be freed.
//!
//! See the [struct docs](struct.Bytes.html) for more details.
//!
//! # `Buf`, `BufMut`
//!
//! These two traits provide read and write access to buffers. The underlying
//! storage may or may not be in contiguous memory. For example, `Bytes` is a
//! buffer that guarantees contiguous memory, but a
//! [rope](https://en.wikipedia.org/wiki/Rope_(data_structure)) stores the bytes
//! in disjoint chunks. `Buf` and `BufMut` maintain cursors tracking the current
//! position in the underlying byte storage. When bytes are read or written, the
//! cursor is advanced.
//!
//! ## Relation with `Read` and `Write`
//!
//! At first glance, it may seem that `Buf` and `BufMut` overlap in
//! functionality with `std::io::Ready` and `std::io::Write`. However, they
//! serve different purposes. A buffer is the value that is provided as an
//! argument to `Read::read` and `Write::write`. `Read` and `Write` may then
//! perform a syscall, which has the potential of failing. Operations on `Buf`
//! and `BufMut` are infallible.
//!
//! # Example
//!
//! ```
//! use bytes::{BytesMut, Buf, BufMut};
//! use std::io::Cursor;
//! use std::thread;
//!
//! // Allocate a buffer capable of holding 1024 bytes.
//! let mut buf = BytesMut::with_capacity(1024);
//!
//! // Write some data
//! buf.put("Hello world");
//! buf.put(b'-');
//! buf.put("goodbye");
//!
//! // Freeze the buffer, enabling concurrent access
//! let b1 = buf.freeze();
//! let b2 = b1.clone();
//!
//! thread::spawn(move || {
//! assert_eq!(&b1[..], b"Hello world-goodbye");
//! });
//!
//! let mut buf = Cursor::new(b2);
//! assert_eq!(b'H', buf.get_u8());
//! ```
#![deny(warnings, missing_docs)]
+70 -2
View File
@@ -1,10 +1,16 @@
extern crate bytes;
use bytes::{Bytes, BytesMut};
use bytes::{Bytes, BytesMut, BufMut};
const LONG: &'static [u8] = b"mary had a little lamb, little lamb, little lamb";
const SHORT: &'static [u8] = b"hello world";
#[cfg(target_pointer_width = "64")]
const INLINE_CAP: usize = 8 * 3;
#[cfg(target_pointer_width = "32")]
const INNER_CAP: usize = 4 * 3;
fn is_sync<T: Sync>() {}
fn is_send<T: Send>() {}
@@ -193,5 +199,67 @@ fn fns_defined_for_bytes_mut() {
// Iterator
let v: Vec<u8> = bytes.iter().map(|b| *b).collect();
assert_eq!(&v[..], &bytes[..]);
assert_eq!(&v[..], bytes);
}
#[test]
fn reserve() {
// Inline -> Vec
let mut bytes = BytesMut::with_capacity(8);
bytes.put("hello");
bytes.reserve(40);
assert_eq!(bytes.capacity(), 45);
assert_eq!(bytes, "hello");
// Inline -> Inline
let mut bytes = BytesMut::with_capacity(INLINE_CAP);
bytes.put("abcdefghijkl");
let a = bytes.drain_to(10);
bytes.reserve(INLINE_CAP - 3);
assert_eq!(INLINE_CAP, bytes.capacity());
assert_eq!(bytes, "kl");
assert_eq!(a, "abcdefghij");
// Vec -> Vec
let mut bytes = BytesMut::from(LONG);
bytes.reserve(64);
assert_eq!(bytes.capacity(), LONG.len() + 64);
// Arc -> Vec
let mut bytes = BytesMut::from(LONG);
let a = bytes.drain_to(30);
bytes.reserve(128);
assert_eq!(bytes.capacity(), bytes.len() + 128);
drop(a);
}
#[test]
fn try_reclaim() {
// Inline w/ start at zero
let mut bytes = BytesMut::from(&SHORT[..]);
assert!(bytes.try_reclaim());
assert_eq!(bytes.capacity(), INLINE_CAP);
assert_eq!(bytes, SHORT);
// Inline w/ start not at zero
let mut bytes = BytesMut::from(&SHORT[..]);
let _ = bytes.drain_to(2);
assert_eq!(bytes.capacity(), INLINE_CAP - 2);
assert!(bytes.try_reclaim());
assert_eq!(bytes.capacity(), INLINE_CAP);
assert_eq!(bytes, &SHORT[2..]);
// Arc
let mut bytes = BytesMut::from(&LONG[..]);
let a = bytes.drain_to(2);
assert!(!bytes.try_reclaim());
assert_eq!(bytes.capacity(), LONG.len() - 2);
drop(a);
assert!(bytes.try_reclaim());
assert_eq!(bytes.capacity(), LONG.len());
}
+3 -3
View File
@@ -15,7 +15,7 @@ fn test_vec_as_mut_buf() {
assert!(buf.bytes_mut().len() >= 64);
}
buf.copy_from(&b"zomg"[..]);
buf.put(&b"zomg"[..]);
assert_eq!(&buf, b"zomg");
@@ -23,7 +23,7 @@ fn test_vec_as_mut_buf() {
assert_eq!(buf.capacity(), 64);
for _ in 0..16 {
buf.copy_from(&b"zomg"[..]);
buf.put(&b"zomg"[..]);
}
assert_eq!(buf.len(), 68);
@@ -32,7 +32,7 @@ fn test_vec_as_mut_buf() {
#[test]
fn test_put_u8() {
let mut buf = Vec::with_capacity(8);
buf.put_u8(33);
buf.put::<u8>(33);
assert_eq!(b"\x21", &buf[..]);
}