Snap for 8564071 from 93e2e9787ff376ef44812969f84c2b9137067c57 to mainline-conscrypt-release

Change-Id: I5908cfa92cc0134dfd001fdd4410cd2b701c13ce
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 @@
 env:
   RUSTFLAGS: -Dwarnings
   RUST_BACKTRACE: 1
-  nightly: nightly-2020-12-17
+  nightly: nightly-2021-04-13
 
 defaults:
   run:
@@ -94,7 +94,7 @@
           - 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 @@
         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 @@
     ],
 }
 
+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 @@
     ],
     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 @@
 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_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 @@
   }
   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 @@
 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 @@
     /// 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 @@
     /// 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 @@
     /// `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 @@
         }
     }
 
+    /// 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 @@
         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 @@
     /// 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 @@
     /// 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 @@
         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 @@
     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 @@
     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 @@
         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 @@
     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 @@
         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 @@
     ///
     /// 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 @@
     ///
     /// assert_eq!(b"boo", &data[..]);
     /// ```
+    #[inline]
     pub fn write_byte(&mut self, index: usize, byte: u8) {
         assert!(index < self.len());
 
@@ -90,6 +92,7 @@
     ///
     /// assert_eq!(b"bar", &data[..]);
     /// ```
+    #[inline]
     pub fn copy_from_slice(&mut self, src: &[u8]) {
         use core::ptr;
 
@@ -116,6 +119,7 @@
     /// 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 @@
     ///
     /// assert_eq!(len, 3);
     /// ```
+    #[inline]
     pub fn len(&self) -> usize {
         self.0.len()
     }
@@ -150,6 +155,7 @@
             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 @@
             }
 
             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<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 @@
     /// 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 @@
         }
     }
 
-    /// Clears the buffer, removing all data.
+    /// Clears the buffer, removing all data. Existing capacity is preserved.
     ///
     /// # Examples
     ///
@@ -819,7 +821,7 @@
     }
 
     fn try_unsplit(&mut self, other: BytesMut) -> Result<(), BytesMut> {
-        if other.is_empty() {
+        if other.capacity() == 0 {
             return Ok(());
         }
 
@@ -1010,6 +1012,19 @@
     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 @@
     }
 }
 
+#[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 @@
     }
 }
 
+#[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 @@
 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 @@
 
     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 @@
 }
 
 #[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 @@
 }
 
 #[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 @@
     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 @@
 }
 
 #[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 @@
 }
 
 #[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 @@
     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 @@
         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 @@
     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);
+}