aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-10 07:01:37 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-10 07:01:37 +0000
commit3e56d2b731e7634655b12e24d0724ff12f8d5a1c (patch)
treebc916d77ff4abffd28ebc6040f8a732aca0311e7
parent073a8f76e3f94372ed2c11d71efbfcb2b168b424 (diff)
parent93e2e9787ff376ef44812969f84c2b9137067c57 (diff)
downloadbytes-android13-mainline-extservices-release.tar.gz
Snap for 8564071 from 93e2e9787ff376ef44812969f84c2b9137067c57 to mainline-extservices-releaseaml_ext_331814220aml_ext_331412000aml_ext_331312000aml_ext_331112010aml_ext_331012020android13-mainline-extservices-release
Change-Id: Ib31e964c496fcc750461a85bc175ddc015a60911
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--.github/workflows/ci.yml6
-rw-r--r--Android.bp124
-rw-r--r--CHANGELOG.md23
-rw-r--r--Cargo.toml7
-rw-r--r--Cargo.toml.orig12
-rw-r--r--METADATA8
-rw-r--r--TEST_MAPPING123
-rw-r--r--cargo2android.json11
-rw-r--r--ci/test-stable.sh3
-rw-r--r--patches/test_bytes.rs.patch12
-rw-r--r--src/buf/buf_impl.rs3
-rw-r--r--src/buf/buf_mut.rs77
-rw-r--r--src/buf/chain.rs27
-rw-r--r--src/buf/take.rs12
-rw-r--r--src/buf/uninit_slice.rs7
-rw-r--r--src/bytes.rs12
-rw-r--r--src/bytes_mut.rs21
-rw-r--r--src/lib.rs1
-rw-r--r--tests/test_buf_mut.rs53
-rw-r--r--tests/test_bytes.rs42
-rw-r--r--tests/test_chain.rs21
-rw-r--r--tests/test_take.rs20
23 files changed, 586 insertions, 41 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 8a97d76..64b65d2 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
{
"git": {
- "sha1": "7b18c1c076adf9dff4dca28ffc1bbd8759860798"
+ "sha1": "ebc61e5af14cd9b436ba880cf19e849b05a04c29"
}
}
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index fc03588..00a4414 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,7 +11,7 @@ on:
env:
RUSTFLAGS: -Dwarnings
RUST_BACKTRACE: 1
- nightly: nightly-2020-12-17
+ nightly: nightly-2021-04-13
defaults:
run:
@@ -94,7 +94,7 @@ jobs:
- powerpc-unknown-linux-gnu
- powerpc64-unknown-linux-gnu
- wasm32-unknown-unknown
- runs-on: ubuntu-16.04
+ runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Rust
@@ -160,6 +160,8 @@ jobs:
run: rustup update stable && rustup default stable
- name: Build documentation
run: cargo doc --no-deps --all-features
+ env:
+ RUSTDOCFLAGS: --cfg docsrs
- name: Publish documentation
run: |
cd target/doc
diff --git a/Android.bp b/Android.bp
index 4d22da0..97dc970 100644
--- a/Android.bp
+++ b/Android.bp
@@ -18,10 +18,130 @@ license {
],
}
+rust_defaults {
+ name: "bytes_test_defaults",
+ crate_name: "bytes",
+ cargo_env_compat: true,
+ cargo_pkg_version: "1.1.0",
+ test_suites: ["general-tests"],
+ auto_gen_config: true,
+ edition: "2018",
+ features: [
+ "default",
+ "std",
+ ],
+ rustlibs: [
+ "libbytes",
+ "libserde_test",
+ ],
+}
+
+rust_test {
+ name: "bytes_test_tests_test_buf",
+ defaults: ["bytes_test_defaults"],
+ host_supported: true,
+ srcs: ["tests/test_buf.rs"],
+ test_options: {
+ unit_test: true,
+ },
+}
+
+rust_test {
+ name: "bytes_test_tests_test_buf_mut",
+ defaults: ["bytes_test_defaults"],
+ host_supported: true,
+ srcs: ["tests/test_buf_mut.rs"],
+ test_options: {
+ unit_test: true,
+ },
+}
+
+rust_test {
+ name: "bytes_test_tests_test_bytes",
+ defaults: ["bytes_test_defaults"],
+ host_supported: true,
+ srcs: ["tests/test_bytes.rs"],
+ test_options: {
+ unit_test: true,
+ },
+}
+
+rust_test {
+ name: "bytes_test_tests_test_bytes_odd_alloc",
+ defaults: ["bytes_test_defaults"],
+ host_supported: true,
+ srcs: ["tests/test_bytes_odd_alloc.rs"],
+ test_options: {
+ unit_test: true,
+ },
+}
+
+rust_test {
+ name: "bytes_test_tests_test_bytes_vec_alloc",
+ defaults: ["bytes_test_defaults"],
+ host_supported: true,
+ srcs: ["tests/test_bytes_vec_alloc.rs"],
+ test_options: {
+ unit_test: true,
+ },
+}
+
+rust_test {
+ name: "bytes_test_tests_test_chain",
+ defaults: ["bytes_test_defaults"],
+ host_supported: true,
+ srcs: ["tests/test_chain.rs"],
+ test_options: {
+ unit_test: true,
+ },
+}
+
+rust_test {
+ name: "bytes_test_tests_test_debug",
+ defaults: ["bytes_test_defaults"],
+ host_supported: true,
+ srcs: ["tests/test_debug.rs"],
+ test_options: {
+ unit_test: true,
+ },
+}
+
+rust_test {
+ name: "bytes_test_tests_test_iter",
+ defaults: ["bytes_test_defaults"],
+ host_supported: true,
+ srcs: ["tests/test_iter.rs"],
+ test_options: {
+ unit_test: true,
+ },
+}
+
+rust_test {
+ name: "bytes_test_tests_test_reader",
+ defaults: ["bytes_test_defaults"],
+ host_supported: true,
+ srcs: ["tests/test_reader.rs"],
+ test_options: {
+ unit_test: true,
+ },
+}
+
+rust_test {
+ name: "bytes_test_tests_test_take",
+ defaults: ["bytes_test_defaults"],
+ host_supported: true,
+ srcs: ["tests/test_take.rs"],
+ test_options: {
+ unit_test: true,
+ },
+}
+
rust_library {
name: "libbytes",
host_supported: true,
crate_name: "bytes",
+ cargo_env_compat: true,
+ cargo_pkg_version: "1.1.0",
srcs: ["src/lib.rs"],
edition: "2018",
features: [
@@ -30,8 +150,12 @@ rust_library {
],
apex_available: [
"//apex_available:platform",
+ "com.android.bluetooth",
+ "com.android.compos",
"com.android.resolv",
+ "com.android.uwb",
"com.android.virt",
],
+ vendor_available: true,
min_sdk_version: "29",
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a53a165..636d36b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,24 @@
+# 1.1.0 (August 25, 2021)
+
+### Added
+
+- `BufMut::put_bytes(self, val, cnt)` (#487)
+- Implement `From<Box<[u8]>>` for `Bytes` (#504)
+
+### Changed
+
+- Override `put_slice` for `&mut [u8]` (#483)
+- Panic on integer overflow in `Chain::remaining` (#482)
+- Add inline tags to `UninitSlice` methods (#443)
+- Override `copy_to_bytes` for Chain and Take (#481)
+- Keep capacity when unsplit on empty other buf (#502)
+
+### Documented
+
+- Clarify `BufMut` allocation guarantees (#501)
+- Clarify `BufMut::put_int` behavior (#486)
+- Clarify actions of `clear` and `truncate`. (#508)
+
# 1.0.1 (January 11, 2021)
### Changed
@@ -10,7 +31,7 @@
# 1.0.0 (December 22, 2020)
### Changed
-- Rename Buf/BufMut, methods to chunk/chunk_mut (#450)
+- Rename `Buf`/`BufMut` methods `bytes()` and `bytes_mut()` to `chunk()` and `chunk_mut()` (#450)
### Removed
- remove unused Buf implementation. (#449)
diff --git a/Cargo.toml b/Cargo.toml
index d102cf0..065f0f1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,15 +13,16 @@
[package]
edition = "2018"
name = "bytes"
-version = "1.0.1"
+version = "1.1.0"
authors = ["Carl Lerche <me@carllerche.com>", "Sean McArthur <sean@seanmonstar.com>"]
description = "Types and traits for working with bytes"
-documentation = "https://docs.rs/bytes/1.0.1/bytes/"
readme = "README.md"
keywords = ["buffers", "zero-copy", "io"]
categories = ["network-programming", "data-structures"]
license = "MIT"
repository = "https://github.com/tokio-rs/bytes"
+[package.metadata.docs.rs]
+rustdoc-args = ["--cfg", "docsrs"]
[dependencies.serde]
version = "1.0.60"
features = ["alloc"]
@@ -34,4 +35,4 @@ version = "1.0"
default = ["std"]
std = []
[target."cfg(loom)".dev-dependencies.loom]
-version = "0.4"
+version = "0.5"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 8f4e224..2b7e32b 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -2,18 +2,15 @@
name = "bytes"
# When releasing to crates.io:
-# - Update html_root_url.
# - Update CHANGELOG.md.
-# - Update doc URL.
-# - Create "v1.0.x" git tag.
-version = "1.0.1"
+# - Create "v1.x.y" git tag.
+version = "1.1.0"
license = "MIT"
authors = [
"Carl Lerche <me@carllerche.com>",
"Sean McArthur <sean@seanmonstar.com>",
]
description = "Types and traits for working with bytes"
-documentation = "https://docs.rs/bytes/1.0.1/bytes/"
repository = "https://github.com/tokio-rs/bytes"
readme = "README.md"
keywords = ["buffers", "zero-copy", "io"]
@@ -31,4 +28,7 @@ serde = { version = "1.0.60", optional = true, default-features = false, feature
serde_test = "1.0"
[target.'cfg(loom)'.dev-dependencies]
-loom = "0.4"
+loom = "0.5"
+
+[package.metadata.docs.rs]
+rustdoc-args = ["--cfg", "docsrs"]
diff --git a/METADATA b/METADATA
index 9c2bf5a..6723e08 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/bytes/bytes-1.0.1.crate"
+ value: "https://static.crates.io/crates/bytes/bytes-1.1.0.crate"
}
- version: "1.0.1"
+ version: "1.1.0"
license_type: NOTICE
last_upgrade_date {
year: 2021
- month: 1
- day: 11
+ month: 9
+ day: 22
}
}
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..f298357
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,123 @@
+// Generated by update_crate_tests.py for tests that depend on this crate.
+{
+ "imports": [
+ {
+ "path": "external/rust/crates/futures-util"
+ },
+ {
+ "path": "external/rust/crates/jni"
+ },
+ {
+ "path": "external/rust/crates/tokio"
+ },
+ {
+ "path": "external/rust/crates/tokio-test"
+ }
+ ],
+ "presubmit": [
+ {
+ "name": "authfs_device_test_src_lib"
+ },
+ {
+ "name": "bytes_test_tests_test_buf"
+ },
+ {
+ "name": "bytes_test_tests_test_buf_mut"
+ },
+ {
+ "name": "bytes_test_tests_test_bytes"
+ },
+ {
+ "name": "bytes_test_tests_test_bytes_odd_alloc"
+ },
+ {
+ "name": "bytes_test_tests_test_bytes_vec_alloc"
+ },
+ {
+ "name": "bytes_test_tests_test_chain"
+ },
+ {
+ "name": "bytes_test_tests_test_debug"
+ },
+ {
+ "name": "bytes_test_tests_test_iter"
+ },
+ {
+ "name": "bytes_test_tests_test_reader"
+ },
+ {
+ "name": "bytes_test_tests_test_take"
+ },
+ {
+ "name": "doh_unit_test"
+ },
+ {
+ "name": "libapkverify.integration_test"
+ },
+ {
+ "name": "libapkverify.test"
+ },
+ {
+ "name": "microdroid_manager_test"
+ },
+ {
+ "name": "rustBinderTest"
+ },
+ {
+ "name": "virtualizationservice_device_test"
+ }
+ ],
+ "presubmit-rust": [
+ {
+ "name": "authfs_device_test_src_lib"
+ },
+ {
+ "name": "bytes_test_tests_test_buf"
+ },
+ {
+ "name": "bytes_test_tests_test_buf_mut"
+ },
+ {
+ "name": "bytes_test_tests_test_bytes"
+ },
+ {
+ "name": "bytes_test_tests_test_bytes_odd_alloc"
+ },
+ {
+ "name": "bytes_test_tests_test_bytes_vec_alloc"
+ },
+ {
+ "name": "bytes_test_tests_test_chain"
+ },
+ {
+ "name": "bytes_test_tests_test_debug"
+ },
+ {
+ "name": "bytes_test_tests_test_iter"
+ },
+ {
+ "name": "bytes_test_tests_test_reader"
+ },
+ {
+ "name": "bytes_test_tests_test_take"
+ },
+ {
+ "name": "doh_unit_test"
+ },
+ {
+ "name": "libapkverify.integration_test"
+ },
+ {
+ "name": "libapkverify.test"
+ },
+ {
+ "name": "microdroid_manager_test"
+ },
+ {
+ "name": "rustBinderTest"
+ },
+ {
+ "name": "virtualizationservice_device_test"
+ }
+ ]
+}
diff --git a/cargo2android.json b/cargo2android.json
index 01465d0..19c5df8 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -1,11 +1,16 @@
{
"apex-available": [
"//apex_available:platform",
+ "com.android.bluetooth",
+ "com.android.compos",
"com.android.resolv",
+ "com.android.uwb",
"com.android.virt"
],
- "min_sdk_version": "29",
"dependencies": true,
"device": true,
- "run": true
-} \ No newline at end of file
+ "min-sdk-version": "29",
+ "run": true,
+ "tests": true,
+ "vendor-available": true
+}
diff --git a/ci/test-stable.sh b/ci/test-stable.sh
index 01a32f5..4421f3a 100644
--- a/ci/test-stable.sh
+++ b/ci/test-stable.sh
@@ -5,7 +5,8 @@ set -ex
cmd="${1:-test}"
# Install cargo-hack for feature flag test
-cargo install cargo-hack
+host=$(rustc -Vv | grep host | sed 's/host: //')
+curl -LsSf https://github.com/taiki-e/cargo-hack/releases/latest/download/cargo-hack-$host.tar.gz | tar xzf - -C ~/.cargo/bin
# Run with each feature
# * --each-feature includes both default/no-default features
diff --git a/patches/test_bytes.rs.patch b/patches/test_bytes.rs.patch
new file mode 100644
index 0000000..429e7f5
--- /dev/null
+++ b/patches/test_bytes.rs.patch
@@ -0,0 +1,12 @@
+diff --git a/tests/test_bytes.rs b/tests/test_bytes.rs
+index f0cae99..402017b 100644
+--- a/tests/test_bytes.rs
++++ b/tests/test_bytes.rs
+@@ -288,6 +288,7 @@ fn split_to_uninitialized() {
+ }
+
+ #[test]
++#[ignore = "Android: we unwind differently."]
+ fn split_off_to_at_gt_len() {
+ fn make_bytes() -> Bytes {
+ let mut bytes = BytesMut::with_capacity(100);
diff --git a/src/buf/buf_impl.rs b/src/buf/buf_impl.rs
index 16ad8a7..a33c8a4 100644
--- a/src/buf/buf_impl.rs
+++ b/src/buf/buf_impl.rs
@@ -127,6 +127,9 @@ pub trait Buf {
/// This function should never panic. Once the end of the buffer is reached,
/// i.e., `Buf::remaining` returns 0, calls to `chunk()` should return an
/// empty slice.
+ // The `chunk` method was previously called `bytes`. This alias makes the rename
+ // more easily discoverable.
+ #[cfg_attr(docsrs, doc(alias = "bytes"))]
fn chunk(&self) -> &[u8];
/// Fills `dst` with potentially multiple slices starting at `self`'s
diff --git a/src/buf/buf_mut.rs b/src/buf/buf_mut.rs
index f736727..4c2bd2c 100644
--- a/src/buf/buf_mut.rs
+++ b/src/buf/buf_mut.rs
@@ -33,6 +33,10 @@ pub unsafe trait BufMut {
/// This value is greater than or equal to the length of the slice returned
/// by `chunk_mut()`.
///
+ /// Writing to a `BufMut` may involve allocating more memory on the fly.
+ /// Implementations may fail before reaching the number of bytes indicated
+ /// by this method if they encounter an allocation failure.
+ ///
/// # Examples
///
/// ```
@@ -158,6 +162,12 @@ pub unsafe trait BufMut {
/// `chunk_mut()` returning an empty slice implies that `remaining_mut()` will
/// return 0 and `remaining_mut()` returning 0 implies that `chunk_mut()` will
/// return an empty slice.
+ ///
+ /// This function may trigger an out-of-memory abort if it tries to allocate
+ /// memory and fails to do so.
+ // The `chunk_mut` method was previously called `bytes_mut`. This alias makes the
+ // rename more easily discoverable.
+ #[cfg_attr(docsrs, doc(alias = "bytes_mut"))]
fn chunk_mut(&mut self) -> &mut UninitSlice;
/// Transfer bytes into `self` from `src` and advance the cursor by the
@@ -251,6 +261,37 @@ pub unsafe trait BufMut {
}
}
+ /// Put `cnt` bytes `val` into `self`.
+ ///
+ /// Logically equivalent to calling `self.put_u8(val)` `cnt` times, but may work faster.
+ ///
+ /// `self` must have at least `cnt` remaining capacity.
+ ///
+ /// ```
+ /// use bytes::BufMut;
+ ///
+ /// let mut dst = [0; 6];
+ ///
+ /// {
+ /// let mut buf = &mut dst[..];
+ /// buf.put_bytes(b'a', 4);
+ ///
+ /// assert_eq!(2, buf.remaining_mut());
+ /// }
+ ///
+ /// assert_eq!(b"aaaa\0\0", &dst);
+ /// ```
+ ///
+ /// # Panics
+ ///
+ /// This function panics if there is not enough remaining capacity in
+ /// `self`.
+ fn put_bytes(&mut self, val: u8, cnt: usize) {
+ for _ in 0..cnt {
+ self.put_u8(val);
+ }
+ }
+
/// Writes an unsigned 8 bit integer to `self`.
///
/// The current position is advanced by 1.
@@ -693,7 +734,7 @@ pub unsafe trait BufMut {
self.put_slice(&n.to_le_bytes()[0..nbytes]);
}
- /// Writes a signed n-byte integer to `self` in big-endian byte order.
+ /// Writes low `nbytes` of a signed integer to `self` in big-endian byte order.
///
/// The current position is advanced by `nbytes`.
///
@@ -703,19 +744,19 @@ pub unsafe trait BufMut {
/// use bytes::BufMut;
///
/// let mut buf = vec![];
- /// buf.put_int(0x010203, 3);
+ /// buf.put_int(0x0504010203, 3);
/// assert_eq!(buf, b"\x01\x02\x03");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
- /// `self`.
+ /// `self` or if `nbytes` is greater than 8.
fn put_int(&mut self, n: i64, nbytes: usize) {
self.put_slice(&n.to_be_bytes()[mem::size_of_val(&n) - nbytes..]);
}
- /// Writes a signed n-byte integer to `self` in little-endian byte order.
+ /// Writes low `nbytes` of a signed integer to `self` in little-endian byte order.
///
/// The current position is advanced by `nbytes`.
///
@@ -725,14 +766,14 @@ pub unsafe trait BufMut {
/// use bytes::BufMut;
///
/// let mut buf = vec![];
- /// buf.put_int_le(0x010203, 3);
+ /// buf.put_int_le(0x0504010203, 3);
/// assert_eq!(buf, b"\x03\x02\x01");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
- /// `self`.
+ /// `self` or if `nbytes` is greater than 8.
fn put_int_le(&mut self, n: i64, nbytes: usize) {
self.put_slice(&n.to_le_bytes()[0..nbytes]);
}
@@ -1009,12 +1050,29 @@ unsafe impl BufMut for &mut [u8] {
let (_, b) = core::mem::replace(self, &mut []).split_at_mut(cnt);
*self = b;
}
+
+ #[inline]
+ fn put_slice(&mut self, src: &[u8]) {
+ self[..src.len()].copy_from_slice(src);
+ unsafe {
+ self.advance_mut(src.len());
+ }
+ }
+
+ fn put_bytes(&mut self, val: u8, cnt: usize) {
+ assert!(self.remaining_mut() >= cnt);
+ unsafe {
+ ptr::write_bytes(self.as_mut_ptr(), val, cnt);
+ self.advance_mut(cnt);
+ }
+ }
}
unsafe impl BufMut for Vec<u8> {
#[inline]
fn remaining_mut(&self) -> usize {
- usize::MAX - self.len()
+ // A vector can never have more than isize::MAX bytes
+ core::isize::MAX as usize - self.len()
}
#[inline]
@@ -1072,6 +1130,11 @@ unsafe impl BufMut for Vec<u8> {
fn put_slice(&mut self, src: &[u8]) {
self.extend_from_slice(src);
}
+
+ fn put_bytes(&mut self, val: u8, cnt: usize) {
+ let new_len = self.len().checked_add(cnt).unwrap();
+ self.resize(new_len, val);
+ }
}
// The existence of this function makes the compiler catch if the BufMut
diff --git a/src/buf/chain.rs b/src/buf/chain.rs
index d68bc2d..9ce5f23 100644
--- a/src/buf/chain.rs
+++ b/src/buf/chain.rs
@@ -1,5 +1,5 @@
use crate::buf::{IntoIter, UninitSlice};
-use crate::{Buf, BufMut};
+use crate::{Buf, BufMut, Bytes};
#[cfg(feature = "std")]
use std::io::IoSlice;
@@ -135,7 +135,7 @@ where
U: Buf,
{
fn remaining(&self) -> usize {
- self.a.remaining() + self.b.remaining()
+ self.a.remaining().checked_add(self.b.remaining()).unwrap()
}
fn chunk(&self) -> &[u8] {
@@ -170,6 +170,24 @@ where
n += self.b.chunks_vectored(&mut dst[n..]);
n
}
+
+ fn copy_to_bytes(&mut self, len: usize) -> Bytes {
+ let a_rem = self.a.remaining();
+ if a_rem >= len {
+ self.a.copy_to_bytes(len)
+ } else if a_rem == 0 {
+ self.b.copy_to_bytes(len)
+ } else {
+ assert!(
+ len - a_rem <= self.b.remaining(),
+ "`len` greater than remaining"
+ );
+ let mut ret = crate::BytesMut::with_capacity(len);
+ ret.put(&mut self.a);
+ ret.put((&mut self.b).take(len - a_rem));
+ ret.freeze()
+ }
+ }
}
unsafe impl<T, U> BufMut for Chain<T, U>
@@ -178,7 +196,10 @@ where
U: BufMut,
{
fn remaining_mut(&self) -> usize {
- self.a.remaining_mut() + self.b.remaining_mut()
+ self.a
+ .remaining_mut()
+ .checked_add(self.b.remaining_mut())
+ .unwrap()
}
fn chunk_mut(&mut self) -> &mut UninitSlice {
diff --git a/src/buf/take.rs b/src/buf/take.rs
index 1747f6e..d3cb10a 100644
--- a/src/buf/take.rs
+++ b/src/buf/take.rs
@@ -1,11 +1,11 @@
-use crate::Buf;
+use crate::{Buf, Bytes};
use core::cmp;
/// A `Buf` adapter which limits the bytes read from an underlying buffer.
///
/// This struct is generally created by calling `take()` on `Buf`. See
-/// documentation of [`take()`](trait.BufExt.html#method.take) for more details.
+/// documentation of [`take()`](trait.Buf.html#method.take) for more details.
#[derive(Debug)]
pub struct Take<T> {
inner: T,
@@ -144,4 +144,12 @@ impl<T: Buf> Buf for Take<T> {
self.inner.advance(cnt);
self.limit -= cnt;
}
+
+ fn copy_to_bytes(&mut self, len: usize) -> Bytes {
+ assert!(len <= self.remaining(), "`len` greater than remaining");
+
+ let r = self.inner.copy_to_bytes(len);
+ self.limit -= len;
+ r
+ }
}
diff --git a/src/buf/uninit_slice.rs b/src/buf/uninit_slice.rs
index 73f4e89..fb67c0a 100644
--- a/src/buf/uninit_slice.rs
+++ b/src/buf/uninit_slice.rs
@@ -40,6 +40,7 @@ impl UninitSlice {
///
/// let slice = unsafe { UninitSlice::from_raw_parts_mut(ptr, len) };
/// ```
+ #[inline]
pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice {
let maybe_init: &mut [MaybeUninit<u8>] =
core::slice::from_raw_parts_mut(ptr as *mut _, len);
@@ -64,6 +65,7 @@ impl UninitSlice {
///
/// assert_eq!(b"boo", &data[..]);
/// ```
+ #[inline]
pub fn write_byte(&mut self, index: usize, byte: u8) {
assert!(index < self.len());
@@ -90,6 +92,7 @@ impl UninitSlice {
///
/// assert_eq!(b"bar", &data[..]);
/// ```
+ #[inline]
pub fn copy_from_slice(&mut self, src: &[u8]) {
use core::ptr;
@@ -116,6 +119,7 @@ impl UninitSlice {
/// let mut slice = &mut data[..];
/// let ptr = BufMut::chunk_mut(&mut slice).as_mut_ptr();
/// ```
+ #[inline]
pub fn as_mut_ptr(&mut self) -> *mut u8 {
self.0.as_mut_ptr() as *mut _
}
@@ -133,6 +137,7 @@ impl UninitSlice {
///
/// assert_eq!(len, 3);
/// ```
+ #[inline]
pub fn len(&self) -> usize {
self.0.len()
}
@@ -150,6 +155,7 @@ macro_rules! impl_index {
impl Index<$t> for UninitSlice {
type Output = UninitSlice;
+ #[inline]
fn index(&self, index: $t) -> &UninitSlice {
let maybe_uninit: &[MaybeUninit<u8>] = &self.0[index];
unsafe { &*(maybe_uninit as *const [MaybeUninit<u8>] as *const UninitSlice) }
@@ -157,6 +163,7 @@ macro_rules! impl_index {
}
impl IndexMut<$t> for UninitSlice {
+ #[inline]
fn index_mut(&mut self, index: $t) -> &mut UninitSlice {
let maybe_uninit: &mut [MaybeUninit<u8>] = &mut self.0[index];
unsafe { &mut *(maybe_uninit as *mut [MaybeUninit<u8>] as *mut UninitSlice) }
diff --git a/src/bytes.rs b/src/bytes.rs
index b1b35ea..d0be0d2 100644
--- a/src/bytes.rs
+++ b/src/bytes.rs
@@ -797,14 +797,20 @@ impl From<&'static str> for Bytes {
impl From<Vec<u8>> for Bytes {
fn from(vec: Vec<u8>) -> Bytes {
- // into_boxed_slice doesn't return a heap allocation for empty vectors,
+ let slice = vec.into_boxed_slice();
+ slice.into()
+ }
+}
+
+impl From<Box<[u8]>> for Bytes {
+ fn from(slice: Box<[u8]>) -> Bytes {
+ // Box<[u8]> doesn't contain a heap allocation for empty slices,
// so the pointer isn't aligned enough for the KIND_VEC stashing to
// work.
- if vec.is_empty() {
+ if slice.is_empty() {
return Bytes::new();
}
- let slice = vec.into_boxed_slice();
let len = slice.len();
let ptr = Box::into_raw(slice) as *mut u8;
diff --git a/src/bytes_mut.rs b/src/bytes_mut.rs
index 61c0460..147484d 100644
--- a/src/bytes_mut.rs
+++ b/src/bytes_mut.rs
@@ -380,6 +380,8 @@ impl BytesMut {
/// If `len` is greater than the buffer's current length, this has no
/// effect.
///
+ /// Existing underlying capacity is preserved.
+ ///
/// The [`split_off`] method can emulate `truncate`, but this causes the
/// excess bytes to be returned instead of dropped.
///
@@ -402,7 +404,7 @@ impl BytesMut {
}
}
- /// Clears the buffer, removing all data.
+ /// Clears the buffer, removing all data. Existing capacity is preserved.
///
/// # Examples
///
@@ -819,7 +821,7 @@ impl BytesMut {
}
fn try_unsplit(&mut self, other: BytesMut) -> Result<(), BytesMut> {
- if other.is_empty() {
+ if other.capacity() == 0 {
return Ok(());
}
@@ -1010,6 +1012,19 @@ unsafe impl BufMut for BytesMut {
fn put_slice(&mut self, src: &[u8]) {
self.extend_from_slice(src);
}
+
+ fn put_bytes(&mut self, val: u8, cnt: usize) {
+ self.reserve(cnt);
+ unsafe {
+ let dst = self.uninit_slice();
+ // Reserved above
+ debug_assert!(dst.len() >= cnt);
+
+ ptr::write_bytes(dst.as_mut_ptr(), val, cnt);
+
+ self.advance_mut(cnt);
+ }
+ }
}
impl AsRef<[u8]> for BytesMut {
@@ -1250,6 +1265,7 @@ impl Shared {
}
}
+#[inline]
fn original_capacity_to_repr(cap: usize) -> usize {
let width = PTR_WIDTH - ((cap >> MIN_ORIGINAL_CAPACITY_WIDTH).leading_zeros() as usize);
cmp::min(
@@ -1476,6 +1492,7 @@ impl PartialEq<Bytes> for BytesMut {
}
}
+#[inline]
fn vptr(ptr: *mut u8) -> NonNull<u8> {
if cfg!(debug_assertions) {
NonNull::new(ptr).expect("Vec pointer should be non-null")
diff --git a/src/lib.rs b/src/lib.rs
index dd8cc96..706735e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,7 +3,6 @@
no_crate_inject,
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
))]
-#![doc(html_root_url = "https://docs.rs/bytes/1.0.1")]
#![no_std]
//! Provides abstractions for working with bytes.
diff --git a/tests/test_buf_mut.rs b/tests/test_buf_mut.rs
index 8d270e3..53f4e86 100644
--- a/tests/test_buf_mut.rs
+++ b/tests/test_buf_mut.rs
@@ -9,7 +9,7 @@ use core::usize;
fn test_vec_as_mut_buf() {
let mut buf = Vec::with_capacity(64);
- assert_eq!(buf.remaining_mut(), usize::MAX);
+ assert_eq!(buf.remaining_mut(), isize::MAX as usize);
assert!(buf.chunk_mut().len() >= 64);
@@ -17,7 +17,7 @@ fn test_vec_as_mut_buf() {
assert_eq!(&buf, b"zomg");
- assert_eq!(buf.remaining_mut(), usize::MAX - 4);
+ assert_eq!(buf.remaining_mut(), isize::MAX as usize - 4);
assert_eq!(buf.capacity(), 64);
for _ in 0..16 {
@@ -28,6 +28,14 @@ fn test_vec_as_mut_buf() {
}
#[test]
+fn test_vec_put_bytes() {
+ let mut buf = Vec::new();
+ buf.push(17);
+ buf.put_bytes(19, 2);
+ assert_eq!([17, 19, 19], &buf[..]);
+}
+
+#[test]
fn test_put_u8() {
let mut buf = Vec::with_capacity(8);
buf.put_u8(33);
@@ -46,6 +54,34 @@ fn test_put_u16() {
}
#[test]
+fn test_put_int() {
+ let mut buf = Vec::with_capacity(8);
+ buf.put_int(0x1020304050607080, 3);
+ assert_eq!(b"\x60\x70\x80", &buf[..]);
+}
+
+#[test]
+#[should_panic]
+fn test_put_int_nbytes_overflow() {
+ let mut buf = Vec::with_capacity(8);
+ buf.put_int(0x1020304050607080, 9);
+}
+
+#[test]
+fn test_put_int_le() {
+ let mut buf = Vec::with_capacity(8);
+ buf.put_int_le(0x1020304050607080, 3);
+ assert_eq!(b"\x80\x70\x60", &buf[..]);
+}
+
+#[test]
+#[should_panic]
+fn test_put_int_le_nbytes_overflow() {
+ let mut buf = Vec::with_capacity(8);
+ buf.put_int_le(0x1020304050607080, 9);
+}
+
+#[test]
#[should_panic(expected = "cannot advance")]
fn test_vec_advance_mut() {
// Verify fix for #354
@@ -70,6 +106,19 @@ fn test_mut_slice() {
let mut v = vec![0, 0, 0, 0];
let mut s = &mut v[..];
s.put_u32(42);
+
+ assert_eq!(s.len(), 0);
+ assert_eq!(&v, &[0, 0, 0, 42]);
+}
+
+#[test]
+fn test_slice_put_bytes() {
+ let mut v = [0, 0, 0, 0];
+ let mut s = &mut v[..];
+ s.put_u8(17);
+ s.put_bytes(19, 2);
+ assert_eq!(1, s.remaining_mut());
+ assert_eq!(&[17, 19, 19, 0], &v[..]);
}
#[test]
diff --git a/tests/test_bytes.rs b/tests/test_bytes.rs
index b9e6ce4..402017b 100644
--- a/tests/test_bytes.rs
+++ b/tests/test_bytes.rs
@@ -288,6 +288,7 @@ fn split_to_uninitialized() {
}
#[test]
+#[ignore = "Android: we unwind differently."]
fn split_off_to_at_gt_len() {
fn make_bytes() -> Bytes {
let mut bytes = BytesMut::with_capacity(100);
@@ -785,6 +786,31 @@ fn bytes_mut_unsplit_empty_self() {
}
#[test]
+fn bytes_mut_unsplit_other_keeps_capacity() {
+ let mut buf = BytesMut::with_capacity(64);
+ buf.extend_from_slice(b"aabb");
+
+ // non empty other created "from" buf
+ let mut other = buf.split_off(buf.len());
+ other.extend_from_slice(b"ccddee");
+ buf.unsplit(other);
+
+ assert_eq!(buf.capacity(), 64);
+}
+
+#[test]
+fn bytes_mut_unsplit_empty_other_keeps_capacity() {
+ let mut buf = BytesMut::with_capacity(64);
+ buf.extend_from_slice(b"aabbccddee");
+
+ // empty other created "from" buf
+ let other = buf.split_off(buf.len());
+ buf.unsplit(other);
+
+ assert_eq!(buf.capacity(), 64);
+}
+
+#[test]
fn bytes_mut_unsplit_arc_different() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbeeee");
@@ -961,3 +987,19 @@ fn bytes_with_capacity_but_empty() {
let vec = Vec::with_capacity(1);
let _ = Bytes::from(vec);
}
+
+#[test]
+fn bytes_put_bytes() {
+ let mut bytes = BytesMut::new();
+ bytes.put_u8(17);
+ bytes.put_bytes(19, 2);
+ assert_eq!([17, 19, 19], bytes.as_ref());
+}
+
+#[test]
+fn box_slice_empty() {
+ // See https://github.com/tokio-rs/bytes/issues/340
+ let empty: Box<[u8]> = Default::default();
+ let b = Bytes::from(empty);
+ assert!(b.is_empty());
+}
diff --git a/tests/test_chain.rs b/tests/test_chain.rs
index 500ccd4..affaf7a 100644
--- a/tests/test_chain.rs
+++ b/tests/test_chain.rs
@@ -132,3 +132,24 @@ fn vectored_read() {
assert_eq!(iovecs[3][..], b""[..]);
}
}
+
+#[test]
+fn chain_get_bytes() {
+ let mut ab = Bytes::copy_from_slice(b"ab");
+ let mut cd = Bytes::copy_from_slice(b"cd");
+ let ab_ptr = ab.as_ptr();
+ let cd_ptr = cd.as_ptr();
+ let mut chain = (&mut ab).chain(&mut cd);
+ let a = chain.copy_to_bytes(1);
+ let bc = chain.copy_to_bytes(2);
+ let d = chain.copy_to_bytes(1);
+
+ assert_eq!(Bytes::copy_from_slice(b"a"), a);
+ assert_eq!(Bytes::copy_from_slice(b"bc"), bc);
+ assert_eq!(Bytes::copy_from_slice(b"d"), d);
+
+ // assert `get_bytes` did not allocate
+ assert_eq!(ab_ptr, a.as_ptr());
+ // assert `get_bytes` did not allocate
+ assert_eq!(cd_ptr.wrapping_offset(1), d.as_ptr());
+}
diff --git a/tests/test_take.rs b/tests/test_take.rs
index a23a29e..51df91d 100644
--- a/tests/test_take.rs
+++ b/tests/test_take.rs
@@ -1,6 +1,7 @@
#![warn(rust_2018_idioms)]
use bytes::buf::Buf;
+use bytes::Bytes;
#[test]
fn long_take() {
@@ -10,3 +11,22 @@ fn long_take() {
assert_eq!(11, buf.remaining());
assert_eq!(b"hello world", buf.chunk());
}
+
+#[test]
+fn take_copy_to_bytes() {
+ let mut abcd = Bytes::copy_from_slice(b"abcd");
+ let abcd_ptr = abcd.as_ptr();
+ let mut take = (&mut abcd).take(2);
+ let a = take.copy_to_bytes(1);
+ assert_eq!(Bytes::copy_from_slice(b"a"), a);
+ // assert `to_bytes` did not allocate
+ assert_eq!(abcd_ptr, a.as_ptr());
+ assert_eq!(Bytes::copy_from_slice(b"bcd"), abcd);
+}
+
+#[test]
+#[should_panic]
+fn take_copy_to_bytes_panics() {
+ let abcd = Bytes::copy_from_slice(b"abcd");
+ abcd.take(2).copy_to_bytes(3);
+}