Compare commits

...
13 Commits
Author SHA1 Message Date
Carl Lerche 3240fb9cd9 Bump version to v0.4.4 2017-05-26 10:09:43 -07:00
Stepan KoltsovandCarl Lerche 9ae51c9f0c Implement truncate, clear for Bytes (#128) 2017-05-26 09:29:31 -07:00
brianwpandCarl Lerche 2b0602e756 impl ExactSizeIterator for Iter<T: Buf> (#127) 2017-05-24 08:13:19 -07:00
Stepan KoltsovandCarl Lerche 3f5890be70 Optimize Bytes::slice(n, n) (#123)
Return empty `Bytes` object

Bench for `slice_empty` difference is

```
55 ns/iter (+/- 1) # before this patch
17 ns/iter (+/- 5) # with this patch
```

Bench for `slice_not_empty` is

```
25,058 ns/iter (+/- 1,099) # before this patch
25,072 ns/iter (+/- 1,593) # with this patch
```
2017-05-22 13:15:08 -07:00
Carl Lerche 70ee87ea29 Fix benchmarks 2017-05-22 12:02:51 -07:00
Stepan KoltsovandCarl Lerche edf1af958a Minor doc fixes (#124) 2017-05-22 11:30:34 -07:00
Stepan KoltsovandCarl Lerche 7110d57b2f BytesMut::reserve should not overallocate (#117)
Round up to power of 2 is not necessary, because `reserve` already
doubles previous capacity in

```
	new_cap = cmp::max(
		cmp::max(v.capacity() << 1, new_cap),
		original_capacity);
```

which makes `reserve` calls constant in average. Avoiding rounding
up prevents `reserve` from wasting space when caller knows exactly
what space they need.

Patch adds three tests which would fail before this test. The most
important is this:

```
#[test]
fn reserve_in_arc_unique_does_not_overallocate() {
    let mut bytes = BytesMut::with_capacity(1000);
    bytes.take();

    // now bytes is Arc and refcount == 1

    assert_eq!(1000, bytes.capacity());
    bytes.reserve(2001);
    assert_eq!(2001, bytes.capacity());
}
```

It asserts that when user requests more than double of current
capacity, exactly the requested amount of memory is allocated and
is not wasted to next power of two.
2017-05-15 11:28:12 -07:00
Stepan KoltsovandCarl Lerche 07db74b009 Bytes::extend_from_slice (#120)
`extend_with_slice` is super-convenient operation on `Bytes`.

While `put_u8` would be expensive on `Bytes`, `extend_from_slice`
is OK, because it is batch, and it checks for kind only once.

Patch also adds `impl Extend for Bytes`.

cc #116
2017-05-15 11:27:45 -07:00
Jack O'ConnorandCarl Lerche 6af66c4f21 fix a docs typo (#115) 2017-05-02 12:35:06 -07:00
Stepan KoltsovandCarl Lerche fa44c7e355 BytesMut::extend_from_slice shortcut (#112)
Similar to `Vec::extend_from_slice`: it a reserve followed by
memcopy.
2017-05-02 11:28:12 -07:00
Stepan KoltsovandCarl Lerche 2c0cb1b6b8 BytesMut::new constructor (#114) 2017-05-02 11:23:20 -07:00
Arthur SilvaandCarl Lerche b196559818 Add serde support behind serde feature (#96) 2017-05-02 10:51:52 -07:00
Sean McArthurandCarl Lerche 37f6cabd96 implement Default for Bytes and BytesMut (#110) 2017-05-01 12:53:27 -07:00
14 changed files with 570 additions and 226 deletions
+3
View File
@@ -33,6 +33,9 @@ matrix:
- env: RUST_TEST_THREADS=1 TARGET=powerpc-unknown-linux-gnu
- env: RUST_TEST_THREADS=1 TARGET=powerpc64-unknown-linux-gnu
# Serde implementation
- env: EXTRA_ARGS="--features serde"
before_install: set -e
install:
+10 -2
View File
@@ -1,10 +1,18 @@
# 0.4.3 (April, 30, 2017)
# 0.4.4 (May 26, 2017)
* Add serde support behind feature flag
* Add `extend_from_slice` on `Bytes` and `BytesMut`
* Add `truncate` and `clear` on `Bytes`
* Misc additional std trait implementations
* Misc performance improvements
# 0.4.3 (April 30, 2017)
* Fix Vec::advance_mut bug
* Bump minimum Rust version to 1.15
* Misc performance tweaks
# 0.4.2 (April, 5, 2017)
# 0.4.2 (April 5, 2017)
* Misc performance tweaks
* Improved `Debug` implementation for `Bytes`
+3 -2
View File
@@ -1,7 +1,7 @@
[package]
name = "bytes"
version = "0.4.3"
version = "0.4.4"
license = "MIT"
authors = ["Carl Lerche <[email protected]>"]
description = "Types and traits for working with bytes"
@@ -22,6 +22,7 @@ categories = ["network-programming", "data-structures"]
[dependencies]
byteorder = "1.0.0"
iovec = "0.1"
serde = { version = "1.0", optional = true }
[dev-dependencies]
tokio-core = "0.1.0"
serde_test = "1.0"
+9
View File
@@ -24,6 +24,15 @@ extern crate bytes;
use bytes::{Bytes, BytesMut, Buf, BufMut};
```
## Serde support
Serde support is optional and disabled by default. To enable use the feature `serde`.
```toml
[dependencies]
bytes = { version = "0.4", features = ["serde"] }
```
# License
`bytes` is primarily distributed under the terms of both the MIT license and the
+148
View File
@@ -0,0 +1,148 @@
#![feature(test)]
extern crate bytes;
extern crate test;
use test::Bencher;
use bytes::{Bytes, BytesMut, BufMut};
#[bench]
fn alloc_small(b: &mut Bencher) {
b.iter(|| {
for _ in 0..1024 {
test::black_box(BytesMut::with_capacity(12));
}
})
}
#[bench]
fn alloc_mid(b: &mut Bencher) {
b.iter(|| {
test::black_box(BytesMut::with_capacity(128));
})
}
#[bench]
fn alloc_big(b: &mut Bencher) {
b.iter(|| {
test::black_box(BytesMut::with_capacity(4096));
})
}
#[bench]
fn deref_unique(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(4096);
buf.put(&[0u8; 1024][..]);
b.iter(|| {
for _ in 0..1024 {
test::black_box(&buf[..]);
}
})
}
#[bench]
fn deref_unique_unroll(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(4096);
buf.put(&[0u8; 1024][..]);
b.iter(|| {
for _ in 0..128 {
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
}
})
}
#[bench]
fn deref_shared(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(4096);
buf.put(&[0u8; 1024][..]);
let _b2 = buf.split_off(1024);
b.iter(|| {
for _ in 0..1024 {
test::black_box(&buf[..]);
}
})
}
#[bench]
fn deref_inline(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(8);
buf.put(&[0u8; 8][..]);
b.iter(|| {
for _ in 0..1024 {
test::black_box(&buf[..]);
}
})
}
#[bench]
fn deref_two(b: &mut Bencher) {
let mut buf1 = BytesMut::with_capacity(8);
buf1.put(&[0u8; 8][..]);
let mut buf2 = BytesMut::with_capacity(4096);
buf2.put(&[0u8; 1024][..]);
b.iter(|| {
for _ in 0..512 {
test::black_box(&buf1[..]);
test::black_box(&buf2[..]);
}
})
}
#[bench]
fn alloc_write_split_to_mid(b: &mut Bencher) {
b.iter(|| {
let mut buf = BytesMut::with_capacity(128);
buf.put_slice(&[0u8; 64]);
test::black_box(buf.split_to(64));
})
}
#[bench]
fn drain_write_drain(b: &mut Bencher) {
let data = [0u8; 128];
b.iter(|| {
let mut buf = BytesMut::with_capacity(1024);
let mut parts = Vec::with_capacity(8);
for _ in 0..8 {
buf.put(&data[..]);
parts.push(buf.split_to(128));
}
test::black_box(parts);
})
}
#[bench]
fn slice_empty(b: &mut Bencher) {
b.iter(|| {
// Use empty vec to avoid measure of allocation/deallocation
let bytes = Bytes::from(Vec::new());
(bytes.slice(0, 0), bytes)
})
}
#[bench]
fn slice_not_empty(b: &mut Bencher) {
b.iter(|| {
let b = Bytes::from(b"aabbccddeeffgghh".to_vec());
for _ in 0..1024 {
test::black_box(b.slice(3, 5));
test::black_box(&b);
}
})
}
-210
View File
@@ -1,210 +0,0 @@
#![feature(test)]
extern crate tokio_core;
extern crate bytes;
extern crate test;
mod bench_easy_buf {
use test::{self, Bencher};
use tokio_core::io::EasyBuf;
#[bench]
fn alloc_small(b: &mut Bencher) {
b.iter(|| {
for _ in 0..1024 {
test::black_box(EasyBuf::with_capacity(12));
}
})
}
#[bench]
fn alloc_mid(b: &mut Bencher) {
b.iter(|| {
test::black_box(EasyBuf::with_capacity(128));
})
}
#[bench]
fn alloc_big(b: &mut Bencher) {
b.iter(|| {
test::black_box(EasyBuf::with_capacity(4096));
})
}
#[bench]
fn deref_front(b: &mut Bencher) {
let mut buf = EasyBuf::with_capacity(4096);
buf.get_mut().extend_from_slice(&[0; 1024][..]);
b.iter(|| {
for _ in 0..1024 {
test::black_box(buf.as_slice());
}
})
}
#[bench]
fn deref_mid(b: &mut Bencher) {
let mut buf = EasyBuf::with_capacity(4096);
buf.get_mut().extend_from_slice(&[0; 1024][..]);
let _a = buf.drain_to(512);
b.iter(|| {
for _ in 0..1024 {
test::black_box(buf.as_slice());
}
})
}
#[bench]
fn alloc_write_drain_to_mid(b: &mut Bencher) {
b.iter(|| {
let mut buf = EasyBuf::with_capacity(128);
buf.get_mut().extend_from_slice(&[0u8; 64]);
test::black_box(buf.drain_to(64));
})
}
#[bench]
fn drain_write_drain(b: &mut Bencher) {
let data = [0u8; 128];
b.iter(|| {
let mut buf = EasyBuf::with_capacity(1024);
let mut parts = Vec::with_capacity(8);
for _ in 0..8 {
buf.get_mut().extend_from_slice(&data[..]);
parts.push(buf.drain_to(128));
}
test::black_box(parts);
})
}
}
mod bench_bytes {
use test::{self, Bencher};
use bytes::{BytesMut, BufMut};
#[bench]
fn alloc_small(b: &mut Bencher) {
b.iter(|| {
for _ in 0..1024 {
test::black_box(BytesMut::with_capacity(12));
}
})
}
#[bench]
fn alloc_mid(b: &mut Bencher) {
b.iter(|| {
test::black_box(BytesMut::with_capacity(128));
})
}
#[bench]
fn alloc_big(b: &mut Bencher) {
b.iter(|| {
test::black_box(BytesMut::with_capacity(4096));
})
}
#[bench]
fn deref_unique(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(4096);
buf.put(&[0u8; 1024][..]);
b.iter(|| {
for _ in 0..1024 {
test::black_box(&buf[..]);
}
})
}
#[bench]
fn deref_unique_unroll(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(4096);
buf.put(&[0u8; 1024][..]);
b.iter(|| {
for _ in 0..128 {
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
}
})
}
#[bench]
fn deref_shared(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(4096);
buf.put(&[0u8; 1024][..]);
let _b2 = buf.split_off(1024);
b.iter(|| {
for _ in 0..1024 {
test::black_box(&buf[..]);
}
})
}
#[bench]
fn deref_inline(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(8);
buf.put(&[0u8; 8][..]);
b.iter(|| {
for _ in 0..1024 {
test::black_box(&buf[..]);
}
})
}
#[bench]
fn deref_two(b: &mut Bencher) {
let mut buf1 = BytesMut::with_capacity(8);
buf1.put(&[0u8; 8][..]);
let mut buf2 = BytesMut::with_capacity(4096);
buf2.put(&[0u8; 1024][..]);
b.iter(|| {
for _ in 0..512 {
test::black_box(&buf1[..]);
test::black_box(&buf2[..]);
}
})
}
#[bench]
fn alloc_write_drain_to_mid(b: &mut Bencher) {
b.iter(|| {
let mut buf = BytesMut::with_capacity(128);
buf.put_slice(&[0u8; 64]);
test::black_box(buf.drain_to(64));
})
}
#[bench]
fn drain_write_drain(b: &mut Bencher) {
let data = [0u8; 128];
b.iter(|| {
let mut buf = BytesMut::with_capacity(1024);
let mut parts = Vec::with_capacity(8);
for _ in 0..8 {
buf.put(&data[..]);
parts.push(buf.drain_to(128));
}
test::black_box(parts);
})
}
}
+2 -2
View File
@@ -3,13 +3,13 @@
set -ex
main() {
cross build --target $TARGET
cross build --target $TARGET $EXTRA_ARGS
if [ ! -z $DISABLE_TESTS ]; then
return
fi
cross test --target $TARGET
cross test --target $TARGET $EXTRA_ARGS
}
# we don't run the "test phase" when doing deploys
+2
View File
@@ -112,3 +112,5 @@ impl<T: Buf> Iterator for Iter<T> {
(rem, Some(rem))
}
}
impl<T: Buf> ExactSizeIterator for Iter<T> { }
+188 -7
View File
@@ -197,14 +197,14 @@ pub struct BytesMut {
// itself for storing the buffer, reserving 1 byte for meta data. This means
// that, on 64 bit systems, 31 byte buffers require no allocation at all.
//
// The byte used for metadata stores a 1 bit flag used to indicate that the
// buffer is stored inline as well as 7 bits for tracking the buffer length (the
// The byte used for metadata stores a 2 bits flag used to indicate that the
// buffer is stored inline as well as 6 bits for tracking the buffer length (the
// return value of `Bytes::len`).
//
// ## Static buffers
//
// `Bytes` can also represent a static buffer, which is created with
// `Bytes::from_static`. No copying or allocations are required for trackign
// `Bytes::from_static`. No copying or allocations are required for tracking
// static buffers. The pointer to the `&'static [u8]`, the length, and a flag
// tracking that the `Bytes` instance represents a static buffer is stored in
// the `Bytes` struct.
@@ -464,6 +464,11 @@ impl Bytes {
/// Requires that `begin <= end` and `end <= self.len()`, otherwise slicing
/// will panic.
pub fn slice(&self, begin: usize, end: usize) -> Bytes {
if begin == end {
assert!(begin <= self.len());
return Bytes::new();
}
let mut ret = self.clone();
unsafe {
@@ -613,6 +618,45 @@ impl Bytes {
self.split_to(at)
}
/// Shortens the buffer, keeping the first `len` bytes and dropping the
/// rest.
///
/// If `len` is greater than the buffer's current length, this has no
/// effect.
///
/// The [`split_off`] method can emulate `truncate`, but this causes the
/// excess bytes to be returned instead of dropped.
///
/// # Examples
///
/// ```
/// use bytes::Bytes;
///
/// let mut buf = Bytes::from(&b"hello world"[..]);
/// buf.truncate(5);
/// assert_eq!(buf, b"hello"[..]);
/// ```
///
/// [`split_off`]: #method.split_off
pub fn truncate(&mut self, len: usize) {
self.inner.truncate(len);
}
/// Clears the buffer, removing all data.
///
/// # Examples
///
/// ```
/// use bytes::Bytes;
///
/// let mut buf = Bytes::from(&b"hello world"[..]);
/// buf.clear();
/// assert!(buf.is_empty());
/// ```
pub fn clear(&mut self) {
self.truncate(0);
}
/// Attempt to convert into a `BytesMut` handle.
///
/// This will only succeed if there are no other outstanding references to
@@ -648,6 +692,48 @@ impl Bytes {
Err(self)
}
}
/// Append given bytes to this object.
///
/// If this `Bytes` object has not enough capacity, it is resized first.
/// It `Bytes` is shared (`refcount > 1`), it is copied first.
///
/// This operation can be less effective than similar operation on `BytesMut`,
/// especially on small additions.
///
/// # Examples
///
/// ```
/// use bytes::Bytes;
///
/// let mut buf = Bytes::from("aabb");
/// buf.extend_from_slice(b"ccdd");
/// buf.extend_from_slice(b"eeff");
///
/// assert_eq!(b"aabbccddeeff", &buf[..]);
/// ```
pub fn extend_from_slice(&mut self, extend: &[u8]) {
if extend.is_empty() {
return;
}
let new_cap = self.len().checked_add(extend.len()).expect("capacity overflow");
let result = match mem::replace(self, Bytes::new()).try_mut() {
Ok(mut bytes_mut) => {
bytes_mut.extend_from_slice(extend);
bytes_mut
},
Err(bytes) => {
let mut bytes_mut = BytesMut::with_capacity(new_cap);
bytes_mut.put_slice(&bytes);
bytes_mut.put_slice(extend);
bytes_mut
}
};
mem::replace(self, result.freeze());
}
}
impl IntoBuf for Bytes {
@@ -742,6 +828,13 @@ impl Ord for Bytes {
impl Eq for Bytes {
}
impl Default for Bytes {
#[inline]
fn default() -> Bytes {
Bytes::new()
}
}
impl fmt::Debug for Bytes {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&debug::BsDebug(&self.inner.as_ref()), fmt)
@@ -779,6 +872,38 @@ impl<'a> IntoIterator for &'a Bytes {
}
}
impl Extend<u8> for Bytes {
fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item = u8> {
let iter = iter.into_iter();
let (lower, upper) = iter.size_hint();
// Avoid possible conversion into mut if there's nothing to add
if let Some(0) = upper {
return;
}
let mut bytes_mut = match mem::replace(self, Bytes::new()).try_mut() {
Ok(bytes_mut) => bytes_mut,
Err(bytes) => {
let mut bytes_mut = BytesMut::with_capacity(bytes.len() + lower);
bytes_mut.put_slice(&bytes);
bytes_mut
}
};
bytes_mut.extend(iter);
mem::replace(self, bytes_mut.freeze());
}
}
impl<'a> Extend<&'a u8> for Bytes {
fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item = &'a u8> {
self.extend(iter.into_iter().map(|b| *b))
}
}
/*
*
* ===== BytesMut =====
@@ -818,6 +943,30 @@ impl BytesMut {
}
}
/// Create a new `BytesMut` with default capacity.
///
/// Resulting object has length 0 and unspecified capacity.
/// This function does not allocate.
///
/// # Examples
///
/// ```
/// use bytes::{BytesMut, BufMut};
///
/// let mut bytes = BytesMut::new();
///
/// assert_eq!(0, bytes.len());
///
/// bytes.reserve(2);
/// bytes.put_slice(b"xy");
///
/// assert_eq!(&b"xy"[..], &bytes[..]);
/// ```
#[inline]
pub fn new() -> BytesMut {
BytesMut::with_capacity(0)
}
/// Returns the number of bytes contained in this `BytesMut`.
///
/// # Examples
@@ -1023,9 +1172,7 @@ impl BytesMut {
///
/// [`split_off`]: #method.split_off
pub fn truncate(&mut self, len: usize) {
if len <= self.len() {
unsafe { self.set_len(len); }
}
self.inner.truncate(len);
}
/// Clears the buffer, removing all data.
@@ -1129,6 +1276,27 @@ impl BytesMut {
pub fn reserve(&mut self, additional: usize) {
self.inner.reserve(additional)
}
/// Append given bytes to this object.
///
/// If this `BytesMut` object has not enough capacity, it is resized first.
/// So unlike `put_slice` operation, `extend_from_slice` does not panic.
///
/// # Examples
///
/// ```
/// use bytes::BytesMut;
///
/// let mut buf = BytesMut::with_capacity(0);
/// buf.extend_from_slice(b"aaabbb");
/// buf.extend_from_slice(b"cccddd");
///
/// assert_eq!(b"aaabbbcccddd", &buf[..]);
/// ```
pub fn extend_from_slice(&mut self, extend: &[u8]) {
self.reserve(extend.len());
self.put_slice(extend);
}
}
impl BufMut for BytesMut {
@@ -1292,6 +1460,13 @@ impl Ord for BytesMut {
impl Eq for BytesMut {
}
impl Default for BytesMut {
#[inline]
fn default() -> BytesMut {
BytesMut::new()
}
}
impl fmt::Debug for BytesMut {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&debug::BsDebug(&self.inner.as_ref()), fmt)
@@ -1571,6 +1746,12 @@ impl Inner {
return other
}
fn truncate(&mut self, len: usize) {
if len <= self.len() {
unsafe { self.set_len(len); }
}
}
unsafe fn set_start(&mut self, start: usize) {
// This function should never be called when the buffer is still backed
// by a `Vec<u8>`
@@ -1886,7 +2067,7 @@ impl Inner {
}
// Create a new vector to store the data
let mut v = Vec::with_capacity(new_cap.next_power_of_two());
let mut v = Vec::with_capacity(new_cap);
// Copy the bytes
v.extend_from_slice(self.as_ref());
+6 -1
View File
@@ -62,7 +62,7 @@
//! ## 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
//! functionality with `std::io::Read` 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`
@@ -93,3 +93,8 @@ mod debug;
pub use bytes::{Bytes, BytesMut};
pub use byteorder::{ByteOrder, BigEndian, LittleEndian};
// Optional Serde support
#[cfg(feature = "serde")]
#[doc(hidden)]
pub mod serde;
+82
View File
@@ -0,0 +1,82 @@
extern crate serde;
use std::{cmp, fmt};
use self::serde::{Serialize, Serializer, Deserialize, Deserializer, de};
use super::{Bytes, BytesMut};
macro_rules! serde_impl {
($ty:ident, $visitor_ty:ident) => (
impl Serialize for $ty {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
serializer.serialize_bytes(&self)
}
}
struct $visitor_ty;
impl<'de> de::Visitor<'de> for $visitor_ty {
type Value = $ty;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("byte array")
}
#[inline]
fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
where V: de::SeqAccess<'de>
{
let len = cmp::min(seq.size_hint().unwrap_or(0), 4096);
let mut values = Vec::with_capacity(len);
while let Some(value) = try!(seq.next_element()) {
values.push(value);
}
Ok(values.into())
}
#[inline]
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where E: de::Error
{
Ok($ty::from(v))
}
#[inline]
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where E: de::Error
{
Ok($ty::from(v))
}
#[inline]
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where E: de::Error
{
Ok($ty::from(v))
}
#[inline]
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where E: de::Error
{
Ok($ty::from(v))
}
}
impl<'de> Deserialize<'de> for $ty {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<$ty, D::Error>
where D: Deserializer<'de>
{
deserializer.deserialize_byte_buf($visitor_ty)
}
}
);
}
serde_impl!(Bytes, BytesVisitor);
serde_impl!(BytesMut, BytesMutVisitor);
+74 -2
View File
@@ -79,6 +79,15 @@ fn slice() {
let b = a.slice(3, 5);
assert_eq!(b, b"lo"[..]);
let b = a.slice(0, 0);
assert_eq!(b, b""[..]);
let b = a.slice(3, 3);
assert_eq!(b, b""[..]);
let b = a.slice(a.len(), a.len());
assert_eq!(b, b""[..]);
let b = a.slice_to(5);
assert_eq!(b, b"hello"[..]);
@@ -302,7 +311,7 @@ fn reserve_convert() {
let a = bytes.split_to(30);
bytes.reserve(128);
assert_eq!(bytes.capacity(), (bytes.len() + 128).next_power_of_two());
assert!(bytes.capacity() >= bytes.len() + 128);
drop(a);
}
@@ -347,6 +356,42 @@ fn reserve_max_original_capacity_value() {
assert_eq!(bytes.capacity(), 64 * 1024);
}
#[test]
fn reserve_in_arc_unique_does_not_overallocate() {
let mut bytes = BytesMut::with_capacity(1000);
bytes.take();
// now bytes is Arc and refcount == 1
assert_eq!(1000, bytes.capacity());
bytes.reserve(2001);
assert_eq!(2001, bytes.capacity());
}
#[test]
fn reserve_in_arc_unique_doubles() {
let mut bytes = BytesMut::with_capacity(1000);
bytes.take();
// now bytes is Arc and refcount == 1
assert_eq!(1000, bytes.capacity());
bytes.reserve(1001);
assert_eq!(2000, bytes.capacity());
}
#[test]
fn reserve_in_arc_nonunique_does_not_overallocate() {
let mut bytes = BytesMut::with_capacity(1000);
let _copy = bytes.take();
// now bytes is Arc and refcount == 2
assert_eq!(1000, bytes.capacity());
bytes.reserve(2001);
assert_eq!(2001, bytes.capacity());
}
#[test]
fn inline_storage() {
let mut bytes = BytesMut::with_capacity(inline_cap());
@@ -357,12 +402,39 @@ fn inline_storage() {
}
#[test]
fn extend() {
fn extend_mut() {
let mut bytes = BytesMut::with_capacity(0);
bytes.extend(LONG);
assert_eq!(*bytes, LONG[..]);
}
#[test]
fn extend_shr() {
let mut bytes = Bytes::new();
bytes.extend(LONG);
assert_eq!(*bytes, LONG[..]);
}
#[test]
fn extend_from_slice_mut() {
for &i in &[3, 34] {
let mut bytes = BytesMut::new();
bytes.extend_from_slice(&LONG[..i]);
bytes.extend_from_slice(&LONG[i..]);
assert_eq!(LONG[..], *bytes);
}
}
#[test]
fn extend_from_slice_shr() {
for &i in &[3, 34] {
let mut bytes = Bytes::new();
bytes.extend_from_slice(&LONG[..i]);
bytes.extend_from_slice(&LONG[i..]);
assert_eq!(LONG[..], *bytes);
}
}
#[test]
fn from_static() {
let mut a = Bytes::from_static(b"ab");
+22
View File
@@ -0,0 +1,22 @@
extern crate bytes;
use bytes::{Buf, IntoBuf, Bytes};
#[test]
fn iter_len() {
let buf = Bytes::from(&b"hello world"[..]).into_buf();
let iter = buf.iter();
assert_eq!(iter.size_hint(), (11, Some(11)));
assert_eq!(iter.len(), 11);
}
#[test]
fn empty_iter_len() {
let buf = Bytes::from(&b""[..]).into_buf();
let iter = buf.iter();
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.len(), 0);
}
+21
View File
@@ -0,0 +1,21 @@
#![cfg(feature = "serde")]
extern crate bytes;
extern crate serde_test;
use serde_test::{Token, assert_tokens};
#[test]
fn test_ser_de_empty() {
let b = bytes::Bytes::new();
assert_tokens(&b, &[Token::Bytes(b"")]);
let b = bytes::BytesMut::with_capacity(0);
assert_tokens(&b, &[Token::Bytes(b"")]);
}
#[test]
fn test_ser_de() {
let b = bytes::Bytes::from(&b"bytes"[..]);
assert_tokens(&b, &[Token::Bytes(b"bytes")]);
let b = bytes::BytesMut::from(&b"bytes"[..]);
assert_tokens(&b, &[Token::Bytes(b"bytes")]);
}