mirror of
https://github.com/tokio-rs/bytes.git
synced 2026-08-08 00:00:26 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3240fb9cd9 | ||
|
|
9ae51c9f0c | ||
|
|
2b0602e756 | ||
|
|
3f5890be70 | ||
|
|
70ee87ea29 | ||
|
|
edf1af958a | ||
|
|
7110d57b2f | ||
|
|
07db74b009 | ||
|
|
6af66c4f21 | ||
|
|
fa44c7e355 | ||
|
|
2c0cb1b6b8 | ||
|
|
b196559818 | ||
|
|
37f6cabd96 | ||
|
|
e5c7ef3b86 | ||
|
|
30bd7c1f21 | ||
|
|
923d927bd1 | ||
|
|
0b4185c716 | ||
|
|
e158160418 | ||
|
|
4645f6ec4b | ||
|
|
1a6901cdcd | ||
|
|
9aa24ebea1 | ||
|
|
627864187c | ||
|
|
b78bb3baaa | ||
|
|
6c6c55d8e1 | ||
|
|
613d4bd5d5 | ||
|
|
dc9c8e304e | ||
|
|
bed128b2c0 | ||
|
|
5a265cc8eb | ||
|
|
4fe4e9429a | ||
|
|
9a4018e757 | ||
|
|
99fba239db |
+6
-3
@@ -19,7 +19,7 @@ matrix:
|
||||
#
|
||||
# This job will also build and deploy the docs to gh-pages.
|
||||
- env: TARGET=x86_64-unknown-linux-gnu
|
||||
rust: 1.10.0
|
||||
rust: 1.15.0
|
||||
after_success:
|
||||
- |
|
||||
pip install 'travis-cargo<0.2' --user &&
|
||||
@@ -30,8 +30,11 @@ matrix:
|
||||
# Run tests on some extra platforms
|
||||
- env: TARGET=i686-unknown-linux-gnu
|
||||
- env: TARGET=armv7-unknown-linux-gnueabihf
|
||||
- env: TARGET=powerpc-unknown-linux-gnu
|
||||
- env: TARGET=powerpc64-unknown-linux-gnu
|
||||
- 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
|
||||
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
# 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)
|
||||
|
||||
* Misc performance tweaks
|
||||
* Improved `Debug` implementation for `Bytes`
|
||||
* Avoid some incorrect assert panics
|
||||
|
||||
# 0.4.1 (March 15, 2017)
|
||||
|
||||
|
||||
+3
-2
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
|
||||
name = "bytes"
|
||||
version = "0.4.1"
|
||||
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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -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
@@ -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
-1
@@ -9,7 +9,8 @@ use std::{cmp, io, ptr};
|
||||
/// A buffer stores bytes in memory such that read operations are 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.
|
||||
/// position. It can be thought of as an efficient `Iterator` for collections of
|
||||
/// bytes.
|
||||
///
|
||||
/// The simplest `Buf` is a `Cursor` wrapping a `[u8]`.
|
||||
///
|
||||
|
||||
+18
-14
@@ -59,7 +59,7 @@ pub trait BufMut {
|
||||
/// further into the underlying buffer.
|
||||
///
|
||||
/// This function is unsafe because there is no guarantee that the bytes
|
||||
/// being advanced to have been initialized.
|
||||
/// being advanced past have been initialized.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -90,9 +90,9 @@ pub trait BufMut {
|
||||
///
|
||||
/// # Implementer notes
|
||||
///
|
||||
/// It is recommended for implementations of `advance_mut` to panic if `cnt
|
||||
/// > self.remaining_mut()`. If the implementation does not panic, the call
|
||||
/// must behave as if `cnt == self.remaining_mut()`.
|
||||
/// It is recommended for implementations of `advance_mut` to panic if
|
||||
/// `cnt > self.remaining_mut()`. If the implementation does not panic,
|
||||
/// the call must behave as if `cnt == self.remaining_mut()`.
|
||||
///
|
||||
/// A call with `cnt == 0` should never panic and be a no-op.
|
||||
unsafe fn advance_mut(&mut self, cnt: usize);
|
||||
@@ -153,8 +153,10 @@ pub trait BufMut {
|
||||
///
|
||||
/// # Implementer notes
|
||||
///
|
||||
/// This function should never panic. Once the end of the buffer is reached,
|
||||
/// i.e., `BufMut::remaining_mut` returns 0, calls to `bytes_mut` should
|
||||
/// This function should never panic. `bytes_mut` should return an empty
|
||||
/// slice **if and only if** `remaining_mut` returns 0. In other words,
|
||||
/// `bytes_mut` returning an empty slice implies that `remaining_mut` will
|
||||
/// return 0 and `remaining_mut` returning 0 implies that `bytes_mut` will
|
||||
/// return an empty slice.
|
||||
unsafe fn bytes_mut(&mut self) -> &mut [u8];
|
||||
|
||||
@@ -699,23 +701,25 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>> BufMut for io::Cursor<T> {
|
||||
}
|
||||
|
||||
impl BufMut for Vec<u8> {
|
||||
#[inline]
|
||||
fn remaining_mut(&self) -> usize {
|
||||
usize::MAX - self.len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn advance_mut(&mut self, cnt: usize) {
|
||||
let cap = self.capacity();
|
||||
let len = self.len().checked_add(cnt)
|
||||
.expect("overflow");
|
||||
|
||||
if len > cap {
|
||||
// Reserve additional
|
||||
self.reserve(cap - len);
|
||||
let len = self.len();
|
||||
let remaining = self.capacity() - len;
|
||||
if cnt > remaining {
|
||||
// Reserve additional capacity, and ensure that the total length
|
||||
// will not overflow usize.
|
||||
self.reserve(cnt);
|
||||
}
|
||||
|
||||
self.set_len(len);
|
||||
self.set_len(len + cnt);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn bytes_mut(&mut self) -> &mut [u8] {
|
||||
use std::slice;
|
||||
|
||||
|
||||
@@ -112,3 +112,5 @@ impl<T: Buf> Iterator for Iter<T> {
|
||||
(rem, Some(rem))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Buf> ExactSizeIterator for Iter<T> { }
|
||||
|
||||
+265
-15
@@ -1,5 +1,6 @@
|
||||
use {IntoBuf, Buf, BufMut};
|
||||
use buf::Iter;
|
||||
use debug;
|
||||
|
||||
use std::{cmp, fmt, mem, hash, ops, slice, ptr, usize};
|
||||
use std::borrow::Borrow;
|
||||
@@ -86,13 +87,13 @@ use std::sync::atomic::Ordering::{Relaxed, Acquire, Release, AcqRel};
|
||||
/// underlying memory slice and may not be mutated, `BytesMut` handles are
|
||||
/// guaranteed to be the only handle able to view that slice of memory. As such,
|
||||
/// `BytesMut` handles are able to mutate the underlying memory. Note that
|
||||
/// holding a unique view to a region of memory does not mean that there are not
|
||||
/// holding a unique view to a region of memory does not mean that there are no
|
||||
/// other `Bytes` and `BytesMut` handles with disjoint views of the underlying
|
||||
/// memory.
|
||||
///
|
||||
/// # Inline bytes.
|
||||
///
|
||||
/// As an opitmization, when the slice referenced by a `Bytes` or `BytesMut`
|
||||
/// As an optimization, when the slice referenced by a `Bytes` or `BytesMut`
|
||||
/// handle is small enough [1], `Bytes` will avoid the allocation by inlining
|
||||
/// the slice directly in the handle. In this case, a clone is no longer
|
||||
/// "shallow" and the data will be copied.
|
||||
@@ -107,10 +108,24 @@ pub struct Bytes {
|
||||
///
|
||||
/// `BytesMut` represents a unique view into a potentially shared memory region.
|
||||
/// Given the uniqueness guarantee, owners of `BytesMut` handles are able to
|
||||
/// mutate the memory.
|
||||
/// mutate the memory. It is similar to a `Vec<u8>` but with less copies and
|
||||
/// allocations.
|
||||
///
|
||||
/// For more detail, see [Bytes](struct.Bytes.html).
|
||||
///
|
||||
/// # Growth
|
||||
///
|
||||
/// One key difference from `Vec<u8>` is that most operations **do not
|
||||
/// implicitly grow the buffer**. This means that calling `my_bytes.put("hello
|
||||
/// world");` could panic if `my_bytes` does not have enough capacity. Before
|
||||
/// writing to the buffer, ensure that there is enough remaining capacity by
|
||||
/// calling `my_bytes.remaining_mut()`. In general, avoiding calls to `reserve`
|
||||
/// is preferable.
|
||||
///
|
||||
/// The only exception is `extend` which implicitly reserves required capacity.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{BytesMut, BufMut};
|
||||
///
|
||||
@@ -182,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.
|
||||
@@ -449,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 {
|
||||
@@ -534,6 +554,16 @@ impl Bytes {
|
||||
///
|
||||
/// Panics if `at > len`
|
||||
pub fn split_off(&mut self, at: usize) -> Bytes {
|
||||
assert!(at <= self.len());
|
||||
|
||||
if at == self.len() {
|
||||
return Bytes::new();
|
||||
}
|
||||
|
||||
if at == 0 {
|
||||
return mem::replace(self, Bytes::new());
|
||||
}
|
||||
|
||||
Bytes {
|
||||
inner: Inner2 {
|
||||
inner: self.inner.split_off(at),
|
||||
@@ -565,6 +595,16 @@ impl Bytes {
|
||||
///
|
||||
/// Panics if `at > len`
|
||||
pub fn split_to(&mut self, at: usize) -> Bytes {
|
||||
assert!(at <= self.len());
|
||||
|
||||
if at == self.len() {
|
||||
return mem::replace(self, Bytes::new());
|
||||
}
|
||||
|
||||
if at == 0 {
|
||||
return Bytes::new();
|
||||
}
|
||||
|
||||
Bytes {
|
||||
inner: Inner2 {
|
||||
inner: self.inner.split_to(at),
|
||||
@@ -578,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
|
||||
@@ -613,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 {
|
||||
@@ -650,6 +771,7 @@ impl AsRef<[u8]> for Bytes {
|
||||
impl ops::Deref for Bytes {
|
||||
type Target = [u8];
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &[u8] {
|
||||
self.inner.as_ref()
|
||||
}
|
||||
@@ -706,9 +828,16 @@ 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(&self.inner.as_ref(), fmt)
|
||||
fmt::Debug::fmt(&debug::BsDebug(&self.inner.as_ref()), fmt)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -743,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 =====
|
||||
@@ -782,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
|
||||
@@ -987,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.
|
||||
@@ -1075,7 +1258,7 @@ impl BytesMut {
|
||||
/// buf.put(&[0; 64][..]);
|
||||
///
|
||||
/// let ptr = buf.as_ptr();
|
||||
/// let other = buf.drain();
|
||||
/// let other = buf.take();
|
||||
///
|
||||
/// assert!(buf.is_empty());
|
||||
/// assert_eq!(buf.capacity(), 64);
|
||||
@@ -1093,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 {
|
||||
@@ -1128,6 +1332,16 @@ impl BufMut for BytesMut {
|
||||
self.advance_mut(len);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn put_u8(&mut self, n: u8) {
|
||||
self.inner.put_u8(n);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn put_i8(&mut self, n: i8) {
|
||||
self.put_u8(n as u8);
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoBuf for BytesMut {
|
||||
@@ -1155,12 +1369,14 @@ impl AsRef<[u8]> for BytesMut {
|
||||
impl ops::Deref for BytesMut {
|
||||
type Target = [u8];
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &[u8] {
|
||||
self.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::DerefMut for BytesMut {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
self.inner.as_mut()
|
||||
}
|
||||
@@ -1244,9 +1460,16 @@ 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(self.inner.as_ref(), fmt)
|
||||
fmt::Debug::fmt(&debug::BsDebug(&self.inner.as_ref()), fmt)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1425,6 +1648,25 @@ impl Inner {
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert a byte into the next slot and advance the len by 1.
|
||||
#[inline]
|
||||
fn put_u8(&mut self, n: u8) {
|
||||
if self.is_inline() {
|
||||
let len = self.inline_len();
|
||||
assert!(len < INLINE_CAP);
|
||||
unsafe {
|
||||
*self.inline_ptr().offset(len as isize) = n;
|
||||
}
|
||||
self.set_inline_len(len + 1);
|
||||
} else {
|
||||
assert!(self.len < self.cap);
|
||||
unsafe {
|
||||
*self.ptr.offset(self.len as isize) = n;
|
||||
}
|
||||
self.len += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn len(&self) -> usize {
|
||||
if self.is_inline() {
|
||||
@@ -1504,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>`
|
||||
@@ -1819,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());
|
||||
@@ -1852,8 +2100,8 @@ impl Inner {
|
||||
#[inline]
|
||||
fn is_shared(&mut self) -> bool {
|
||||
match self.kind() {
|
||||
KIND_INLINE | KIND_ARC => true,
|
||||
_ => false,
|
||||
KIND_VEC => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1984,12 +2232,14 @@ unsafe impl Sync for Inner {}
|
||||
impl ops::Deref for Inner2 {
|
||||
type Target = Inner;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Inner {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::DerefMut for Inner2 {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut Inner {
|
||||
&mut self.inner
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
use std::fmt;
|
||||
|
||||
/// Alternative implementation of `fmt::Debug` for byte slice.
|
||||
///
|
||||
/// Standard `Debug` implementation for `[u8]` is comma separated
|
||||
/// list of numbers. Since large amount of byte strings are in fact
|
||||
/// ASCII strings or contain a lot of ASCII strings (e. g. HTTP),
|
||||
/// it is convenient to print strings as ASCII when possible.
|
||||
///
|
||||
/// This struct wraps `&[u8]` just to override `fmt::Debug`.
|
||||
///
|
||||
/// `BsDebug` is not a part of public API of bytes crate.
|
||||
pub struct BsDebug<'a>(pub &'a [u8]);
|
||||
|
||||
impl<'a> fmt::Debug for BsDebug<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
try!(write!(fmt, "b\""));
|
||||
for &c in self.0 {
|
||||
// https://doc.rust-lang.org/reference.html#byte-escapes
|
||||
if c == b'\n' {
|
||||
try!(write!(fmt, "\\n"));
|
||||
} else if c == b'\r' {
|
||||
try!(write!(fmt, "\\r"));
|
||||
} else if c == b'\t' {
|
||||
try!(write!(fmt, "\\t"));
|
||||
} else if c == b'\\' || c == b'"' {
|
||||
try!(write!(fmt, "\\{}", c as char));
|
||||
} else if c == b'\0' {
|
||||
try!(write!(fmt, "\\0"));
|
||||
// ASCII printable except space
|
||||
} else if c > 0x20 && c < 0x7f {
|
||||
try!(write!(fmt, "{}", c as char));
|
||||
} else {
|
||||
try!(write!(fmt, "\\x{:02x}", c));
|
||||
}
|
||||
}
|
||||
try!(write!(fmt, "\""));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
+9
-3
@@ -29,12 +29,12 @@
|
||||
//! buf.put(&b"hello world"[..]);
|
||||
//! buf.put_u16::<BigEndian>(1234);
|
||||
//!
|
||||
//! let a = buf.drain();
|
||||
//! let a = buf.take();
|
||||
//! assert_eq!(a, b"hello world\x04\xD2"[..]);
|
||||
//!
|
||||
//! buf.put(&b"goodbye world"[..]);
|
||||
//!
|
||||
//! let b = buf.drain();
|
||||
//! let b = buf.take();
|
||||
//! assert_eq!(b, b"goodbye world"[..]);
|
||||
//!
|
||||
//! assert_eq!(buf.capacity(), 998);
|
||||
@@ -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`
|
||||
@@ -89,6 +89,12 @@ pub use buf::{
|
||||
};
|
||||
|
||||
mod bytes;
|
||||
mod debug;
|
||||
pub use bytes::{Bytes, BytesMut};
|
||||
|
||||
pub use byteorder::{ByteOrder, BigEndian, LittleEndian};
|
||||
|
||||
// Optional Serde support
|
||||
#[cfg(feature = "serde")]
|
||||
#[doc(hidden)]
|
||||
pub mod serde;
|
||||
|
||||
@@ -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);
|
||||
@@ -49,6 +49,17 @@ fn test_put_u16() {
|
||||
assert_eq!(b"\x54\x21", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vec_advance_mut() {
|
||||
// Regression test for carllerche/bytes#108.
|
||||
let mut buf = Vec::with_capacity(8);
|
||||
unsafe {
|
||||
buf.advance_mut(12);
|
||||
assert_eq!(buf.len(), 12);
|
||||
assert!(buf.capacity() >= 12, "capacity: {}", buf.capacity());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clone() {
|
||||
let mut buf = BytesMut::with_capacity(100);
|
||||
|
||||
+156
-5
@@ -43,7 +43,7 @@ fn from_slice() {
|
||||
#[test]
|
||||
fn fmt() {
|
||||
let a = format!("{:?}", Bytes::from(&b"abcdefg"[..]));
|
||||
let b = format!("{:?}", b"abcdefg");
|
||||
let b = "b\"abcdefg\"";
|
||||
|
||||
assert_eq!(a, b);
|
||||
|
||||
@@ -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"[..]);
|
||||
|
||||
@@ -134,6 +143,50 @@ fn split_off_uninitialized() {
|
||||
assert_eq!(other.capacity(), 896);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_off_to_loop() {
|
||||
let s = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
for i in 0..(s.len() + 1) {
|
||||
{
|
||||
let mut bytes = Bytes::from(&s[..]);
|
||||
let off = bytes.split_off(i);
|
||||
assert_eq!(i, bytes.len());
|
||||
let mut sum = Vec::new();
|
||||
sum.extend(&bytes);
|
||||
sum.extend(&off);
|
||||
assert_eq!(&s[..], &sum[..]);
|
||||
}
|
||||
{
|
||||
let mut bytes = BytesMut::from(&s[..]);
|
||||
let off = bytes.split_off(i);
|
||||
assert_eq!(i, bytes.len());
|
||||
let mut sum = Vec::new();
|
||||
sum.extend(&bytes);
|
||||
sum.extend(&off);
|
||||
assert_eq!(&s[..], &sum[..]);
|
||||
}
|
||||
{
|
||||
let mut bytes = Bytes::from(&s[..]);
|
||||
let off = bytes.split_to(i);
|
||||
assert_eq!(i, off.len());
|
||||
let mut sum = Vec::new();
|
||||
sum.extend(&off);
|
||||
sum.extend(&bytes);
|
||||
assert_eq!(&s[..], &sum[..]);
|
||||
}
|
||||
{
|
||||
let mut bytes = BytesMut::from(&s[..]);
|
||||
let off = bytes.split_to(i);
|
||||
assert_eq!(i, off.len());
|
||||
let mut sum = Vec::new();
|
||||
sum.extend(&off);
|
||||
sum.extend(&bytes);
|
||||
assert_eq!(&s[..], &sum[..]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_to_1() {
|
||||
// Inline
|
||||
@@ -194,6 +247,28 @@ fn split_to_uninitialized() {
|
||||
assert_eq!(other.capacity(), 128);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_off_to_at_gt_len() {
|
||||
fn make_bytes() -> Bytes {
|
||||
let mut bytes = BytesMut::with_capacity(100);
|
||||
bytes.put_slice(&[10, 20, 30, 40]);
|
||||
bytes.freeze()
|
||||
}
|
||||
|
||||
use std::panic;
|
||||
|
||||
make_bytes().split_to(4);
|
||||
make_bytes().split_off(4);
|
||||
|
||||
assert!(panic::catch_unwind(move || {
|
||||
make_bytes().split_to(5);
|
||||
}).is_err());
|
||||
|
||||
assert!(panic::catch_unwind(move || {
|
||||
make_bytes().split_off(5);
|
||||
}).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fns_defined_for_bytes_mut() {
|
||||
let mut bytes = BytesMut::from(&b"hello world"[..]);
|
||||
@@ -236,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);
|
||||
}
|
||||
@@ -281,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());
|
||||
@@ -291,13 +402,52 @@ 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");
|
||||
let b = a.split_off(1);
|
||||
|
||||
assert_eq!(a, b"a"[..]);
|
||||
assert_eq!(b, b"b"[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Only run these tests on little endian systems. CI uses qemu for testing
|
||||
// little endian... and qemu doesn't really support threading all that well.
|
||||
#[cfg(target_endian = "little")]
|
||||
fn stress() {
|
||||
// Tests promoting a buffer from a vec -> shared in a concurrent situation
|
||||
use std::sync::{Arc, Barrier};
|
||||
@@ -308,7 +458,7 @@ fn stress() {
|
||||
|
||||
for i in 0..ITERS {
|
||||
let data = [i as u8; 256];
|
||||
let buf = Arc::new(BytesMut::from(&data[..]));
|
||||
let buf = Arc::new(Bytes::from(&data[..]));
|
||||
|
||||
let barrier = Arc::new(Barrier::new(THREADS));
|
||||
let mut joins = Vec::with_capacity(THREADS);
|
||||
@@ -319,7 +469,8 @@ fn stress() {
|
||||
|
||||
joins.push(thread::spawn(move || {
|
||||
c.wait();
|
||||
let _buf = buf.clone();
|
||||
let buf: Bytes = (*buf).clone();
|
||||
drop(buf);
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
+33
-24
@@ -53,41 +53,50 @@ fn vectored_read() {
|
||||
let b = Cursor::new(Bytes::from(&b"world"[..]));
|
||||
|
||||
let mut buf = a.chain(b);
|
||||
let mut iovecs: [&IoVec; 4] = Default::default();
|
||||
|
||||
assert_eq!(2, buf.bytes_vec(&mut iovecs));
|
||||
assert_eq!(iovecs[0][..], b"hello"[..]);
|
||||
assert_eq!(iovecs[1][..], b"world"[..]);
|
||||
assert!(iovecs[2].is_empty());
|
||||
assert!(iovecs[3].is_empty());
|
||||
{
|
||||
let mut iovecs: [&IoVec; 4] = Default::default();
|
||||
|
||||
assert_eq!(2, buf.bytes_vec(&mut iovecs));
|
||||
assert_eq!(iovecs[0][..], b"hello"[..]);
|
||||
assert_eq!(iovecs[1][..], b"world"[..]);
|
||||
assert!(iovecs[2].is_empty());
|
||||
assert!(iovecs[3].is_empty());
|
||||
}
|
||||
|
||||
buf.advance(2);
|
||||
|
||||
iovecs = Default::default();
|
||||
{
|
||||
let mut iovecs: [&IoVec; 4] = Default::default();
|
||||
|
||||
assert_eq!(2, buf.bytes_vec(&mut iovecs));
|
||||
assert_eq!(iovecs[0][..], b"llo"[..]);
|
||||
assert_eq!(iovecs[1][..], b"world"[..]);
|
||||
assert!(iovecs[2].is_empty());
|
||||
assert!(iovecs[3].is_empty());
|
||||
assert_eq!(2, buf.bytes_vec(&mut iovecs));
|
||||
assert_eq!(iovecs[0][..], b"llo"[..]);
|
||||
assert_eq!(iovecs[1][..], b"world"[..]);
|
||||
assert!(iovecs[2].is_empty());
|
||||
assert!(iovecs[3].is_empty());
|
||||
}
|
||||
|
||||
buf.advance(3);
|
||||
|
||||
iovecs = Default::default();
|
||||
{
|
||||
let mut iovecs: [&IoVec; 4] = Default::default();
|
||||
|
||||
assert_eq!(1, buf.bytes_vec(&mut iovecs));
|
||||
assert_eq!(iovecs[0][..], b"world"[..]);
|
||||
assert!(iovecs[1].is_empty());
|
||||
assert!(iovecs[2].is_empty());
|
||||
assert!(iovecs[3].is_empty());
|
||||
assert_eq!(1, buf.bytes_vec(&mut iovecs));
|
||||
assert_eq!(iovecs[0][..], b"world"[..]);
|
||||
assert!(iovecs[1].is_empty());
|
||||
assert!(iovecs[2].is_empty());
|
||||
assert!(iovecs[3].is_empty());
|
||||
}
|
||||
|
||||
buf.advance(3);
|
||||
|
||||
iovecs = Default::default();
|
||||
{
|
||||
let mut iovecs: [&IoVec; 4] = Default::default();
|
||||
|
||||
assert_eq!(1, buf.bytes_vec(&mut iovecs));
|
||||
assert_eq!(iovecs[0][..], b"ld"[..]);
|
||||
assert!(iovecs[1].is_empty());
|
||||
assert!(iovecs[2].is_empty());
|
||||
assert!(iovecs[3].is_empty());
|
||||
assert_eq!(1, buf.bytes_vec(&mut iovecs));
|
||||
assert_eq!(iovecs[0][..], b"ld"[..]);
|
||||
assert!(iovecs[1].is_empty());
|
||||
assert!(iovecs[2].is_empty());
|
||||
assert!(iovecs[3].is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
extern crate bytes;
|
||||
|
||||
use bytes::Bytes;
|
||||
|
||||
#[test]
|
||||
fn fmt() {
|
||||
let vec: Vec<_> = (0..0x100).map(|b| b as u8).collect();
|
||||
|
||||
let expected = "b\"\
|
||||
\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\
|
||||
\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\
|
||||
\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\
|
||||
\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\
|
||||
\\x20!\\\"#$%&'()*+,-./0123456789:;<=>?\
|
||||
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_\
|
||||
`abcdefghijklmnopqrstuvwxyz{|}~\\x7f\
|
||||
\\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87\
|
||||
\\x88\\x89\\x8a\\x8b\\x8c\\x8d\\x8e\\x8f\
|
||||
\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\
|
||||
\\x98\\x99\\x9a\\x9b\\x9c\\x9d\\x9e\\x9f\
|
||||
\\xa0\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6\\xa7\
|
||||
\\xa8\\xa9\\xaa\\xab\\xac\\xad\\xae\\xaf\
|
||||
\\xb0\\xb1\\xb2\\xb3\\xb4\\xb5\\xb6\\xb7\
|
||||
\\xb8\\xb9\\xba\\xbb\\xbc\\xbd\\xbe\\xbf\
|
||||
\\xc0\\xc1\\xc2\\xc3\\xc4\\xc5\\xc6\\xc7\
|
||||
\\xc8\\xc9\\xca\\xcb\\xcc\\xcd\\xce\\xcf\
|
||||
\\xd0\\xd1\\xd2\\xd3\\xd4\\xd5\\xd6\\xd7\
|
||||
\\xd8\\xd9\\xda\\xdb\\xdc\\xdd\\xde\\xdf\
|
||||
\\xe0\\xe1\\xe2\\xe3\\xe4\\xe5\\xe6\\xe7\
|
||||
\\xe8\\xe9\\xea\\xeb\\xec\\xed\\xee\\xef\
|
||||
\\xf0\\xf1\\xf2\\xf3\\xf4\\xf5\\xf6\\xf7\
|
||||
\\xf8\\xf9\\xfa\\xfb\\xfc\\xfd\\xfe\\xff\"";
|
||||
|
||||
assert_eq!(expected, format!("{:?}", Bytes::from(vec)));
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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")]);
|
||||
}
|
||||
Reference in New Issue
Block a user