mirror of
https://github.com/openharmony/third_party_rust_bytes.git
synced 2026-07-18 08:15:59 -04:00
Refactor Bytes to use an internal vtable (#298)
Bytes is a useful tool for managing multiple slices into the same region of memory, and the other things it used to have been removed to reduce complexity. The exact strategy for managing the multiple references is no longer hard-coded, but instead backing by a customizable vtable. - Removed ability to mutate the underlying memory from the `Bytes` type. - Removed the "inline" (SBO) mechanism in `Bytes`. The reduces a large amount of complexity, and improves performance when accessing the slice of bytes, since a branch is no longer needed to check if the data is inline. - Removed `Bytes` knowledge of `BytesMut` (`BytesMut` may grow that knowledge back at a future point.)
This commit is contained in:
@@ -28,4 +28,5 @@ serde = { version = "1.0", optional = true }
|
||||
either = { version = "1.5", default-features = false, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
loom = "0.2.10"
|
||||
serde_test = "1.0"
|
||||
|
||||
+20
-152
@@ -4,47 +4,11 @@
|
||||
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 split_off_and_drop(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
let v = vec![10; 200];
|
||||
let mut b = Bytes::from(v);
|
||||
test::black_box(b.split_off(100));
|
||||
test::black_box(b);
|
||||
}
|
||||
})
|
||||
}
|
||||
use bytes::Bytes;
|
||||
|
||||
#[bench]
|
||||
fn deref_unique(b: &mut Bencher) {
|
||||
let mut buf = BytesMut::with_capacity(4096);
|
||||
buf.put(&[0u8; 1024][..]);
|
||||
let buf = Bytes::from(vec![0; 1024]);
|
||||
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
@@ -53,30 +17,10 @@ fn deref_unique(b: &mut Bencher) {
|
||||
})
|
||||
}
|
||||
|
||||
#[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);
|
||||
let buf = Bytes::from(vec![0; 1024]);
|
||||
let _b2 = buf.clone();
|
||||
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
@@ -86,9 +30,8 @@ fn deref_shared(b: &mut Bencher) {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deref_inline(b: &mut Bencher) {
|
||||
let mut buf = BytesMut::with_capacity(8);
|
||||
buf.put(&[0u8; 8][..]);
|
||||
fn deref_static(b: &mut Bencher) {
|
||||
let buf = Bytes::from_static(b"hello world");
|
||||
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
@@ -97,33 +40,6 @@ fn deref_inline(b: &mut Bencher) {
|
||||
})
|
||||
}
|
||||
|
||||
#[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 clone_inline(b: &mut Bencher) {
|
||||
let bytes = Bytes::from_static(b"hello world");
|
||||
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
test::black_box(&bytes.clone());
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn clone_static(b: &mut Bencher) {
|
||||
let bytes = Bytes::from_static("hello world 1234567890 and have a good byte 0987654321".as_bytes());
|
||||
@@ -136,8 +52,8 @@ fn clone_static(b: &mut Bencher) {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn clone_arc(b: &mut Bencher) {
|
||||
let bytes = Bytes::from("hello world 1234567890 and have a good byte 0987654321".as_bytes());
|
||||
fn clone_shared(b: &mut Bencher) {
|
||||
let bytes = Bytes::from(b"hello world 1234567890 and have a good byte 0987654321".to_vec());
|
||||
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
@@ -147,42 +63,14 @@ fn clone_arc(b: &mut Bencher) {
|
||||
}
|
||||
|
||||
#[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];
|
||||
fn clone_arc_vec(b: &mut Bencher) {
|
||||
use std::sync::Arc;
|
||||
let bytes = Arc::new(b"hello world 1234567890 and have a good byte 0987654321".to_vec());
|
||||
|
||||
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));
|
||||
for _ in 0..1024 {
|
||||
test::black_box(&bytes.clone());
|
||||
}
|
||||
|
||||
test::black_box(parts);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn fmt_write(b: &mut Bencher) {
|
||||
use std::fmt::Write;
|
||||
let mut buf = BytesMut::with_capacity(128);
|
||||
let s = "foo bar baz quux lorem ipsum dolor et";
|
||||
|
||||
b.bytes = s.len() as u64;
|
||||
b.iter(|| {
|
||||
let _ = write!(buf, "{}", s);
|
||||
test::black_box(&buf);
|
||||
unsafe { buf.set_len(0); }
|
||||
})
|
||||
}
|
||||
|
||||
@@ -191,7 +79,7 @@ fn from_long_slice(b: &mut Bencher) {
|
||||
let data = [0u8; 128];
|
||||
b.bytes = data.len() as u64;
|
||||
b.iter(|| {
|
||||
let buf = BytesMut::from(&data[..]);
|
||||
let buf = Bytes::copy_from_slice(&data[..]);
|
||||
test::black_box(buf);
|
||||
})
|
||||
}
|
||||
@@ -217,34 +105,14 @@ fn slice_short_from_arc(b: &mut Bencher) {
|
||||
})
|
||||
}
|
||||
|
||||
// Keep in sync with bytes.rs
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const INLINE_CAP: usize = 4 * 8 - 1;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
const INLINE_CAP: usize = 4 * 4 - 1;
|
||||
|
||||
#[bench]
|
||||
fn slice_avg_le_inline_from_arc(b: &mut Bencher) {
|
||||
fn split_off_and_drop(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
// `clone` is to convert to ARC
|
||||
let b = Bytes::from(vec![17; 1024]).clone();
|
||||
for i in 0..1000 {
|
||||
// [1, INLINE_CAP]
|
||||
let len = 1 + i % (INLINE_CAP - 1);
|
||||
test::black_box(b.slice(i % 10..i % 10 + len));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn slice_large_le_inline_from_arc(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
// `clone` is to convert to ARC
|
||||
let b = Bytes::from(vec![17; 1024]).clone();
|
||||
for i in 0..1000 {
|
||||
// [INLINE_CAP - 10, INLINE_CAP]
|
||||
let len = INLINE_CAP - 9 + i % 10;
|
||||
test::black_box(b.slice(i % 10..i % 10 + len));
|
||||
for _ in 0..1024 {
|
||||
let v = vec![10; 200];
|
||||
let mut b = Bytes::from(v);
|
||||
test::black_box(b.split_off(100));
|
||||
test::black_box(b);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
#![feature(test)]
|
||||
#![deny(warnings, rust_2018_idioms)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use test::Bencher;
|
||||
use bytes::{BufMut, BytesMut};
|
||||
|
||||
#[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_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 clone_frozen(b: &mut Bencher) {
|
||||
let bytes = BytesMut::from(&b"hello world 1234567890 and have a good byte 0987654321"[..]).split().freeze();
|
||||
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
test::black_box(&bytes.clone());
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[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 fmt_write(b: &mut Bencher) {
|
||||
use std::fmt::Write;
|
||||
let mut buf = BytesMut::with_capacity(128);
|
||||
let s = "foo bar baz quux lorem ipsum dolor et";
|
||||
|
||||
b.bytes = s.len() as u64;
|
||||
b.iter(|| {
|
||||
let _ = write!(buf, "{}", s);
|
||||
test::black_box(&buf);
|
||||
unsafe { buf.set_len(0); }
|
||||
})
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
parameters:
|
||||
cmd: test
|
||||
cmd: build
|
||||
rust_version: stable
|
||||
|
||||
jobs:
|
||||
|
||||
+2
-2
@@ -18,9 +18,9 @@ jobs:
|
||||
|
||||
# Run address sanitizer
|
||||
RUSTFLAGS="-Z sanitizer=address" \
|
||||
cargo test --tests --target x86_64-unknown-linux-gnu
|
||||
cargo test --target x86_64-unknown-linux-gnu --test test_bytes --test test_buf --test test_buf_mut
|
||||
|
||||
# Run thread sanitizer
|
||||
RUSTFLAGS="-Z sanitizer=thread" \
|
||||
cargo test --tests --target x86_64-unknown-linux-gnu
|
||||
cargo test --target x86_64-unknown-linux-gnu --test test_bytes --test test_buf --test test_buf_mut
|
||||
displayName: TSAN / MSAN
|
||||
|
||||
@@ -19,10 +19,6 @@ race:test::run_tests_console::*closure
|
||||
# Probably more fences in std.
|
||||
race:__call_tls_dtors
|
||||
|
||||
# `is_inline_or_static` is explicitly called concurrently without synchronization.
|
||||
# The safety explanation can be found in a comment.
|
||||
race:Inner::is_inline_or_static
|
||||
|
||||
# This ignores a false positive caused by `thread::park()`/`thread::unpark()`.
|
||||
# See: https://github.com/rust-lang/rust/pull/54806#issuecomment-436193353
|
||||
race:pthread_cond_destroy
|
||||
|
||||
@@ -186,14 +186,6 @@ impl<T, U> Buf for Chain<T, U>
|
||||
n += self.b.bytes_vectored(&mut dst[n..]);
|
||||
n
|
||||
}
|
||||
|
||||
fn to_bytes(&mut self) -> crate::Bytes {
|
||||
let mut bytes: crate::BytesMut = self.a.to_bytes().try_mut()
|
||||
.unwrap_or_else(|bytes| bytes.into());
|
||||
|
||||
bytes.put(&mut self.b);
|
||||
bytes.freeze()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> BufMut for Chain<T, U>
|
||||
|
||||
@@ -20,22 +20,3 @@ impl Buf for VecDeque<u8> {
|
||||
self.drain(..cnt);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn hello_world() {
|
||||
let mut buffer: VecDeque<u8> = VecDeque::new();
|
||||
buffer.extend(b"hello world");
|
||||
assert_eq!(11, buffer.remaining());
|
||||
assert_eq!(b"hello world", buffer.bytes());
|
||||
buffer.advance(6);
|
||||
assert_eq!(b"world", buffer.bytes());
|
||||
buffer.extend(b" piece");
|
||||
let mut out = [0; 11];
|
||||
buffer.copy_to_slice(&mut out);
|
||||
assert_eq!(b"world piece", &out[..]);
|
||||
}
|
||||
}
|
||||
|
||||
+354
-2460
File diff suppressed because it is too large
Load Diff
+1429
File diff suppressed because it is too large
Load Diff
+26
-1
@@ -84,10 +84,13 @@ pub use crate::buf::{
|
||||
BufMut,
|
||||
};
|
||||
|
||||
mod bytes_mut;
|
||||
mod bytes;
|
||||
mod debug;
|
||||
mod hex;
|
||||
pub use crate::bytes::{Bytes, BytesMut};
|
||||
mod loom;
|
||||
pub use crate::bytes_mut::BytesMut;
|
||||
pub use crate::bytes::Bytes;
|
||||
|
||||
// Optional Serde support
|
||||
#[cfg(feature = "serde")]
|
||||
@@ -96,3 +99,25 @@ mod serde;
|
||||
// Optional `Either` support
|
||||
#[cfg(feature = "either")]
|
||||
mod either;
|
||||
|
||||
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
fn abort() -> ! {
|
||||
#[cfg(feature = "std")]
|
||||
{
|
||||
std::process::abort();
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
{
|
||||
struct Abort;
|
||||
impl Drop for Abort {
|
||||
fn drop(&mut self) {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
let _a = Abort;
|
||||
panic!("abort");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
pub(crate) mod sync {
|
||||
pub(crate) mod atomic {
|
||||
pub(crate) use core::sync::atomic::{fence, AtomicPtr, AtomicUsize, Ordering};
|
||||
}
|
||||
}
|
||||
+7
-7
@@ -5,7 +5,7 @@ use serde::{Serialize, Serializer, Deserialize, Deserializer, de};
|
||||
use super::{Bytes, BytesMut};
|
||||
|
||||
macro_rules! serde_impl {
|
||||
($ty:ident, $visitor_ty:ident, $from_slice:ident) => (
|
||||
($ty:ident, $visitor_ty:ident, $from_slice:ident, $from_vec:ident) => (
|
||||
impl Serialize for $ty {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@@ -29,13 +29,13 @@ macro_rules! serde_impl {
|
||||
where V: de::SeqAccess<'de>
|
||||
{
|
||||
let len = cmp::min(seq.size_hint().unwrap_or(0), 4096);
|
||||
let mut values = Vec::with_capacity(len);
|
||||
let mut values: Vec<u8> = Vec::with_capacity(len);
|
||||
|
||||
while let Some(value) = seq.next_element()? {
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
Ok(values.into())
|
||||
Ok($ty::$from_vec(values))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -49,7 +49,7 @@ macro_rules! serde_impl {
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||
where E: de::Error
|
||||
{
|
||||
Ok($ty::from(v))
|
||||
Ok($ty::$from_vec(v))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -63,7 +63,7 @@ macro_rules! serde_impl {
|
||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||
where E: de::Error
|
||||
{
|
||||
Ok($ty::from(v))
|
||||
Ok($ty::$from_vec(v.into_bytes()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,5 +78,5 @@ macro_rules! serde_impl {
|
||||
);
|
||||
}
|
||||
|
||||
serde_impl!(Bytes, BytesVisitor, copy_from_slice);
|
||||
serde_impl!(BytesMut, BytesMutVisitor, from);
|
||||
serde_impl!(Bytes, BytesVisitor, copy_from_slice, from);
|
||||
serde_impl!(BytesMut, BytesMutVisitor, from, from_vec);
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
// pretend to like `crate::`
|
||||
extern crate alloc;
|
||||
#[path = "../src/buf/mod.rs"]
|
||||
#[allow(warnings)]
|
||||
mod buf;
|
||||
#[path = "../src/debug.rs"]
|
||||
#[allow(warnings)]
|
||||
mod debug;
|
||||
#[path = "../src/bytes.rs"]
|
||||
#[allow(warnings)]
|
||||
mod bytes;
|
||||
#[path = "../src/bytes_mut.rs"]
|
||||
#[allow(warnings)]
|
||||
mod bytes_mut;
|
||||
use std::process::abort;
|
||||
|
||||
use self::buf::{Buf, BufMut};
|
||||
use self::bytes::Bytes;
|
||||
use self::bytes_mut::BytesMut;
|
||||
|
||||
use std::sync::Arc;
|
||||
use loom;
|
||||
use loom::thread;
|
||||
|
||||
#[test]
|
||||
fn bytes_cloning_vec() {
|
||||
loom::model(|| {
|
||||
let a = Bytes::from(b"abcdefgh".to_vec());
|
||||
let addr = a.as_ptr() as usize;
|
||||
|
||||
// test the Bytes::clone is Sync by putting it in an Arc
|
||||
let a1 = Arc::new(a);
|
||||
let a2 = a1.clone();
|
||||
|
||||
let t1 = thread::spawn(move || {
|
||||
let b: Bytes = (*a1).clone();
|
||||
assert_eq!(b.as_ptr() as usize, addr);
|
||||
});
|
||||
|
||||
let t2 = thread::spawn(move || {
|
||||
let b: Bytes = (*a2).clone();
|
||||
assert_eq!(b.as_ptr() as usize, addr);
|
||||
});
|
||||
|
||||
t1.join().unwrap();
|
||||
t2.join().unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_mut_cloning_frozen() {
|
||||
loom::model(|| {
|
||||
let a = BytesMut::from(&b"abcdefgh"[..]).split().freeze();
|
||||
let addr = a.as_ptr() as usize;
|
||||
|
||||
// test the Bytes::clone is Sync by putting it in an Arc
|
||||
let a1 = Arc::new(a);
|
||||
let a2 = a1.clone();
|
||||
|
||||
let t1 = thread::spawn(move || {
|
||||
let b: Bytes = (*a1).clone();
|
||||
assert_eq!(b.as_ptr() as usize, addr);
|
||||
});
|
||||
|
||||
let t2 = thread::spawn(move || {
|
||||
let b: Bytes = (*a2).clone();
|
||||
assert_eq!(b.as_ptr() as usize, addr);
|
||||
});
|
||||
|
||||
t1.join().unwrap();
|
||||
t2.join().unwrap();
|
||||
});
|
||||
}
|
||||
@@ -53,3 +53,19 @@ fn test_bufs_vec() {
|
||||
|
||||
assert_eq!(1, buf.bytes_vectored(&mut dst[..]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vec_deque() {
|
||||
use std::collections::VecDeque;
|
||||
|
||||
let mut buffer: VecDeque<u8> = VecDeque::new();
|
||||
buffer.extend(b"hello world");
|
||||
assert_eq!(11, buffer.remaining());
|
||||
assert_eq!(b"hello world", buffer.bytes());
|
||||
buffer.advance(6);
|
||||
assert_eq!(b"world", buffer.bytes());
|
||||
buffer.extend(b" piece");
|
||||
let mut out = [0; 11];
|
||||
buffer.copy_to_slice(&mut out);
|
||||
assert_eq!(b"world piece", &out[..]);
|
||||
}
|
||||
|
||||
@@ -70,11 +70,19 @@ fn test_clone() {
|
||||
|
||||
#[test]
|
||||
fn test_bufs_vec_mut() {
|
||||
let mut buf = BytesMut::from(&b"hello world"[..]);
|
||||
let b1: &mut [u8] = &mut [];
|
||||
let b2: &mut [u8] = &mut [];
|
||||
let mut dst = [IoSliceMut::new(b1), IoSliceMut::new(b2)];
|
||||
|
||||
// with no capacity
|
||||
let mut buf = BytesMut::new();
|
||||
assert_eq!(buf.capacity(), 0);
|
||||
unsafe {
|
||||
assert_eq!(0, buf.bytes_vectored_mut(&mut dst[..]));
|
||||
}
|
||||
|
||||
// with capacity
|
||||
let mut buf = BytesMut::with_capacity(64);
|
||||
unsafe {
|
||||
assert_eq!(1, buf.bytes_vectored_mut(&mut dst[..]));
|
||||
}
|
||||
|
||||
+80
-163
@@ -5,11 +5,6 @@ use bytes::{Bytes, BytesMut, Buf, BufMut};
|
||||
const LONG: &'static [u8] = b"mary had a little lamb, little lamb, little lamb";
|
||||
const SHORT: &'static [u8] = b"hello world";
|
||||
|
||||
fn inline_cap() -> usize {
|
||||
use std::mem;
|
||||
4 * mem::size_of::<usize>() - 1
|
||||
}
|
||||
|
||||
fn is_sync<T: Sync>() {}
|
||||
fn is_send<T: Send>() {}
|
||||
|
||||
@@ -21,6 +16,35 @@ fn test_bounds() {
|
||||
is_send::<BytesMut>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_layout() {
|
||||
use std::mem;
|
||||
|
||||
assert_eq!(
|
||||
mem::size_of::<Bytes>(),
|
||||
mem::size_of::<usize>() * 4,
|
||||
"Bytes size should be 4 words",
|
||||
);
|
||||
assert_eq!(
|
||||
mem::size_of::<BytesMut>(),
|
||||
mem::size_of::<usize>() * 4,
|
||||
"BytesMut should be 4 words",
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
mem::size_of::<Bytes>(),
|
||||
mem::size_of::<Option<Bytes>>(),
|
||||
"Bytes should be same size as Option<Bytes>",
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
mem::size_of::<BytesMut>(),
|
||||
mem::size_of::<Option<BytesMut>>(),
|
||||
"BytesMut should be same size as Option<BytesMut>",
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_slice() {
|
||||
let a = Bytes::from(&b"abcdefgh"[..]);
|
||||
@@ -121,14 +145,14 @@ fn slice() {
|
||||
#[should_panic]
|
||||
fn slice_oob_1() {
|
||||
let a = Bytes::from(&b"hello world"[..]);
|
||||
a.slice(5..(inline_cap() + 1));
|
||||
a.slice(5..44);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn slice_oob_2() {
|
||||
let a = Bytes::from(&b"hello world"[..]);
|
||||
a.slice((inline_cap() + 1)..(inline_cap() + 5));
|
||||
a.slice(44..49);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -150,7 +174,7 @@ fn split_off() {
|
||||
#[should_panic]
|
||||
fn split_off_oob() {
|
||||
let mut hello = Bytes::from(&b"helloworld"[..]);
|
||||
hello.split_off(inline_cap() + 1);
|
||||
hello.split_off(44);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -211,21 +235,21 @@ fn split_off_to_loop() {
|
||||
|
||||
#[test]
|
||||
fn split_to_1() {
|
||||
// Inline
|
||||
let mut a = Bytes::from(SHORT);
|
||||
// Static
|
||||
let mut a = Bytes::from_static(SHORT);
|
||||
let b = a.split_to(4);
|
||||
|
||||
assert_eq!(SHORT[4..], a);
|
||||
assert_eq!(SHORT[..4], b);
|
||||
|
||||
// Allocated
|
||||
let mut a = Bytes::from(LONG);
|
||||
let mut a = Bytes::copy_from_slice(LONG);
|
||||
let b = a.split_to(4);
|
||||
|
||||
assert_eq!(LONG[4..], a);
|
||||
assert_eq!(LONG[..4], b);
|
||||
|
||||
let mut a = Bytes::from(LONG);
|
||||
let mut a = Bytes::copy_from_slice(LONG);
|
||||
let b = a.split_to(30);
|
||||
|
||||
assert_eq!(LONG[30..], a);
|
||||
@@ -247,14 +271,14 @@ fn split_to_2() {
|
||||
#[should_panic]
|
||||
fn split_to_oob() {
|
||||
let mut hello = Bytes::from(&b"helloworld"[..]);
|
||||
hello.split_to(inline_cap() + 1);
|
||||
hello.split_to(33);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn split_to_oob_mut() {
|
||||
let mut hello = BytesMut::from(&b"helloworld"[..]);
|
||||
hello.split_to(inline_cap() + 1);
|
||||
hello.split_to(33);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -286,6 +310,24 @@ fn split_off_to_at_gt_len() {
|
||||
}).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn freeze_clone_shared() {
|
||||
let s = &b"abcdefgh"[..];
|
||||
let b = BytesMut::from(s).split().freeze();
|
||||
assert_eq!(b, s);
|
||||
let c = b.clone();
|
||||
assert_eq!(c, s);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn freeze_clone_unique() {
|
||||
let s = &b"abcdefgh"[..];
|
||||
let b = BytesMut::from(s).freeze();
|
||||
assert_eq!(b, s);
|
||||
let c = b.clone();
|
||||
assert_eq!(c, s);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fns_defined_for_bytes_mut() {
|
||||
let mut bytes = BytesMut::from(&b"hello world"[..]);
|
||||
@@ -300,24 +342,6 @@ fn fns_defined_for_bytes_mut() {
|
||||
|
||||
#[test]
|
||||
fn reserve_convert() {
|
||||
// Inline -> Vec
|
||||
let mut bytes = BytesMut::with_capacity(8);
|
||||
bytes.put("hello".as_bytes());
|
||||
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".as_bytes());
|
||||
|
||||
let a = bytes.split_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);
|
||||
@@ -373,19 +397,18 @@ fn reserve_max_original_capacity_value() {
|
||||
assert_eq!(bytes.capacity(), 64 * 1024);
|
||||
}
|
||||
|
||||
// Without either looking at the internals of the BytesMut or doing weird stuff
|
||||
// with the memory allocator, there's no good way to automatically verify from
|
||||
// within the program that this actually recycles memory. Instead, just exercise
|
||||
// the code path to ensure that the results are correct.
|
||||
#[test]
|
||||
fn reserve_vec_recycling() {
|
||||
let mut bytes = BytesMut::from(Vec::with_capacity(16));
|
||||
let mut bytes = BytesMut::with_capacity(16);
|
||||
assert_eq!(bytes.capacity(), 16);
|
||||
bytes.put("0123456789012345".as_bytes());
|
||||
let addr = bytes.as_ptr() as usize;
|
||||
bytes.put("0123456789012345");
|
||||
assert_eq!(bytes.as_ptr() as usize, addr);
|
||||
bytes.advance(10);
|
||||
assert_eq!(bytes.capacity(), 6);
|
||||
bytes.reserve(8);
|
||||
assert_eq!(bytes.capacity(), 16);
|
||||
assert_eq!(bytes.as_ptr() as usize, addr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -424,15 +447,6 @@ fn reserve_in_arc_nonunique_does_not_overallocate() {
|
||||
assert_eq!(2001, bytes.capacity());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inline_storage() {
|
||||
let mut bytes = BytesMut::with_capacity(inline_cap());
|
||||
let zero = [0u8; 64];
|
||||
|
||||
bytes.put(&zero[0..inline_cap()]);
|
||||
assert_eq!(*bytes, zero[0..inline_cap()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extend_mut() {
|
||||
let mut bytes = BytesMut::with_capacity(0);
|
||||
@@ -440,13 +454,6 @@ fn extend_mut() {
|
||||
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] {
|
||||
@@ -457,16 +464,6 @@ fn extend_from_slice_mut() {
|
||||
}
|
||||
}
|
||||
|
||||
#[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");
|
||||
@@ -476,13 +473,6 @@ fn from_static() {
|
||||
assert_eq!(b, b"b"[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn advance_inline() {
|
||||
let mut a = Bytes::from(&b"hello world"[..]);
|
||||
a.advance(6);
|
||||
assert_eq!(a, &b"world"[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn advance_static() {
|
||||
let mut a = Bytes::from_static(b"hello world");
|
||||
@@ -492,7 +482,20 @@ fn advance_static() {
|
||||
|
||||
#[test]
|
||||
fn advance_vec() {
|
||||
let mut a = BytesMut::from(b"hello world boooo yah world zomg wat wat".to_vec());
|
||||
let mut a = Bytes::from(b"hello world boooo yah world zomg wat wat".to_vec());
|
||||
a.advance(16);
|
||||
assert_eq!(a, b"o yah world zomg wat wat"[..]);
|
||||
|
||||
a.advance(4);
|
||||
assert_eq!(a, b"h world zomg wat wat"[..]);
|
||||
|
||||
a.advance(6);
|
||||
assert_eq!(a, b"d zomg wat wat"[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn advance_bytes_mut() {
|
||||
let mut a = BytesMut::from("hello world boooo yah world zomg wat wat");
|
||||
a.advance(16);
|
||||
assert_eq!(a, b"o yah world zomg wat wat"[..]);
|
||||
|
||||
@@ -510,7 +513,7 @@ fn advance_vec() {
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn advance_past_len() {
|
||||
let mut a = BytesMut::from(b"hello world".to_vec());
|
||||
let mut a = BytesMut::from("hello world");
|
||||
a.advance(20);
|
||||
}
|
||||
|
||||
@@ -563,10 +566,10 @@ fn partial_eq_bytesmut() {
|
||||
assert!(bytesmut != bytes2);
|
||||
}
|
||||
|
||||
/*
|
||||
#[test]
|
||||
fn bytes_unsplit_basic() {
|
||||
let mut buf = Bytes::with_capacity(64);
|
||||
buf.extend_from_slice(b"aaabbbcccddd");
|
||||
let buf = Bytes::from(&b"aaabbbcccddd"[..]);
|
||||
|
||||
let splitted = buf.split_off(6);
|
||||
assert_eq!(b"aaabbb", &buf[..]);
|
||||
@@ -578,8 +581,7 @@ fn bytes_unsplit_basic() {
|
||||
|
||||
#[test]
|
||||
fn bytes_unsplit_empty_other() {
|
||||
let mut buf = Bytes::with_capacity(64);
|
||||
buf.extend_from_slice(b"aaabbbcccddd");
|
||||
let buf = Bytes::from(&b"aaabbbcccddd"[..]);
|
||||
|
||||
// empty other
|
||||
let other = Bytes::new();
|
||||
@@ -600,49 +602,6 @@ fn bytes_unsplit_empty_self() {
|
||||
assert_eq!(b"aaabbbcccddd", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_unsplit_inline_arc() {
|
||||
let mut buf = Bytes::with_capacity(8); //inline
|
||||
buf.extend_from_slice(b"aaaabbbb");
|
||||
|
||||
let mut buf2 = Bytes::with_capacity(64);
|
||||
buf2.extend_from_slice(b"ccccddddeeee");
|
||||
|
||||
buf2.split_off(8); //arc
|
||||
|
||||
buf.unsplit(buf2);
|
||||
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_unsplit_arc_inline() {
|
||||
let mut buf = Bytes::with_capacity(64);
|
||||
buf.extend_from_slice(b"aaaabbbbeeee");
|
||||
|
||||
buf.split_off(8); //arc
|
||||
|
||||
let mut buf2 = Bytes::with_capacity(8); //inline
|
||||
buf2.extend_from_slice(b"ccccdddd");
|
||||
|
||||
buf.unsplit(buf2);
|
||||
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_unsplit_both_inline() {
|
||||
let mut buf = Bytes::with_capacity(16); //inline
|
||||
buf.extend_from_slice(b"aaaabbbbccccdddd");
|
||||
|
||||
let splitted = buf.split_off(8); // both inline
|
||||
assert_eq!(b"aaaabbbb", &buf[..]);
|
||||
assert_eq!(b"ccccdddd", &splitted[..]);
|
||||
|
||||
buf.unsplit(splitted);
|
||||
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn bytes_unsplit_arc_different() {
|
||||
let mut buf = Bytes::with_capacity(64);
|
||||
@@ -696,6 +655,7 @@ fn bytes_unsplit_overlapping_references() {
|
||||
assert_eq!(b"abcdefghijklmnopqrst", &buf0010[..]);
|
||||
assert_eq!(b"fghijklmno", &buf0515[..]);
|
||||
}
|
||||
*/
|
||||
|
||||
#[test]
|
||||
fn bytes_mut_unsplit_basic() {
|
||||
@@ -734,49 +694,6 @@ fn bytes_mut_unsplit_empty_self() {
|
||||
assert_eq!(b"aaabbbcccddd", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_mut_unsplit_inline_arc() {
|
||||
let mut buf = BytesMut::with_capacity(8); //inline
|
||||
buf.extend_from_slice(b"aaaabbbb");
|
||||
|
||||
let mut buf2 = BytesMut::with_capacity(64);
|
||||
buf2.extend_from_slice(b"ccccddddeeee");
|
||||
|
||||
buf2.split_off(8); //arc
|
||||
|
||||
buf.unsplit(buf2);
|
||||
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_mut_unsplit_arc_inline() {
|
||||
let mut buf = BytesMut::with_capacity(64);
|
||||
buf.extend_from_slice(b"aaaabbbbeeee");
|
||||
|
||||
buf.split_off(8); //arc
|
||||
|
||||
let mut buf2 = BytesMut::with_capacity(8); //inline
|
||||
buf2.extend_from_slice(b"ccccdddd");
|
||||
|
||||
buf.unsplit(buf2);
|
||||
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_mut_unsplit_both_inline() {
|
||||
let mut buf = BytesMut::with_capacity(16); //inline
|
||||
buf.extend_from_slice(b"aaaabbbbccccdddd");
|
||||
|
||||
let splitted = buf.split_off(8); // both inline
|
||||
assert_eq!(b"aaaabbbb", &buf[..]);
|
||||
assert_eq!(b"ccccdddd", &splitted[..]);
|
||||
|
||||
buf.unsplit(splitted);
|
||||
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn bytes_mut_unsplit_arc_different() {
|
||||
let mut buf = BytesMut::with_capacity(64);
|
||||
|
||||
Reference in New Issue
Block a user