зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1716518 - Upgrade bytes to v0.4.12 and v0.5.6. r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D117769
This commit is contained in:
Родитель
d46a175de9
Коммит
1144362c0b
|
@ -149,7 +149,7 @@ dependencies = [
|
|||
"ashmem",
|
||||
"audio_thread_priority",
|
||||
"bincode",
|
||||
"bytes 0.4.9",
|
||||
"bytes 0.4.12",
|
||||
"cc",
|
||||
"cubeb",
|
||||
"error-chain",
|
||||
|
@ -454,9 +454,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
|||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "0.4.9"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e178b8e0e239e844b083d5a0d4a156b2654e67f9f80144d48398fcd736a24fb8"
|
||||
checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"iovec",
|
||||
|
@ -464,9 +464,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "0.5.3"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10004c15deb332055f7a4a208190aed362cf9a7c2f6ab70a305fba50e1105f38"
|
||||
checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
|
||||
|
||||
[[package]]
|
||||
name = "c2-chacha"
|
||||
|
@ -2229,7 +2229,7 @@ version = "0.2.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7938e6aa2a31df4e21f224dc84704bd31c089a6d1355c535b03667371cccc843"
|
||||
dependencies = [
|
||||
"bytes 0.5.3",
|
||||
"bytes 0.5.6",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
|
@ -2289,7 +2289,7 @@ checksum = "ed18eb2459bf1a09ad2d6b1547840c3e5e62882fa09b9a6a20b1de8e3228848f"
|
|||
dependencies = [
|
||||
"base64 0.12.3",
|
||||
"bitflags",
|
||||
"bytes 0.5.3",
|
||||
"bytes 0.5.6",
|
||||
"headers-core",
|
||||
"http",
|
||||
"mime",
|
||||
|
@ -2327,7 +2327,7 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b"
|
||||
dependencies = [
|
||||
"bytes 0.5.3",
|
||||
"bytes 0.5.6",
|
||||
"fnv",
|
||||
"itoa",
|
||||
]
|
||||
|
@ -2338,7 +2338,7 @@ version = "0.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b"
|
||||
dependencies = [
|
||||
"bytes 0.5.3",
|
||||
"bytes 0.5.6",
|
||||
"http",
|
||||
]
|
||||
|
||||
|
@ -2386,7 +2386,7 @@ version = "0.13.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96816e1d921eca64d208a85aab4f7798455a8e34229ee5a88c935bdee1b78b14"
|
||||
dependencies = [
|
||||
"bytes 0.5.3",
|
||||
"bytes 0.5.6",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
|
@ -3976,7 +3976,7 @@ version = "0.6.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce49aefe0a6144a45de32927c77bd2859a5f7677b55f220ae5b744e87389c212"
|
||||
dependencies = [
|
||||
"bytes 0.5.3",
|
||||
"bytes 0.5.6",
|
||||
"prost-derive",
|
||||
]
|
||||
|
||||
|
@ -5176,7 +5176,7 @@ version = "0.1.11"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e93c78d23cc61aa245a8acd2c4a79c4d7fa7fb5c3ca90d5737029f043a84895"
|
||||
dependencies = [
|
||||
"bytes 0.4.9",
|
||||
"bytes 0.4.12",
|
||||
"futures 0.1.29",
|
||||
"mio",
|
||||
"tokio-codec",
|
||||
|
@ -5198,7 +5198,7 @@ version = "0.2.18"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34ef16d072d2b6dc8b4a56c70f5c5ced1a37752116f8e7c1e80c659aa7cb6713"
|
||||
dependencies = [
|
||||
"bytes 0.5.3",
|
||||
"bytes 0.5.6",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"iovec",
|
||||
|
@ -5215,7 +5215,7 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "881e9645b81c2ce95fcb799ded2c29ffb9f25ef5bef909089a420e5961dd8ccb"
|
||||
dependencies = [
|
||||
"bytes 0.4.9",
|
||||
"bytes 0.4.12",
|
||||
"futures 0.1.29",
|
||||
"tokio-io",
|
||||
]
|
||||
|
@ -5257,7 +5257,7 @@ version = "0.1.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5c9635ee806f26d302b8baa1e145689a280d8f5aa8d0552e7344808da54cc21"
|
||||
dependencies = [
|
||||
"bytes 0.4.9",
|
||||
"bytes 0.4.12",
|
||||
"futures 0.1.29",
|
||||
"log",
|
||||
]
|
||||
|
@ -5282,7 +5282,7 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b4c329b47f071eb8a746040465fa751bd95e4716e98daef6a9b4e434c17d565"
|
||||
dependencies = [
|
||||
"bytes 0.4.9",
|
||||
"bytes 0.4.12",
|
||||
"futures 0.1.29",
|
||||
"iovec",
|
||||
"mio",
|
||||
|
@ -5325,7 +5325,7 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43eb534af6e8f37d43ab1b612660df14755c42bd003c5f8d2475ee78cc4600c0"
|
||||
dependencies = [
|
||||
"bytes 0.4.9",
|
||||
"bytes 0.4.12",
|
||||
"futures 0.1.29",
|
||||
"log",
|
||||
"mio",
|
||||
|
@ -5340,7 +5340,7 @@ version = "0.2.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445"
|
||||
dependencies = [
|
||||
"bytes 0.4.9",
|
||||
"bytes 0.4.12",
|
||||
"futures 0.1.29",
|
||||
"iovec",
|
||||
"libc",
|
||||
|
@ -5358,7 +5358,7 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930"
|
||||
dependencies = [
|
||||
"bytes 0.5.3",
|
||||
"bytes 0.5.6",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"log",
|
||||
|
@ -5595,7 +5595,7 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54cd1e2b3eb3539284d88b76a9afcf5e20f2ef2fab74db5b21a1c30d7d945e82"
|
||||
dependencies = [
|
||||
"bytes 0.5.3",
|
||||
"bytes 0.5.6",
|
||||
"futures 0.3.12",
|
||||
"headers",
|
||||
"http",
|
||||
|
@ -5648,7 +5648,7 @@ name = "webdriver"
|
|||
version = "0.43.1"
|
||||
dependencies = [
|
||||
"base64 0.12.3",
|
||||
"bytes 0.5.3",
|
||||
"bytes 0.5.6",
|
||||
"cookie",
|
||||
"http",
|
||||
"log",
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{"files":{"CHANGELOG.md":"4653003b329c39ab26967eb8e867f678f91848c0b9110087cf2f1f94cd9fa5fb","Cargo.toml":"c26672075ad52777c94facd5d1a8bd5a062a8cae93dd19fed7261f309c478380","LICENSE":"45f522cacecb1023856e46df79ca625dfc550c94910078bd8aec6e02880b3d42","README.md":"98017aa9d4a827389919b1a35cbf4173a50fe631a33923d77f51b49388f5f47b","benches/bytes.rs":"a60889c35cf76faf2b403f94d3ab2831a569f2e1f6e4cc4d5e88f3c26bddb8b0","ci/before_deploy.ps1":"a8ee0204dd1397a245a47626fecd98eff5da76e12b15139c06271b3cc309a3e1","ci/before_deploy.sh":"ea008e2c544482cba5b659c17887ccd5354779c629096f28e667d40391299cc5","ci/install.sh":"8b165fc99df296261fcc9cdcbc8b8a177c11c505cdc9255cc19efb66cb0055db","ci/script.sh":"4e6f6b7df02d316ce5166a3526dc6bca6b6d051dbc5bd6d5b28a7c79fc646834","ci/tsan":"ab91828d326a1fa304097de624c00bc264066223fcb6ff2a0e1eef0b3365abeb","src/buf/buf.rs":"bb75d85a07d132c869cf2f34200003c8ff9f721642df17a8a98a935a7562d886","src/buf/buf_mut.rs":"576750f263091bfb15e7ad00be086d252fb75bbf8d63017186ce67438987355d","src/buf/chain.rs":"3a4f88879d27240e84e58bbeddf3f7c0958d0d81f4707245199b53e922029a26","src/buf/from_buf.rs":"949683c6a08099b280bd324d0c8646b1d6ff80af4d3e9397edb76cc2f1b18c88","src/buf/into_buf.rs":"b6e35d34533fae229f5209b95a39a1c35485f48a873a1d357d99218c486b0b95","src/buf/iter.rs":"325428e4f913beb602f6451b59847d4c8658ec23939a15f7b145733969c17f03","src/buf/mod.rs":"481a8f937f0f015ac1136febe59148e8b7039326102983e5a4cce8dab4d4de1e","src/buf/reader.rs":"ba26856d56300cf4397cf0d1b19089267c8e51355c38133e3d25d63331bb3a7a","src/buf/take.rs":"0bdd0720afc546c999e5a3125f20b6f31a5692b37f7218c25f414773e2702f3d","src/buf/vec_deque.rs":"4023992fd8607a7a6a45f3120d39c33fd4ec5cb68f171dcd9eff6b92fde15599","src/buf/writer.rs":"4a28c1d362e837682a4b3197732a6dbb4072dc660f0dbba18616679adf8a60f2","src/bytes.rs":"213533117810e44a669972d8166a7215228e4bbf4ae18796fca4ebdbbc7c16ac","src/debug.rs":"a8bd8062e7e500fdc5a79cb6c848fb860be8359d95e1c91034777fe33c78d54e","src/either.rs":"5ecb5bcec6faea2454d274cdfef8fd26096e1b93d586cb29aebfe42291026e43","src/lib.rs":"ceabc03d07402008c2177b21cc9ea9ca0556d67b07dc4740908942145188c573","src/serde.rs":"e8d0fe3630e173272756fb24a8c3ccb112f4cb551b8b88b64f669a71f39ef83b","tests/test_buf.rs":"6409f32f734969bebeffa7592fed531953d252c5a639e422b6e4b14ec024b1d5","tests/test_buf_mut.rs":"a6a653d5053340b0254900c33e36df6db1421f821c3e985be0044b1b447ecedc","tests/test_bytes.rs":"59538b70536e0947e00b9503da24f2c511cd8b454ad2d57b8e7e7f6ed34b0490","tests/test_chain.rs":"3fe1f28f3bce4377f8ed506718f95f3ed3ebaf251a1cb43b2705331e3dd6b43a","tests/test_debug.rs":"4cfd44c30d0b8f7c5eb8e8916ad7436e9f538732fe9f4b696dc22b84c31ac64a","tests/test_from_buf.rs":"9bf743c77e69c643d0a7673426547dacaedbcc65028a26cf5864eb6714e4897a","tests/test_iter.rs":"bc8a5da0b3cc7e5a5dc37e91dd2a3ca3fc78ba74b087883473043be45cd9b265","tests/test_reader.rs":"a23c969882dda095c42f5e4da54b2274854c3ece9864ff9ff2439ab4ee289b11","tests/test_serde.rs":"98e0ab121153a7ead47538257ac7fc7d5db081fc35050552b5e5dc9500b414f9","tests/test_take.rs":"bb81822eec5d3774bd2626f0f29b543d3651f4f5a95c51dfe8f93dec8b4f8e94"},"package":"206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"}
|
|
@ -1,3 +1,20 @@
|
|||
# 0.4.12 (March 6, 2018)
|
||||
|
||||
### Added
|
||||
- Implement `FromIterator<&'a u8>` for `BytesMut`/`Bytes` (#244).
|
||||
- Implement `Buf` for `VecDeque` (#249).
|
||||
|
||||
# 0.4.11 (November 17, 2018)
|
||||
|
||||
* Use raw pointers for potentially racy loads (#233).
|
||||
* Implement `BufRead` for `buf::Reader` (#232).
|
||||
* Documentation tweaks (#234).
|
||||
|
||||
# 0.4.10 (September 4, 2018)
|
||||
|
||||
* impl `Buf` and `BufMut` for `Either` (#225).
|
||||
* Add `Bytes::slice_ref` (#208).
|
||||
|
||||
# 0.4.9 (July 12, 2018)
|
||||
|
||||
* Add 128 bit number support behind a feature flag (#209).
|
|
@ -12,12 +12,12 @@
|
|||
|
||||
[package]
|
||||
name = "bytes"
|
||||
version = "0.4.9"
|
||||
version = "0.4.12"
|
||||
authors = ["Carl Lerche <me@carllerche.com>"]
|
||||
exclude = [".gitignore", ".travis.yml", "deploy.sh", "bench/**/*", "test/**/*"]
|
||||
description = "Types and traits for working with bytes"
|
||||
homepage = "https://github.com/carllerche/bytes"
|
||||
documentation = "https://carllerche.github.io/bytes/bytes"
|
||||
documentation = "https://docs.rs/bytes/0.4.12/bytes"
|
||||
readme = "README.md"
|
||||
keywords = ["buffers", "zero-copy", "io"]
|
||||
categories = ["network-programming", "data-structures"]
|
||||
|
@ -28,6 +28,11 @@ features = ["i128"]
|
|||
[dependencies.byteorder]
|
||||
version = "1.1.0"
|
||||
|
||||
[dependencies.either]
|
||||
version = "1.5"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dependencies.iovec]
|
||||
version = "0.1"
|
||||
|
|
@ -5,7 +5,7 @@ A utility library for working with bytes.
|
|||
[![Crates.io](https://img.shields.io/crates/v/bytes.svg?maxAge=2592000)](https://crates.io/crates/bytes)
|
||||
[![Build Status](https://travis-ci.org/carllerche/bytes.svg?branch=master)](https://travis-ci.org/carllerche/bytes)
|
||||
|
||||
[Documentation](https://carllerche.github.io/bytes/bytes/index.html)
|
||||
[Documentation](https://docs.rs/bytes/0.4.12/bytes/)
|
||||
|
||||
## Usage
|
||||
|
||||
|
@ -13,7 +13,7 @@ To use `bytes`, first add this to your `Cargo.toml`:
|
|||
|
||||
```toml
|
||||
[dependencies]
|
||||
bytes = "0.4"
|
||||
bytes = "0.4.12"
|
||||
```
|
||||
|
||||
Next, add this to your crate:
|
||||
|
@ -30,7 +30,7 @@ Serde support is optional and disabled by default. To enable use the feature `se
|
|||
|
||||
```toml
|
||||
[dependencies]
|
||||
bytes = { version = "0.4", features = ["serde"] }
|
||||
bytes = { version = "0.4.12", features = ["serde"] }
|
||||
```
|
||||
|
||||
## License
|
|
@ -19,6 +19,10 @@ 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
|
|
@ -91,7 +91,8 @@ pub trait Buf {
|
|||
fn remaining(&self) -> usize;
|
||||
|
||||
/// Returns a slice starting at the current position and of length between 0
|
||||
/// and `Buf::remaining()`.
|
||||
/// and `Buf::remaining()`. Note that this *can* return shorter slice (this allows
|
||||
/// non-continuous internal representation).
|
||||
///
|
||||
/// This is a lower level function. Most operations are done with other
|
||||
/// functions.
|
|
@ -121,7 +121,8 @@ pub trait BufMut {
|
|||
}
|
||||
|
||||
/// Returns a mutable slice starting at the current BufMut position and of
|
||||
/// length between 0 and `BufMut::remaining_mut()`.
|
||||
/// length between 0 and `BufMut::remaining_mut()`. Note that this *can* be shorter than the
|
||||
/// whole remainder of the buffer (this allows non-continuous implementation).
|
||||
///
|
||||
/// This is a lower level function. Most operations are done with other
|
||||
/// functions.
|
|
@ -24,6 +24,7 @@ mod into_buf;
|
|||
mod iter;
|
||||
mod reader;
|
||||
mod take;
|
||||
mod vec_deque;
|
||||
mod writer;
|
||||
|
||||
pub use self::buf::Buf;
|
|
@ -86,3 +86,12 @@ impl<B: Buf + Sized> io::Read for Reader<B> {
|
|||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Buf + Sized> io::BufRead for Reader<B> {
|
||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
||||
Ok(self.buf.bytes())
|
||||
}
|
||||
fn consume(&mut self, amt: usize) {
|
||||
self.buf.advance(amt)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
use std::collections::VecDeque;
|
||||
|
||||
use super::Buf;
|
||||
|
||||
impl Buf for VecDeque<u8> {
|
||||
fn remaining(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn bytes(&self) -> &[u8] {
|
||||
let (s1, s2) = self.as_slices();
|
||||
if s1.is_empty() {
|
||||
s2
|
||||
} else {
|
||||
s1
|
||||
}
|
||||
}
|
||||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
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");
|
||||
assert_eq!(b"world piece" as &[u8], &buffer.collect::<Vec<u8>>()[..]);
|
||||
}
|
||||
}
|
|
@ -273,7 +273,7 @@ pub struct BytesMut {
|
|||
// The rest of `arc`'s bytes are used as part of the inline buffer, which means
|
||||
// that those bytes need to be located next to the `ptr`, `len`, and `cap`
|
||||
// fields, which make up the rest of the inline buffer. This requires special
|
||||
// casing the layout of `Inner` depending on if the target platform is bit or
|
||||
// casing the layout of `Inner` depending on if the target platform is big or
|
||||
// little endian.
|
||||
//
|
||||
// On little endian platforms, the `arc` field must be the first field in the
|
||||
|
@ -576,6 +576,46 @@ impl Bytes {
|
|||
self.slice(0, end)
|
||||
}
|
||||
|
||||
/// Returns a slice of self that is equivalent to the given `subset`.
|
||||
///
|
||||
/// When processing a `Bytes` buffer with other tools, one often gets a
|
||||
/// `&[u8]` which is in fact a slice of the `Bytes`, i.e. a subset of it.
|
||||
/// This function turns that `&[u8]` into another `Bytes`, as if one had
|
||||
/// called `self.slice()` with the offsets that correspond to `subset`.
|
||||
///
|
||||
/// This operation is `O(1)`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::Bytes;
|
||||
///
|
||||
/// let bytes = Bytes::from(&b"012345678"[..]);
|
||||
/// let as_slice = bytes.as_ref();
|
||||
/// let subset = &as_slice[2..6];
|
||||
/// let subslice = bytes.slice_ref(&subset);
|
||||
/// assert_eq!(&subslice[..], b"2345");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Requires that the given `sub` slice is in fact contained within the
|
||||
/// `Bytes` buffer; otherwise this function will panic.
|
||||
pub fn slice_ref(&self, subset: &[u8]) -> Bytes {
|
||||
let bytes_p = self.as_ptr() as usize;
|
||||
let bytes_len = self.len();
|
||||
|
||||
let sub_p = subset.as_ptr() as usize;
|
||||
let sub_len = subset.len();
|
||||
|
||||
assert!(sub_p >= bytes_p);
|
||||
assert!(sub_p + sub_len <= bytes_p + bytes_len);
|
||||
|
||||
let sub_offset = sub_p - bytes_p;
|
||||
|
||||
self.slice(sub_offset, sub_offset + sub_len)
|
||||
}
|
||||
|
||||
/// Splits the bytes into two at the given index.
|
||||
///
|
||||
/// Afterwards `self` contains elements `[0, at)`, and the returned `Bytes`
|
||||
|
@ -886,6 +926,18 @@ impl FromIterator<u8> for Bytes {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> FromIterator<&'a u8> for BytesMut {
|
||||
fn from_iter<T: IntoIterator<Item = &'a u8>>(into_iter: T) -> Self {
|
||||
BytesMut::from_iter(into_iter.into_iter().map(|b| *b))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromIterator<&'a u8> for Bytes {
|
||||
fn from_iter<T: IntoIterator<Item = &'a u8>>(into_iter: T) -> Self {
|
||||
BytesMut::from_iter(into_iter).freeze()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Bytes {
|
||||
fn eq(&self, other: &Bytes) -> bool {
|
||||
self.inner.as_ref() == other.inner.as_ref()
|
||||
|
@ -2389,6 +2441,10 @@ impl Inner {
|
|||
// bits, so even without any explicit atomic operations, reading the
|
||||
// flag will be correct.
|
||||
//
|
||||
// This is undefind behavior due to a data race, but experimental
|
||||
// evidence shows that it works in practice (discussion:
|
||||
// https://internals.rust-lang.org/t/bit-wise-reasoning-for-atomic-accesses/8853).
|
||||
//
|
||||
// This function is very critical performance wise as it is called for
|
||||
// every operation. Performing an atomic load would mess with the
|
||||
// compiler's ability to optimize. Simple benchmarks show up to a 10%
|
||||
|
@ -2398,7 +2454,7 @@ impl Inner {
|
|||
#[inline]
|
||||
fn imp(arc: &AtomicPtr<Shared>) -> usize {
|
||||
unsafe {
|
||||
let p: &u8 = mem::transmute(arc);
|
||||
let p: *const u8 = mem::transmute(arc);
|
||||
(*p as usize) & KIND_MASK
|
||||
}
|
||||
}
|
||||
|
@ -2407,7 +2463,7 @@ impl Inner {
|
|||
#[inline]
|
||||
fn imp(arc: &AtomicPtr<Shared>) -> usize {
|
||||
unsafe {
|
||||
let p: &usize = mem::transmute(arc);
|
||||
let p: *const usize = mem::transmute(arc);
|
||||
*p & KIND_MASK
|
||||
}
|
||||
}
|
||||
|
@ -2423,7 +2479,7 @@ impl Inner {
|
|||
// function.
|
||||
let prev = unsafe {
|
||||
let p: &AtomicPtr<Shared> = &self.arc;
|
||||
let p: &usize = mem::transmute(p);
|
||||
let p: *const usize = mem::transmute(p);
|
||||
*p
|
||||
};
|
||||
|
||||
|
@ -2530,35 +2586,51 @@ fn original_capacity_from_repr(repr: usize) -> usize {
|
|||
|
||||
#[test]
|
||||
fn test_original_capacity_to_repr() {
|
||||
for &cap in &[0, 1, 16, 1000] {
|
||||
assert_eq!(0, original_capacity_to_repr(cap));
|
||||
assert_eq!(original_capacity_to_repr(0), 0);
|
||||
|
||||
let max_width = 32;
|
||||
|
||||
for width in 1..(max_width + 1) {
|
||||
let cap = 1 << width - 1;
|
||||
|
||||
let expected = if width < MIN_ORIGINAL_CAPACITY_WIDTH {
|
||||
0
|
||||
} else if width < MAX_ORIGINAL_CAPACITY_WIDTH {
|
||||
width - MIN_ORIGINAL_CAPACITY_WIDTH
|
||||
} else {
|
||||
MAX_ORIGINAL_CAPACITY_WIDTH - MIN_ORIGINAL_CAPACITY_WIDTH
|
||||
};
|
||||
|
||||
assert_eq!(original_capacity_to_repr(cap), expected);
|
||||
|
||||
if width > 1 {
|
||||
assert_eq!(original_capacity_to_repr(cap + 1), expected);
|
||||
}
|
||||
|
||||
for &cap in &[1024, 1025, 1100, 2000, 2047] {
|
||||
assert_eq!(1, original_capacity_to_repr(cap));
|
||||
// MIN_ORIGINAL_CAPACITY_WIDTH must be bigger than 7 to pass tests below
|
||||
if width == MIN_ORIGINAL_CAPACITY_WIDTH + 1 {
|
||||
assert_eq!(original_capacity_to_repr(cap - 24), expected - 1);
|
||||
assert_eq!(original_capacity_to_repr(cap + 76), expected);
|
||||
} else if width == MIN_ORIGINAL_CAPACITY_WIDTH + 2 {
|
||||
assert_eq!(original_capacity_to_repr(cap - 1), expected - 1);
|
||||
assert_eq!(original_capacity_to_repr(cap - 48), expected - 1);
|
||||
}
|
||||
|
||||
for &cap in &[2048, 2049] {
|
||||
assert_eq!(2, original_capacity_to_repr(cap));
|
||||
}
|
||||
|
||||
// TODO: more
|
||||
|
||||
for &cap in &[65536, 65537, 68000, 1 << 17, 1 << 18, 1 << 20, 1 << 30] {
|
||||
assert_eq!(7, original_capacity_to_repr(cap), "cap={}", cap);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_original_capacity_from_repr() {
|
||||
assert_eq!(0, original_capacity_from_repr(0));
|
||||
assert_eq!(1024, original_capacity_from_repr(1));
|
||||
assert_eq!(1024 * 2, original_capacity_from_repr(2));
|
||||
assert_eq!(1024 * 4, original_capacity_from_repr(3));
|
||||
assert_eq!(1024 * 8, original_capacity_from_repr(4));
|
||||
assert_eq!(1024 * 16, original_capacity_from_repr(5));
|
||||
assert_eq!(1024 * 32, original_capacity_from_repr(6));
|
||||
assert_eq!(1024 * 64, original_capacity_from_repr(7));
|
||||
|
||||
let min_cap = 1 << MIN_ORIGINAL_CAPACITY_WIDTH;
|
||||
|
||||
assert_eq!(min_cap, original_capacity_from_repr(1));
|
||||
assert_eq!(min_cap * 2, original_capacity_from_repr(2));
|
||||
assert_eq!(min_cap * 4, original_capacity_from_repr(3));
|
||||
assert_eq!(min_cap * 8, original_capacity_from_repr(4));
|
||||
assert_eq!(min_cap * 16, original_capacity_from_repr(5));
|
||||
assert_eq!(min_cap * 32, original_capacity_from_repr(6));
|
||||
assert_eq!(min_cap * 64, original_capacity_from_repr(7));
|
||||
}
|
||||
|
||||
unsafe impl Send for Inner {}
|
|
@ -0,0 +1,89 @@
|
|||
extern crate either;
|
||||
|
||||
use {Buf, BufMut};
|
||||
|
||||
use self::either::Either;
|
||||
use self::either::Either::*;
|
||||
use iovec::IoVec;
|
||||
|
||||
impl<L, R> Buf for Either<L, R>
|
||||
where
|
||||
L: Buf,
|
||||
R: Buf,
|
||||
{
|
||||
fn remaining(&self) -> usize {
|
||||
match *self {
|
||||
Left(ref b) => b.remaining(),
|
||||
Right(ref b) => b.remaining(),
|
||||
}
|
||||
}
|
||||
|
||||
fn bytes(&self) -> &[u8] {
|
||||
match *self {
|
||||
Left(ref b) => b.bytes(),
|
||||
Right(ref b) => b.bytes(),
|
||||
}
|
||||
}
|
||||
|
||||
fn bytes_vec<'a>(&'a self, dst: &mut [&'a IoVec]) -> usize {
|
||||
match *self {
|
||||
Left(ref b) => b.bytes_vec(dst),
|
||||
Right(ref b) => b.bytes_vec(dst),
|
||||
}
|
||||
}
|
||||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
match *self {
|
||||
Left(ref mut b) => b.advance(cnt),
|
||||
Right(ref mut b) => b.advance(cnt),
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_to_slice(&mut self, dst: &mut [u8]) {
|
||||
match *self {
|
||||
Left(ref mut b) => b.copy_to_slice(dst),
|
||||
Right(ref mut b) => b.copy_to_slice(dst),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<L, R> BufMut for Either<L, R>
|
||||
where
|
||||
L: BufMut,
|
||||
R: BufMut,
|
||||
{
|
||||
fn remaining_mut(&self) -> usize {
|
||||
match *self {
|
||||
Left(ref b) => b.remaining_mut(),
|
||||
Right(ref b) => b.remaining_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn bytes_mut(&mut self) -> &mut [u8] {
|
||||
match *self {
|
||||
Left(ref mut b) => b.bytes_mut(),
|
||||
Right(ref mut b) => b.bytes_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn bytes_vec_mut<'a>(&'a mut self, dst: &mut [&'a mut IoVec]) -> usize {
|
||||
match *self {
|
||||
Left(ref mut b) => b.bytes_vec_mut(dst),
|
||||
Right(ref mut b) => b.bytes_vec_mut(dst),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn advance_mut(&mut self, cnt: usize) {
|
||||
match *self {
|
||||
Left(ref mut b) => b.advance_mut(cnt),
|
||||
Right(ref mut b) => b.advance_mut(cnt),
|
||||
}
|
||||
}
|
||||
|
||||
fn put_slice(&mut self, src: &[u8]) {
|
||||
match *self {
|
||||
Left(ref mut b) => b.put_slice(src),
|
||||
Right(ref mut b) => b.put_slice(src),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -69,7 +69,7 @@
|
|||
//! and `BufMut` are infallible.
|
||||
|
||||
#![deny(warnings, missing_docs, missing_debug_implementations)]
|
||||
#![doc(html_root_url = "https://docs.rs/bytes/0.4.9")]
|
||||
#![doc(html_root_url = "https://docs.rs/bytes/0.4.12")]
|
||||
|
||||
extern crate byteorder;
|
||||
extern crate iovec;
|
||||
|
@ -99,3 +99,7 @@ pub use byteorder::{ByteOrder, BigEndian, LittleEndian};
|
|||
#[cfg(feature = "serde")]
|
||||
#[doc(hidden)]
|
||||
pub mod serde;
|
||||
|
||||
// Optional `Either` support
|
||||
#[cfg(feature = "either")]
|
||||
mod either;
|
|
@ -717,3 +717,57 @@ fn from_iter_no_size_hint() {
|
|||
|
||||
assert_eq!(&actual[..], &expect[..]);
|
||||
}
|
||||
|
||||
fn test_slice_ref(bytes: &Bytes, start: usize, end: usize, expected: &[u8]) {
|
||||
let slice = &(bytes.as_ref()[start..end]);
|
||||
let sub = bytes.slice_ref(&slice);
|
||||
assert_eq!(&sub[..], expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slice_ref_works() {
|
||||
let bytes = Bytes::from(&b"012345678"[..]);
|
||||
|
||||
test_slice_ref(&bytes, 0, 0, b"");
|
||||
test_slice_ref(&bytes, 0, 3, b"012");
|
||||
test_slice_ref(&bytes, 2, 6, b"2345");
|
||||
test_slice_ref(&bytes, 7, 9, b"78");
|
||||
test_slice_ref(&bytes, 9, 9, b"");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn slice_ref_empty() {
|
||||
let bytes = Bytes::from(&b""[..]);
|
||||
let slice = &(bytes.as_ref()[0..0]);
|
||||
|
||||
let sub = bytes.slice_ref(&slice);
|
||||
assert_eq!(&sub[..], b"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn slice_ref_catches_not_a_subset() {
|
||||
let bytes = Bytes::from(&b"012345678"[..]);
|
||||
let slice = &b"012345"[0..4];
|
||||
|
||||
bytes.slice_ref(slice);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn slice_ref_catches_not_an_empty_subset() {
|
||||
let bytes = Bytes::from(&b"012345678"[..]);
|
||||
let slice = &b""[0..0];
|
||||
|
||||
bytes.slice_ref(slice);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn empty_slice_ref_catches_not_an_empty_subset() {
|
||||
let bytes = Bytes::from(&b""[..]);
|
||||
let slice = &b""[0..0];
|
||||
|
||||
bytes.slice_ref(slice);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
extern crate bytes;
|
||||
|
||||
use std::io::{BufRead, Cursor, Read};
|
||||
|
||||
use bytes::Buf;
|
||||
|
||||
#[test]
|
||||
fn read() {
|
||||
let buf1 = Cursor::new(b"hello ");
|
||||
let buf2 = Cursor::new(b"world");
|
||||
let buf = Buf::chain(buf1, buf2); // Disambiguate with Read::chain
|
||||
let mut buffer = Vec::new();
|
||||
buf.reader().read_to_end(&mut buffer).unwrap();
|
||||
assert_eq!(b"hello world", &buffer[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buf_read() {
|
||||
let buf1 = Cursor::new(b"hell");
|
||||
let buf2 = Cursor::new(b"o\nworld");
|
||||
let mut reader = Buf::chain(buf1, buf2).reader();
|
||||
let mut line = String::new();
|
||||
reader.read_line(&mut line).unwrap();
|
||||
assert_eq!("hello\n", &line);
|
||||
line.clear();
|
||||
reader.read_line(&mut line).unwrap();
|
||||
assert_eq!("world", &line);
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
{"files":{"CHANGELOG.md":"55941e30721c4b104cc8f84473da5acd0cd57903d66e8fd029b8c5160d99ed53","Cargo.toml":"f71e10b42ed8637ed615222f6d9e2af5df707f7f3d9d4fd203358c2af87b7ff0","LICENSE":"45f522cacecb1023856e46df79ca625dfc550c94910078bd8aec6e02880b3d42","README.md":"3ca600d7b4175eee634621a870904fe5ec761e6fd623f745423d378dec1bfd51","benches/bytes.rs":"a60889c35cf76faf2b403f94d3ab2831a569f2e1f6e4cc4d5e88f3c26bddb8b0","ci/before_deploy.ps1":"a8ee0204dd1397a245a47626fecd98eff5da76e12b15139c06271b3cc309a3e1","ci/before_deploy.sh":"ea008e2c544482cba5b659c17887ccd5354779c629096f28e667d40391299cc5","ci/install.sh":"8b165fc99df296261fcc9cdcbc8b8a177c11c505cdc9255cc19efb66cb0055db","ci/script.sh":"4e6f6b7df02d316ce5166a3526dc6bca6b6d051dbc5bd6d5b28a7c79fc646834","ci/tsan":"905d22267f7493550d123b1482fc1a7f4b24e8cbc4ae4f0e0c2d42383e79ad83","src/buf/buf.rs":"1b5ff3ab694380fe59588b8d195111ba663c5f8901b272b531851deb26e4629a","src/buf/buf_mut.rs":"d2f54e9c64b86c8ddd325d40b3c8e1b2132d361937bac3b5fccb7a81154b89b8","src/buf/chain.rs":"3a4f88879d27240e84e58bbeddf3f7c0958d0d81f4707245199b53e922029a26","src/buf/from_buf.rs":"949683c6a08099b280bd324d0c8646b1d6ff80af4d3e9397edb76cc2f1b18c88","src/buf/into_buf.rs":"b6e35d34533fae229f5209b95a39a1c35485f48a873a1d357d99218c486b0b95","src/buf/iter.rs":"325428e4f913beb602f6451b59847d4c8658ec23939a15f7b145733969c17f03","src/buf/mod.rs":"4f385ce47d6d19a064a1dbec3339e95e116aa9b501eb9d8a47030c2794e1ee9e","src/buf/reader.rs":"62098e87bd1aa8b7f57ed4a4d1b5417462f01ad2cfebfbac46b6ce7f00ea0192","src/buf/take.rs":"0bdd0720afc546c999e5a3125f20b6f31a5692b37f7218c25f414773e2702f3d","src/buf/writer.rs":"4a28c1d362e837682a4b3197732a6dbb4072dc660f0dbba18616679adf8a60f2","src/bytes.rs":"546f2ef082656be2639314994d4228833f331747578a9ebf69075d2bcec0ae2d","src/debug.rs":"a8bd8062e7e500fdc5a79cb6c848fb860be8359d95e1c91034777fe33c78d54e","src/lib.rs":"fb61bba13236978f2c3b93cc39eb4a99c02f1ecd539c917a8380e5d344e67706","src/serde.rs":"e8d0fe3630e173272756fb24a8c3ccb112f4cb551b8b88b64f669a71f39ef83b","tests/test_buf.rs":"6409f32f734969bebeffa7592fed531953d252c5a639e422b6e4b14ec024b1d5","tests/test_buf_mut.rs":"a6a653d5053340b0254900c33e36df6db1421f821c3e985be0044b1b447ecedc","tests/test_bytes.rs":"92ae28671dee4ab91c7e0366e094b009c547defd8fd1c977520e5ad574eea70d","tests/test_chain.rs":"3fe1f28f3bce4377f8ed506718f95f3ed3ebaf251a1cb43b2705331e3dd6b43a","tests/test_debug.rs":"4cfd44c30d0b8f7c5eb8e8916ad7436e9f538732fe9f4b696dc22b84c31ac64a","tests/test_from_buf.rs":"9bf743c77e69c643d0a7673426547dacaedbcc65028a26cf5864eb6714e4897a","tests/test_iter.rs":"bc8a5da0b3cc7e5a5dc37e91dd2a3ca3fc78ba74b087883473043be45cd9b265","tests/test_serde.rs":"98e0ab121153a7ead47538257ac7fc7d5db081fc35050552b5e5dc9500b414f9","tests/test_take.rs":"bb81822eec5d3774bd2626f0f29b543d3651f4f5a95c51dfe8f93dec8b4f8e94"},"package":"e178b8e0e239e844b083d5a0d4a156b2654e67f9f80144d48398fcd736a24fb8"}
|
|
@ -1,21 +0,0 @@
|
|||
# TSAN suppressions file for `bytes`
|
||||
|
||||
# TSAN does not understand fences and `Arc::drop` is implemented using a fence.
|
||||
# This causes many false positives.
|
||||
race:Arc*drop
|
||||
race:arc*Weak*drop
|
||||
|
||||
# `std` mpsc is not used in any Bytes code base. This race is triggered by some
|
||||
# rust runtime logic.
|
||||
race:std*mpsc_queue
|
||||
|
||||
# Not sure why this is warning, but it is in the test harness and not the library.
|
||||
race:TestEvent*clone
|
||||
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
|
|
@ -1 +1 @@
|
|||
{"files":{"CHANGELOG.md":"4faf2b723ed25868249363523d3506a939810e53877d7a68f72b705564e7200a","Cargo.toml":"52ab465c70fd369a72545d6fd12f5700edf6b741bfb26ef49076cd74770301a8","LICENSE":"45f522cacecb1023856e46df79ca625dfc550c94910078bd8aec6e02880b3d42","README.md":"c2aac235762c99395ae437e5f561d135a06e390a98f74baf80fb4c71dfb91ece","azure-pipelines.yml":"80098a973fbec019ae6da61ffe075047371ebb574acf4e726379628449a77016","benches/buf.rs":"7cfbe40095c70dfc42ebe1ed2cb59c84b557a89c09e8925842efd76be226bd12","benches/bytes.rs":"dd7a4c89e1bb1d7490d0532e19c50634c118bfbfd32d5b1c189b4f96fcce381e","benches/bytes_mut.rs":"e2510665597135634c96fcb85e11519a8cf0363d51460d87821229cf1745b16b","ci/azure-cross-compile.yml":"93d711ef0d66262f762624f82deb0b61afd69637e9a6cfe38d18ad84cd09781d","ci/azure-deploy-docs.yml":"fce86e75cb8bc61aca7513cd6afa5ebe0fff8963beda7d6775e341945bec7eb2","ci/azure-install-rust.yml":"898f3dd92859375bdc14b7449a9da56860936d0e77e9de5d2505663d22abd95e","ci/azure-loom.yml":"c1e8782e855b27d26c022bcf2b34239ed5b0a7de2802de68fd7140566e175317","ci/azure-test-stable.yml":"e8a264a813f17b62db1ca1c7e34ba1842a87cdc5ad4a591c1643af0a8a4057f6","ci/azure-tsan.yml":"3996de625bf276ee16cc815809a3c312d5e9fe62424c38d2e1bc97614caf7df3","ci/tsan":"5194270c4e37b1a72e890c98eb2a4aae5f5506fb26a67af3d2834360d2e3d3c2","src/buf/buf_impl.rs":"d921c3171094f824bba4ec3bd69f07ce47257af257741a3cb0ff96887f5f5bd0","src/buf/buf_mut.rs":"289a9348aa2788e0cc12419d311c89c0e87a5e84d62bd8cd71f045924eb0349f","src/buf/ext/chain.rs":"d526cd39d870b7ae8c08e3bd2bc9e7770e9d014b9d9360246dd42c236b6400db","src/buf/ext/limit.rs":"99a42933ac6e309ee5b87818f9560ff041a3e388e8cef18b78ccfd00e3c5eec9","src/buf/ext/mod.rs":"aa2b370a4b44cd7c56ef7c5b07bdaf3723efe3cc465cef358df56433881503b3","src/buf/ext/reader.rs":"d48f07cb1ae0404a224162509fd356eb217b5f8ab020403467491445631616b1","src/buf/ext/take.rs":"fa1009c96175fc67a66f5a8d013140fed7cf0199fefe49bcd4ace82b7a82741b","src/buf/ext/writer.rs":"f01022d4589cee78e36c96032d01e68b6d559062d549e35132a3af869099a2d0","src/buf/iter.rs":"6de36052c0f428d912cea4055fd5c027038f70d369e881e42b6ada6aa9ea92c2","src/buf/mod.rs":"4f66903ca61fe88513c23664a4f33f26c00e4218fbc607e7f52981ba66b90456","src/buf/vec_deque.rs":"5a4063961d10380c1ab3681f8b3f6201112766d9f57a63e2861dc9f2b134668d","src/bytes.rs":"5af1de291faa0344fd7ebf6c1a5834f04aa9f9a7f1b405c8173c31819dd27ca2","src/bytes_mut.rs":"28af39ed6576df6be1c0e57d526ba4f7dd9d50d0d7b0767a3da54940f9fb3417","src/debug.rs":"0875de8307c223bce68e861bc78917e0ad7ef00d75966c0151a0b1aa83a6521a","src/hex.rs":"39c8ee531a45a25b8ef085b4279a9ba7f3b488e4d36c4f80d8769e04b1e51bfd","src/lib.rs":"7fedc5dee1f1d6968ccdccc84514003b1293a22a4b712b4557b49fa57d0752b2","src/loom.rs":"70263b3847d1e4960450a64cb34a87947eaa73755b45977d151265c13ebe4598","src/serde.rs":"c42e0644bed431852445433ac0d6e46f04891e40c046456350323dd3f7b8cf1c","tests/test_buf.rs":"dd3a83218bf5bcc277a8aa1c59c7ed6deeb7e752252b01bce5be4219e65a3e4f","tests/test_buf_mut.rs":"de50fcb03c984f299a84131829b72e351263541c592eec2c23e7ff4504c8e376","tests/test_bytes.rs":"a3b429df530ad90d450d236e893705b218b0319d61b074e9445715df56a15416","tests/test_chain.rs":"d3dab042b20b35e865af1101d78db002878a6604a0a4f4b7901bb1ee98f60684","tests/test_debug.rs":"5b425e056a32d0319d1857b54c88cf58952397bda6fee26b39c624d6c1444eee","tests/test_iter.rs":"95c531b984bcd9b60222b31558925f9662a38b409e731e4aaaafa904b1a64896","tests/test_reader.rs":"1b782d370c757dac14d59df1c4432a25fd8209cbe31b07fa4c380f5b82eec409","tests/test_serde.rs":"2cd4426bfa3a886745dd6958aab21c3493d1116b961acbbf35ec2866c2168a52","tests/test_take.rs":"998d16facf37fa0b2358e7aa42380279d4466d8dde2a3f8c1ae8a082bb37b180"},"package":"10004c15deb332055f7a4a208190aed362cf9a7c2f6ab70a305fba50e1105f38"}
|
||||
{"files":{"CHANGELOG.md":"7c1c6fe9fa6aa8a155d4a04dab5d4e3abadb349121886b2f24252db0e45fba51","Cargo.toml":"bb5072cd9bad83919ed35f49f3a7f88b608a0150d6ccdcbb4bf17dfb3c64ef3f","LICENSE":"45f522cacecb1023856e46df79ca625dfc550c94910078bd8aec6e02880b3d42","README.md":"2c2f6f1a240ad375f9dbd8e7f023510b645d98e327ea0a42ba339c94fd9baaa9","benches/buf.rs":"b0f4f1130081680f6f99d1efd49a75bd1d97d9a30117b7ad9525c96b7c8968e6","benches/bytes.rs":"dc5289a9ce82be35e71ed5853ab33aa108a30460e481135f6058fe4d2f7dc15e","benches/bytes_mut.rs":"1326fe6224b26826228e02b4133151e756f38152c2d9cfe66adf83af76c3ec98","ci/test-stable.sh":"6e010f1a95b72fea7bebdd217fda78427f3eb07b1e753f79507c71d982b2d38a","ci/tsan.sh":"466b86b19225dd26c756cf2252cb1973f87a145642c99364b462ed7ceb55c7dd","src/buf/buf_impl.rs":"fe1bc64bb9aef5b57d83901268f89bf148490e71bebc340c7ecc40ff95bcfb70","src/buf/buf_mut.rs":"d226189d9db76c9023537dcca0687aa5dd25851a9052d19154de8ee9b25bdee3","src/buf/ext/chain.rs":"337f58e1a8da5b4768e55921ff394f4ba3a0c6d476448fd5bceab6f3c1db1b3e","src/buf/ext/limit.rs":"a705d7cf38f9a11a904d6ee5e7afea83e9abdf8f454bb8e16b407b0e055dc11a","src/buf/ext/mod.rs":"ba2fa392c61b7429530c71797114e3f09d9b6b750b6f77f57fde964d2b218bc4","src/buf/ext/reader.rs":"ee4733fa2c2d893c6df8151c2333a46171619e8a45ec9bae863edc8deb438ac5","src/buf/ext/take.rs":"e92be765539b8b0c1cb67a01b691319cccd35fc098f2bb59ced3bbbe41ee0257","src/buf/ext/writer.rs":"3c52df6e73d09935d37bed9a05689c1966952f980b85b40aaab05081ec7ef6d8","src/buf/iter.rs":"a0de69367fa61d0d1c6c2ff4b4d337de9c5f4213d0c86e083226cf409666d860","src/buf/mod.rs":"4f8e3b4c4b69b7d004306d458ad835801e53659b38ca08312d7217d82da4c64f","src/buf/vec_deque.rs":"5a4063961d10380c1ab3681f8b3f6201112766d9f57a63e2861dc9f2b134668d","src/bytes.rs":"8c3aa5fe425604206ffc1b85a8bff5a9be38917786453450955984523f829cec","src/bytes_mut.rs":"e276f74da841ab65ca681cb09820de98aa2e9837dd975ed564b1a9be40440cf3","src/fmt/debug.rs":"19ebe7e5516e40ab712995f3ec2e0ba78ddfa905cce117e6d01e8eb330f3970a","src/fmt/hex.rs":"13755ec6f1b79923e1f1a05c51b179a38c03c40bb8ed2db0210e8901812e61e7","src/fmt/mod.rs":"176da4e359da99b8e5cf16e480cb7b978f574876827f1b9bb9c08da4d74ac0f5","src/lib.rs":"9b96e2a011a782ceb82428e6b71fd212a46bc186bd152102018c7b6428a0d441","src/loom.rs":"5dc97a5afce14875a66e44cbf0afa67e084c8b6b8c560bc14e7a70ef73aee96e","src/serde.rs":"3ecd7e828cd4c2b7db93c807cb1548fad209e674df493edf7cda69a7b04d405d","tests/test_buf.rs":"3ca99c58f470e7c4beb18e5dc69250ce541dd8ac96b88fb1162640510a735ada","tests/test_buf_mut.rs":"56636e439cb07af2fabdfb60a08995829680c9730a8ebe5c6ad2f54dbf208e32","tests/test_bytes.rs":"3ec0a82ce98fea633ed7d635caca21cd8035d0c9ea4287d1cc0199e167a4a3c1","tests/test_bytes_odd_alloc.rs":"87d51d4ab6ad98193b140ea8158f6631eba985a204c2ea94d34b3bb157791a16","tests/test_bytes_vec_alloc.rs":"2b686b6ab44f924e69d8270a4f256eb3626a3b4db8c1919b74bc422c10124899","tests/test_chain.rs":"71772fbc0bab72a697bd85c6c1be0eddfe7d7dc4f4737a0cd53be4ad191d076b","tests/test_debug.rs":"13299107172809e8cbbd823964ac9450cd0d6b6de79f2e6a2e0f44b9225a0593","tests/test_iter.rs":"c1f46823df26a90139645fd8728a03138edd95b2849dfec830452a80ddd9726d","tests/test_reader.rs":"9c94e164aa7de4c10966f8084ad04d06f4e9c66e156d017d194a1dac3dfc6619","tests/test_serde.rs":"2691f891796ba259de0ecf926de05c514f4912cc5fcd3e6a1591efbcd23ed4d0","tests/test_take.rs":"975aa2e216b6a3c939b31e41ecfbb3a90938096413a14a2ae986c842d2250180"},"package":"0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"}
|
|
@ -1,3 +1,31 @@
|
|||
# 0.5.6 (July 13, 2020)
|
||||
|
||||
- Improve `BytesMut` to reuse buffer when fully `advance`d.
|
||||
- Mark `BytesMut::{as_mut, set_len}` with `#[inline]`.
|
||||
- Relax synchronization when cloning in shared vtable of `Bytes`.
|
||||
- Move `loom` to `dev-dependencies`.
|
||||
|
||||
# 0.5.5 (June 18, 2020)
|
||||
|
||||
### Added
|
||||
- Allow using the `serde` feature in `no_std` environments (#385).
|
||||
|
||||
### Fix
|
||||
- Fix `BufMut::advance_mut` to panic if advanced passed the capacity (#354)..
|
||||
- Fix `BytesMut::freeze` ignoring amount previously `advance`d (#352).
|
||||
|
||||
# 0.5.4 (January 23, 2020)
|
||||
|
||||
### Added
|
||||
- Make `Bytes::new` a `const fn`.
|
||||
- Add `From<BytesMut>` for `Bytes`.
|
||||
|
||||
### Fix
|
||||
- Fix reversed arguments in `PartialOrd` for `Bytes`.
|
||||
- Fix `Bytes::truncate` losing original capacity when repr is an unshared `Vec`.
|
||||
- Fix `Bytes::from(Vec)` when allocator gave `Vec` a pointer with LSB set.
|
||||
- Fix panic in `Bytes::slice_ref` if argument is an empty slice.
|
||||
|
||||
# 0.5.3 (December 12, 2019)
|
||||
|
||||
### Added
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
[package]
|
||||
edition = "2018"
|
||||
name = "bytes"
|
||||
version = "0.5.3"
|
||||
version = "0.5.6"
|
||||
authors = ["Carl Lerche <me@carllerche.com>", "Sean McArthur <sean@seanmonstar.com>"]
|
||||
description = "Types and traits for working with bytes"
|
||||
documentation = "https://docs.rs/bytes"
|
||||
|
@ -23,14 +23,15 @@ categories = ["network-programming", "data-structures"]
|
|||
license = "MIT"
|
||||
repository = "https://github.com/tokio-rs/bytes"
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
version = "1.0.60"
|
||||
features = ["alloc"]
|
||||
optional = true
|
||||
[dev-dependencies.loom]
|
||||
version = "0.2.10"
|
||||
|
||||
default-features = false
|
||||
[dev-dependencies.serde_test]
|
||||
version = "1.0"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = []
|
||||
[target."cfg(loom)".dev-dependencies.loom]
|
||||
version = "0.3"
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
A utility library for working with bytes.
|
||||
|
||||
[![Crates.io][crates-badge]][crates-url]
|
||||
[![Build Status][azure-badge]][azure-url]
|
||||
[![Build Status][ci-badge]][ci-url]
|
||||
|
||||
[crates-badge]: https://img.shields.io/crates/v/bytes.svg
|
||||
[crates-url]: https://crates.io/crates/bytes
|
||||
[azure-badge]: https://dev.azure.com/tokio-rs/bytes/_apis/build/status/tokio-rs.bytes?branchName=master
|
||||
[azure-url]: https://dev.azure.com/tokio-rs/bytes/_build/latest?definitionId=3&branchName=master
|
||||
[ci-badge]: https://github.com/tokio-rs/bytes/workflows/CI/badge.svg
|
||||
[ci-url]: https://github.com/tokio-rs/bytes/actions
|
||||
|
||||
[Documentation](https://docs.rs/bytes)
|
||||
|
||||
|
@ -45,4 +45,3 @@ This project is licensed under the [MIT license](LICENSE).
|
|||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in `bytes` by you, shall be licensed as MIT, without any additional
|
||||
terms or conditions.
|
||||
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
trigger: ["master"]
|
||||
pr: ["master"]
|
||||
|
||||
jobs:
|
||||
# Check formatting
|
||||
# - template: ci/azure-rustfmt.yml
|
||||
# parameters:
|
||||
# name: rustfmt
|
||||
|
||||
# Apply clippy lints
|
||||
# - template: ci/azure-clippy.yml
|
||||
# parameters:
|
||||
# name: clippy
|
||||
|
||||
# This represents the minimum Rust version supported by
|
||||
# Bytes. Updating this should be done in a dedicated PR.
|
||||
#
|
||||
# Tests are not run as tests may require newer versions of
|
||||
# rust.
|
||||
- template: ci/azure-test-stable.yml
|
||||
parameters:
|
||||
name: minrust
|
||||
rust_version: 1.39.0
|
||||
cmd: check
|
||||
|
||||
# Stable
|
||||
- template: ci/azure-test-stable.yml
|
||||
parameters:
|
||||
name: stable
|
||||
cross: true
|
||||
features:
|
||||
- serde
|
||||
|
||||
# Nightly
|
||||
- template: ci/azure-test-stable.yml
|
||||
parameters:
|
||||
name: nightly
|
||||
# Pin nightly to avoid being impacted by breakage
|
||||
rust_version: nightly-2019-09-25
|
||||
benches: true
|
||||
|
||||
# Run tests on some extra platforms
|
||||
- template: ci/azure-cross-compile.yml
|
||||
parameters:
|
||||
name: cross
|
||||
|
||||
# Sanitizers
|
||||
- template: ci/azure-tsan.yml
|
||||
parameters:
|
||||
name: tsan
|
||||
rust_version: nightly
|
||||
|
||||
# Loom
|
||||
- template: ci/azure-loom.yml
|
||||
parameters:
|
||||
name: loom
|
||||
rust_version: stable
|
||||
|
||||
|
||||
- template: ci/azure-deploy-docs.yml
|
||||
parameters:
|
||||
dependsOn:
|
||||
# - rustfmt
|
||||
# - clippy
|
||||
- stable
|
||||
- nightly
|
||||
- minrust
|
||||
- cross
|
|
@ -1,10 +1,10 @@
|
|||
#![feature(test)]
|
||||
#![deny(warnings, rust_2018_idioms)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use test::Bencher;
|
||||
use bytes::Buf;
|
||||
use test::Bencher;
|
||||
|
||||
/// Dummy Buf implementation
|
||||
struct TestBuf {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#![feature(test)]
|
||||
#![deny(warnings, rust_2018_idioms)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use test::Bencher;
|
||||
use bytes::Bytes;
|
||||
use test::Bencher;
|
||||
|
||||
#[bench]
|
||||
fn deref_unique(b: &mut Bencher) {
|
||||
|
@ -42,7 +42,8 @@ fn deref_static(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn clone_static(b: &mut Bencher) {
|
||||
let bytes = Bytes::from_static("hello world 1234567890 and have a good byte 0987654321".as_bytes());
|
||||
let bytes =
|
||||
Bytes::from_static("hello world 1234567890 and have a good byte 0987654321".as_bytes());
|
||||
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#![feature(test)]
|
||||
#![deny(warnings, rust_2018_idioms)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use test::Bencher;
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use test::Bencher;
|
||||
|
||||
#[bench]
|
||||
fn alloc_small(b: &mut Bencher) {
|
||||
|
@ -29,7 +29,6 @@ fn alloc_big(b: &mut Bencher) {
|
|||
})
|
||||
}
|
||||
|
||||
|
||||
#[bench]
|
||||
fn deref_unique(b: &mut Bencher) {
|
||||
let mut buf = BytesMut::with_capacity(4096);
|
||||
|
@ -92,7 +91,9 @@ fn deref_two(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn clone_frozen(b: &mut Bencher) {
|
||||
let bytes = BytesMut::from(&b"hello world 1234567890 and have a good byte 0987654321"[..]).split().freeze();
|
||||
let bytes = BytesMut::from(&b"hello world 1234567890 and have a good byte 0987654321"[..])
|
||||
.split()
|
||||
.freeze();
|
||||
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
|
@ -137,7 +138,9 @@ fn fmt_write(b: &mut Bencher) {
|
|||
b.iter(|| {
|
||||
let _ = write!(buf, "{}", s);
|
||||
test::black_box(&buf);
|
||||
unsafe { buf.set_len(0); }
|
||||
unsafe {
|
||||
buf.set_len(0);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -152,7 +155,9 @@ fn bytes_mut_extend(b: &mut Bencher) {
|
|||
buf.extend(&data);
|
||||
}
|
||||
test::black_box(&buf);
|
||||
unsafe { buf.set_len(0); }
|
||||
unsafe {
|
||||
buf.set_len(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -169,7 +174,9 @@ fn put_slice_bytes_mut(b: &mut Bencher) {
|
|||
buf.put_slice(&data);
|
||||
}
|
||||
test::black_box(&buf);
|
||||
unsafe { buf.set_len(0); }
|
||||
unsafe {
|
||||
buf.set_len(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -184,7 +191,9 @@ fn put_u8_bytes_mut(b: &mut Bencher) {
|
|||
buf.put_u8(b'x');
|
||||
}
|
||||
test::black_box(&buf);
|
||||
unsafe { buf.set_len(0); }
|
||||
unsafe {
|
||||
buf.set_len(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -199,7 +208,9 @@ fn put_slice_vec(b: &mut Bencher) {
|
|||
buf.put_slice(&data);
|
||||
}
|
||||
test::black_box(&buf);
|
||||
unsafe { buf.set_len(0); }
|
||||
unsafe {
|
||||
buf.set_len(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -214,7 +225,9 @@ fn put_u8_vec(b: &mut Bencher) {
|
|||
buf.put_u8(b'x');
|
||||
}
|
||||
test::black_box(&buf);
|
||||
unsafe { buf.set_len(0); }
|
||||
unsafe {
|
||||
buf.set_len(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -229,7 +242,9 @@ fn put_slice_vec_extend(b: &mut Bencher) {
|
|||
buf.extend_from_slice(&data);
|
||||
}
|
||||
test::black_box(&buf);
|
||||
unsafe { buf.set_len(0); }
|
||||
unsafe {
|
||||
buf.set_len(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -244,6 +259,8 @@ fn put_u8_vec_push(b: &mut Bencher) {
|
|||
buf.push(b'x');
|
||||
}
|
||||
test::black_box(&buf);
|
||||
unsafe { buf.set_len(0); }
|
||||
unsafe {
|
||||
buf.set_len(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
parameters:
|
||||
cmd: build
|
||||
rust_version: stable
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.name }}
|
||||
displayName: Cross
|
||||
strategy:
|
||||
matrix:
|
||||
i686:
|
||||
vmImage: ubuntu-16.04
|
||||
target: i686-unknown-linux-gnu
|
||||
armv7:
|
||||
vmImage: ubuntu-16.04
|
||||
target: armv7-unknown-linux-gnueabihf
|
||||
powerpc:
|
||||
vmImage: ubuntu-16.04
|
||||
target: powerpc-unknown-linux-gnu
|
||||
powerpc64:
|
||||
vmImage: ubuntu-16.04
|
||||
target: powerpc64-unknown-linux-gnu
|
||||
wasm:
|
||||
vmImage: ubuntu-16.04
|
||||
target: wasm32-unknown-unknown
|
||||
pool:
|
||||
vmImage: $(vmImage)
|
||||
|
||||
steps:
|
||||
- template: azure-install-rust.yml
|
||||
parameters:
|
||||
rust_version: ${{parameters.rust_version}}
|
||||
|
||||
- script: cargo install cross
|
||||
displayName: Install cross
|
||||
condition: not(eq(variables['target'], 'wasm32-unknown-unknown'))
|
||||
|
||||
- script: cross ${{ parameters.cmd }} --target $(target)
|
||||
displayName: cross ${{ parameters.cmd }} --target $(target)
|
||||
condition: not(eq(variables['target'], 'wasm32-unknown-unknown'))
|
||||
|
||||
# WASM support
|
||||
- script: |
|
||||
rustup target add $(target)
|
||||
cargo build --target $(target)
|
||||
displayName: cargo build --target $(target)
|
||||
condition: eq(variables['target'], 'wasm32-unknown-unknown')
|
|
@ -1,39 +0,0 @@
|
|||
parameters:
|
||||
dependsOn: []
|
||||
|
||||
jobs:
|
||||
- job: documentation
|
||||
displayName: 'Deploy API Documentation'
|
||||
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
dependsOn:
|
||||
- ${{ parameters.dependsOn }}
|
||||
steps:
|
||||
- template: azure-install-rust.yml
|
||||
parameters:
|
||||
rust_version: stable
|
||||
- script: |
|
||||
cargo doc --no-deps
|
||||
cp -R target/doc '$(Build.BinariesDirectory)'
|
||||
displayName: 'Generate Documentation'
|
||||
- script: |
|
||||
set -e
|
||||
|
||||
git --version
|
||||
ls -la
|
||||
git init
|
||||
git config user.name 'Deployment Bot (from Azure Pipelines)'
|
||||
git config user.email 'deploy@tokio-rs.com'
|
||||
git config --global credential.helper 'store --file ~/.my-credentials'
|
||||
printf "protocol=https\nhost=github.com\nusername=carllerche\npassword=%s\n\n" "$GITHUB_TOKEN" | git credential-store --file ~/.my-credentials store
|
||||
git remote add origin https://github.com/tokio-rs/bytes
|
||||
git checkout -b gh-pages
|
||||
git add .
|
||||
git commit -m 'Deploy Bytes API documentation'
|
||||
git push -f origin gh-pages
|
||||
env:
|
||||
GITHUB_TOKEN: $(githubPersonalToken)
|
||||
workingDirectory: '$(Build.BinariesDirectory)'
|
||||
displayName: 'Deploy Documentation'
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
steps:
|
||||
# Linux and macOS.
|
||||
- script: |
|
||||
set -e
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
|
||||
export PATH=$PATH:$HOME/.cargo/bin
|
||||
rustup toolchain install $RUSTUP_TOOLCHAIN
|
||||
rustup default $RUSTUP_TOOLCHAIN
|
||||
echo "##vso[task.setvariable variable=PATH;]$PATH:$HOME/.cargo/bin"
|
||||
env:
|
||||
RUSTUP_TOOLCHAIN: ${{parameters.rust_version}}
|
||||
displayName: "Install rust (*nix)"
|
||||
condition: not(eq(variables['Agent.OS'], 'Windows_NT'))
|
||||
|
||||
# Windows.
|
||||
- script: |
|
||||
curl -sSf -o rustup-init.exe https://win.rustup.rs
|
||||
rustup-init.exe -y --default-toolchain none
|
||||
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
|
||||
rustup toolchain install %RUSTUP_TOOLCHAIN%
|
||||
rustup default %RUSTUP_TOOLCHAIN%
|
||||
echo "##vso[task.setvariable variable=PATH;]%PATH%;%USERPROFILE%\.cargo\bin"
|
||||
env:
|
||||
RUSTUP_TOOLCHAIN: ${{parameters.rust_version}}
|
||||
displayName: "Install rust (windows)"
|
||||
condition: eq(variables['Agent.OS'], 'Windows_NT')
|
||||
|
||||
# All platforms.
|
||||
- script: |
|
||||
rustup toolchain list
|
||||
rustc -Vv
|
||||
cargo -V
|
||||
displayName: Query rust and cargo versions
|
|
@ -1,15 +0,0 @@
|
|||
jobs:
|
||||
- job: ${{parameters.name}}
|
||||
displayName: Loom tests
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
|
||||
steps:
|
||||
- template: azure-install-rust.yml
|
||||
parameters:
|
||||
rust_version: ${{parameters.rust_version}}
|
||||
|
||||
- script: RUSTFLAGS="--cfg loom" cargo test --lib
|
||||
displayName: RUSTFLAGS="--cfg loom" cargo test --lib
|
||||
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
parameters:
|
||||
cmd: test
|
||||
rust_version: stable
|
||||
features: []
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.name }}
|
||||
displayName: ${{ parameters.displayName }}
|
||||
strategy:
|
||||
matrix:
|
||||
Linux:
|
||||
vmImage: ubuntu-16.04
|
||||
|
||||
${{ if parameters.cross }}:
|
||||
MacOS:
|
||||
vmImage: macOS-10.13
|
||||
Windows:
|
||||
vmImage: vs2017-win2016
|
||||
pool:
|
||||
vmImage: $(vmImage)
|
||||
|
||||
steps:
|
||||
- template: azure-install-rust.yml
|
||||
parameters:
|
||||
rust_version: ${{parameters.rust_version}}
|
||||
|
||||
# Run with default crate features
|
||||
- script: cargo ${{ parameters.cmd }}
|
||||
displayName: cargo ${{ parameters.cmd }}
|
||||
|
||||
# Run with each specified feature
|
||||
- ${{ each feature in parameters.features }}:
|
||||
- script: cargo ${{ parameters.cmd }} --features ${{ feature }}
|
||||
displayName: cargo ${{ parameters.cmd }} --features ${{ feature }}
|
||||
|
||||
- ${{ if eq(parameters.cmd, 'test') }}:
|
||||
- script: cargo doc --no-deps
|
||||
displayName: cargo doc --no-deps
|
||||
|
||||
- ${{ if parameters.benches }}:
|
||||
- script: cargo check --benches
|
||||
displayName: Check benchmarks
|
||||
|
||||
# Run with all features
|
||||
- script: cargo ${{ parameters.cmd }} --all-features
|
||||
displayName: cargo ${{ parameters.cmd }} --all-features
|
||||
|
||||
# Run with no default features
|
||||
- script: cargo check --no-default-features
|
||||
displayName: cargo check --no-default-features
|
|
@ -1,26 +0,0 @@
|
|||
jobs:
|
||||
- job: ${{ parameters.name }}
|
||||
displayName: TSAN
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
|
||||
steps:
|
||||
- template: azure-install-rust.yml
|
||||
parameters:
|
||||
rust_version: ${{ parameters.rust_version }}
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
|
||||
export RUST_TEST_THREADS=1
|
||||
export ASAN_OPTIONS="detect_odr_violation=0 detect_leaks=0"
|
||||
export TSAN_OPTIONS="suppressions=`pwd`/ci/tsan"
|
||||
|
||||
# Run address sanitizer
|
||||
RUSTFLAGS="-Z sanitizer=address" \
|
||||
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 --target x86_64-unknown-linux-gnu --test test_bytes --test test_buf --test test_buf_mut
|
||||
displayName: TSAN / MSAN
|
|
@ -0,0 +1,27 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
cmd="${1:-test}"
|
||||
|
||||
# Install cargo-hack for feature flag test
|
||||
cargo install cargo-hack
|
||||
|
||||
# Run with each feature
|
||||
# * --each-feature includes both default/no-default features
|
||||
# * --optional-deps is needed for serde feature
|
||||
cargo hack "${cmd}" --each-feature --optional-deps
|
||||
# Run with all features
|
||||
cargo "${cmd}" --all-features
|
||||
|
||||
cargo doc --no-deps --all-features
|
||||
|
||||
if [[ "${RUST_VERSION}" == "nightly"* ]]; then
|
||||
# Check benchmarks
|
||||
cargo check --benches
|
||||
|
||||
# Check minimal versions
|
||||
cargo clean
|
||||
cargo update -Zminimal-versions
|
||||
cargo check --all-features
|
||||
fi
|
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
export ASAN_OPTIONS="detect_odr_violation=0 detect_leaks=0"
|
||||
|
||||
# Run address sanitizer
|
||||
RUSTFLAGS="-Z sanitizer=address" \
|
||||
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 -Zbuild-std test --target x86_64-unknown-linux-gnu --test test_bytes --test test_buf --test test_buf_mut
|
|
@ -1,19 +1,20 @@
|
|||
use core::{cmp, ptr, mem};
|
||||
use core::{cmp, mem, ptr};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::io::IoSlice;
|
||||
|
||||
use alloc::{boxed::Box};
|
||||
use alloc::boxed::Box;
|
||||
|
||||
macro_rules! buf_get_impl {
|
||||
($this:ident, $typ:tt::$conv:tt) => ({
|
||||
($this:ident, $typ:tt::$conv:tt) => {{
|
||||
const SIZE: usize = mem::size_of::<$typ>();
|
||||
// try to convert directly from the bytes
|
||||
// this Option<ret> trick is to avoid keeping a borrow on self
|
||||
// when advance() is called (mut borrow) and to call bytes() only once
|
||||
let ret = $this.bytes().get(..SIZE).map(|src| unsafe {
|
||||
$typ::$conv(*(src as *const _ as *const [_; SIZE]))
|
||||
});
|
||||
let ret = $this
|
||||
.bytes()
|
||||
.get(..SIZE)
|
||||
.map(|src| unsafe { $typ::$conv(*(src as *const _ as *const [_; SIZE])) });
|
||||
|
||||
if let Some(ret) = ret {
|
||||
// if the direct conversion was possible, advance and return
|
||||
|
@ -25,8 +26,8 @@ macro_rules! buf_get_impl {
|
|||
$this.copy_to_slice(&mut buf); // (do the advance)
|
||||
return $typ::$conv(buf);
|
||||
}
|
||||
});
|
||||
(le => $this:ident, $typ:tt, $len_to_read:expr) => ({
|
||||
}};
|
||||
(le => $this:ident, $typ:tt, $len_to_read:expr) => {{
|
||||
debug_assert!(mem::size_of::<$typ>() >= $len_to_read);
|
||||
|
||||
// The same trick as above does not improve the best case speed.
|
||||
|
@ -34,12 +35,12 @@ macro_rules! buf_get_impl {
|
|||
let mut buf = [0; (mem::size_of::<$typ>())];
|
||||
$this.copy_to_slice(&mut buf[..($len_to_read)]);
|
||||
return $typ::from_le_bytes(buf);
|
||||
});
|
||||
}};
|
||||
(be => $this:ident, $typ:tt, $len_to_read:expr) => {{
|
||||
debug_assert!(mem::size_of::<$typ>() >= $len_to_read);
|
||||
|
||||
let mut buf = [0; (mem::size_of::<$typ>())];
|
||||
$this.copy_to_slice(&mut buf[mem::size_of::<$typ>()-($len_to_read)..]);
|
||||
$this.copy_to_slice(&mut buf[mem::size_of::<$typ>() - ($len_to_read)..]);
|
||||
return $typ::from_be_bytes(buf);
|
||||
}};
|
||||
}
|
||||
|
@ -251,8 +252,7 @@ pub trait Buf {
|
|||
let src = self.bytes();
|
||||
cnt = cmp::min(src.len(), dst.len() - off);
|
||||
|
||||
ptr::copy_nonoverlapping(
|
||||
src.as_ptr(), dst[off..].as_mut_ptr(), cnt);
|
||||
ptr::copy_nonoverlapping(src.as_ptr(), dst[off..].as_mut_ptr(), cnt);
|
||||
|
||||
off += cnt;
|
||||
}
|
||||
|
@ -810,7 +810,7 @@ pub trait Buf {
|
|||
}
|
||||
|
||||
macro_rules! deref_forward_buf {
|
||||
() => (
|
||||
() => {
|
||||
fn remaining(&self) -> usize {
|
||||
(**self).remaining()
|
||||
}
|
||||
|
@ -911,8 +911,7 @@ macro_rules! deref_forward_buf {
|
|||
fn to_bytes(&mut self) -> crate::Bytes {
|
||||
(**self).to_bytes()
|
||||
}
|
||||
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
impl<T: Buf + ?Sized> Buf for &mut T {
|
||||
|
@ -950,7 +949,8 @@ impl Buf for Option<[u8; 1]> {
|
|||
}
|
||||
|
||||
fn bytes(&self) -> &[u8] {
|
||||
self.as_ref().map(AsRef::as_ref)
|
||||
self.as_ref()
|
||||
.map(AsRef::as_ref)
|
||||
.unwrap_or(Default::default())
|
||||
}
|
||||
|
||||
|
@ -994,7 +994,8 @@ impl<T: AsRef<[u8]>> Buf for std::io::Cursor<T> {
|
|||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
let pos = (self.position() as usize)
|
||||
.checked_add(cnt).expect("overflow");
|
||||
.checked_add(cnt)
|
||||
.expect("overflow");
|
||||
|
||||
assert!(pos <= self.get_ref().as_ref().len());
|
||||
self.set_position(pos as u64);
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
use core::{cmp, mem::{self, MaybeUninit}, ptr, usize};
|
||||
use core::{
|
||||
cmp,
|
||||
mem::{self, MaybeUninit},
|
||||
ptr, usize,
|
||||
};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::fmt;
|
||||
|
||||
use alloc::{vec::Vec, boxed::Box};
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
|
||||
/// A trait for values that provide sequential write access to bytes.
|
||||
///
|
||||
|
@ -226,7 +230,10 @@ pub trait BufMut {
|
|||
/// # Panics
|
||||
///
|
||||
/// Panics if `self` does not have enough capacity to contain `src`.
|
||||
fn put<T: super::Buf>(&mut self, mut src: T) where Self: Sized {
|
||||
fn put<T: super::Buf>(&mut self, mut src: T)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
assert!(self.remaining_mut() >= src.remaining());
|
||||
|
||||
while src.has_remaining() {
|
||||
|
@ -237,14 +244,13 @@ pub trait BufMut {
|
|||
let d = self.bytes_mut();
|
||||
l = cmp::min(s.len(), d.len());
|
||||
|
||||
ptr::copy_nonoverlapping(
|
||||
s.as_ptr(),
|
||||
d.as_mut_ptr() as *mut u8,
|
||||
l);
|
||||
ptr::copy_nonoverlapping(s.as_ptr(), d.as_mut_ptr() as *mut u8, l);
|
||||
}
|
||||
|
||||
src.advance(l);
|
||||
unsafe { self.advance_mut(l); }
|
||||
unsafe {
|
||||
self.advance_mut(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -270,7 +276,12 @@ pub trait BufMut {
|
|||
fn put_slice(&mut self, src: &[u8]) {
|
||||
let mut off = 0;
|
||||
|
||||
assert!(self.remaining_mut() >= src.len(), "buffer overflow; remaining = {}; src = {}", self.remaining_mut(), src.len());
|
||||
assert!(
|
||||
self.remaining_mut() >= src.len(),
|
||||
"buffer overflow; remaining = {}; src = {}",
|
||||
self.remaining_mut(),
|
||||
src.len()
|
||||
);
|
||||
|
||||
while off < src.len() {
|
||||
let cnt;
|
||||
|
@ -279,16 +290,14 @@ pub trait BufMut {
|
|||
let dst = self.bytes_mut();
|
||||
cnt = cmp::min(dst.len(), src.len() - off);
|
||||
|
||||
ptr::copy_nonoverlapping(
|
||||
src[off..].as_ptr(),
|
||||
dst.as_mut_ptr() as *mut u8,
|
||||
cnt);
|
||||
ptr::copy_nonoverlapping(src[off..].as_ptr(), dst.as_mut_ptr() as *mut u8, cnt);
|
||||
|
||||
off += cnt;
|
||||
|
||||
}
|
||||
|
||||
unsafe { self.advance_mut(cnt); }
|
||||
unsafe {
|
||||
self.advance_mut(cnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -872,7 +881,7 @@ pub trait BufMut {
|
|||
}
|
||||
|
||||
macro_rules! deref_forward_bufmut {
|
||||
() => (
|
||||
() => {
|
||||
fn remaining_mut(&self) -> usize {
|
||||
(**self).remaining_mut()
|
||||
}
|
||||
|
@ -949,7 +958,7 @@ macro_rules! deref_forward_bufmut {
|
|||
fn put_i64_le(&mut self, n: i64) {
|
||||
(**self).put_i64_le(n)
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
impl<T: BufMut + ?Sized> BufMut for &mut T {
|
||||
|
@ -990,11 +999,13 @@ impl BufMut for Vec<u8> {
|
|||
unsafe fn advance_mut(&mut self, cnt: usize) {
|
||||
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);
|
||||
}
|
||||
|
||||
assert!(
|
||||
cnt <= remaining,
|
||||
"cannot advance past `remaining_mut`: {:?} <= {:?}",
|
||||
cnt,
|
||||
remaining
|
||||
);
|
||||
|
||||
self.set_len(len + cnt);
|
||||
}
|
||||
|
@ -1011,15 +1022,16 @@ impl BufMut for Vec<u8> {
|
|||
let len = self.len();
|
||||
|
||||
let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
|
||||
unsafe {
|
||||
&mut slice::from_raw_parts_mut(ptr, cap)[len..]
|
||||
}
|
||||
unsafe { &mut slice::from_raw_parts_mut(ptr, cap)[len..] }
|
||||
}
|
||||
|
||||
// Specialize these methods so they can skip checking `remaining_mut`
|
||||
// and `advance_mut`.
|
||||
|
||||
fn put<T: super::Buf>(&mut self, mut src: T) where Self: Sized {
|
||||
fn put<T: super::Buf>(&mut self, mut src: T)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
// In case the src isn't contiguous, reserve upfront
|
||||
self.reserve(src.remaining());
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use crate::{Buf, BufMut};
|
||||
use crate::buf::IntoIter;
|
||||
use crate::{Buf, BufMut};
|
||||
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::io::{IoSlice};
|
||||
#[cfg(feature = "std")]
|
||||
use crate::buf::IoSliceMut;
|
||||
#[cfg(feature = "std")]
|
||||
use std::io::IoSlice;
|
||||
|
||||
/// A `Chain` sequences two buffers.
|
||||
///
|
||||
|
@ -41,10 +41,7 @@ pub struct Chain<T, U> {
|
|||
impl<T, U> Chain<T, U> {
|
||||
/// Creates a new `Chain` sequencing the provided values.
|
||||
pub fn new(a: T, b: U) -> Chain<T, U> {
|
||||
Chain {
|
||||
a,
|
||||
b,
|
||||
}
|
||||
Chain { a, b }
|
||||
}
|
||||
|
||||
/// Gets a reference to the first underlying `Buf`.
|
||||
|
@ -137,7 +134,8 @@ impl<T, U> Chain<T, U> {
|
|||
}
|
||||
|
||||
impl<T, U> Buf for Chain<T, U>
|
||||
where T: Buf,
|
||||
where
|
||||
T: Buf,
|
||||
U: Buf,
|
||||
{
|
||||
fn remaining(&self) -> usize {
|
||||
|
@ -179,7 +177,8 @@ impl<T, U> Buf for Chain<T, U>
|
|||
}
|
||||
|
||||
impl<T, U> BufMut for Chain<T, U>
|
||||
where T: BufMut,
|
||||
where
|
||||
T: BufMut,
|
||||
U: BufMut,
|
||||
{
|
||||
fn remaining_mut(&self) -> usize {
|
||||
|
|
|
@ -11,10 +11,7 @@ pub struct Limit<T> {
|
|||
}
|
||||
|
||||
pub(super) fn new<T>(inner: T, limit: usize) -> Limit<T> {
|
||||
Limit {
|
||||
inner,
|
||||
limit,
|
||||
}
|
||||
Limit { inner, limit }
|
||||
}
|
||||
|
||||
impl<T> Limit<T> {
|
||||
|
|
|
@ -10,9 +10,9 @@ mod take;
|
|||
#[cfg(feature = "std")]
|
||||
mod writer;
|
||||
|
||||
pub use self::chain::Chain;
|
||||
pub use self::limit::Limit;
|
||||
pub use self::take::Take;
|
||||
pub use self::chain::Chain;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use self::{reader::Reader, writer::Writer};
|
||||
|
@ -27,7 +27,7 @@ pub trait BufExt: Buf {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, BufMut, buf::BufExt};
|
||||
/// use bytes::{BufMut, buf::BufExt};
|
||||
///
|
||||
/// let mut buf = b"hello world"[..].take(5);
|
||||
/// let mut dst = vec![];
|
||||
|
@ -41,7 +41,8 @@ pub trait BufExt: Buf {
|
|||
/// assert_eq!(dst, b" world");
|
||||
/// ```
|
||||
fn take(self, limit: usize) -> Take<Self>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
take::new(self, limit)
|
||||
}
|
||||
|
@ -62,7 +63,8 @@ pub trait BufExt: Buf {
|
|||
/// assert_eq!(full.bytes(), b"hello world");
|
||||
/// ```
|
||||
fn chain<U: Buf>(self, next: U) -> Chain<Self, U>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Chain::new(self, next)
|
||||
}
|
||||
|
@ -77,7 +79,7 @@ pub trait BufExt: Buf {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, Bytes, buf::BufExt};
|
||||
/// use bytes::{Bytes, buf::BufExt};
|
||||
/// use std::io::Read;
|
||||
///
|
||||
/// let buf = Bytes::from("hello world");
|
||||
|
@ -91,7 +93,10 @@ pub trait BufExt: Buf {
|
|||
/// assert_eq!(&dst[..11], &b"hello world"[..]);
|
||||
/// ```
|
||||
#[cfg(feature = "std")]
|
||||
fn reader(self) -> Reader<Self> where Self: Sized {
|
||||
fn reader(self) -> Reader<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
reader::new(self)
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +119,8 @@ pub trait BufMutExt: BufMut {
|
|||
/// assert_eq!(dst.remaining_mut(), 10);
|
||||
/// ```
|
||||
fn limit(self, limit: usize) -> Limit<Self>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
limit::new(self, limit)
|
||||
}
|
||||
|
@ -129,7 +135,7 @@ pub trait BufMutExt: BufMut {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{BufMut, buf::BufMutExt};
|
||||
/// use bytes::buf::BufMutExt;
|
||||
/// use std::io::Write;
|
||||
///
|
||||
/// let mut buf = vec![].writer();
|
||||
|
@ -142,7 +148,10 @@ pub trait BufMutExt: BufMut {
|
|||
/// assert_eq!(*buf, b"hello world"[..]);
|
||||
/// ```
|
||||
#[cfg(feature = "std")]
|
||||
fn writer(self) -> Writer<Self> where Self: Sized {
|
||||
fn writer(self) -> Writer<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
writer::new(self)
|
||||
}
|
||||
|
||||
|
@ -167,7 +176,8 @@ pub trait BufMutExt: BufMut {
|
|||
/// assert_eq!(&b[..], b" world");
|
||||
/// ```
|
||||
fn chain_mut<U: BufMut>(self, next: U) -> Chain<Self, U>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Chain::new(self, next)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{Buf};
|
||||
use crate::Buf;
|
||||
|
||||
use std::{cmp, io};
|
||||
|
||||
|
@ -26,7 +26,7 @@ impl<B: Buf> Reader<B> {
|
|||
/// ```rust
|
||||
/// use bytes::buf::BufExt;
|
||||
///
|
||||
/// let mut buf = b"hello world".reader();
|
||||
/// let buf = b"hello world".reader();
|
||||
///
|
||||
/// assert_eq!(b"hello world", buf.get_ref());
|
||||
/// ```
|
||||
|
|
|
@ -5,7 +5,7 @@ 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.Buf.html#method.take) for more details.
|
||||
/// documentation of [`take()`](trait.BufExt.html#method.take) for more details.
|
||||
#[derive(Debug)]
|
||||
pub struct Take<T> {
|
||||
inner: T,
|
||||
|
@ -13,10 +13,7 @@ pub struct Take<T> {
|
|||
}
|
||||
|
||||
pub fn new<T>(inner: T, limit: usize) -> Take<T> {
|
||||
Take {
|
||||
inner,
|
||||
limit,
|
||||
}
|
||||
Take { inner, limit }
|
||||
}
|
||||
|
||||
impl<T> Take<T> {
|
||||
|
@ -25,7 +22,7 @@ impl<T> Take<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use bytes::buf::{Buf, BufMut, BufExt};
|
||||
/// use bytes::buf::{BufMut, BufExt};
|
||||
///
|
||||
/// let mut buf = b"hello world".take(2);
|
||||
/// let mut dst = vec![];
|
||||
|
@ -52,7 +49,7 @@ impl<T> Take<T> {
|
|||
/// ```rust
|
||||
/// use bytes::{Buf, buf::BufExt};
|
||||
///
|
||||
/// let mut buf = b"hello world".take(2);
|
||||
/// let buf = b"hello world".take(2);
|
||||
///
|
||||
/// assert_eq!(11, buf.get_ref().remaining());
|
||||
/// ```
|
||||
|
@ -113,7 +110,7 @@ impl<T> Take<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use bytes::{Buf, BufMut, buf::BufExt};
|
||||
/// use bytes::{BufMut, buf::BufExt};
|
||||
///
|
||||
/// let mut buf = b"hello world".take(2);
|
||||
/// let mut dst = vec![];
|
||||
|
|
|
@ -26,7 +26,7 @@ impl<B: BufMut> Writer<B> {
|
|||
/// ```rust
|
||||
/// use bytes::buf::BufMutExt;
|
||||
///
|
||||
/// let mut buf = Vec::with_capacity(1024).writer();
|
||||
/// let buf = Vec::with_capacity(1024).writer();
|
||||
///
|
||||
/// assert_eq!(1024, buf.get_ref().capacity());
|
||||
/// ```
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::Buf;
|
|||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, Bytes};
|
||||
/// use bytes::Bytes;
|
||||
///
|
||||
/// let buf = Bytes::from(&b"abc"[..]);
|
||||
/// let mut iter = buf.into_iter();
|
||||
|
@ -33,7 +33,7 @@ impl<T> IntoIter<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, Bytes};
|
||||
/// use bytes::Bytes;
|
||||
/// use bytes::buf::IntoIter;
|
||||
///
|
||||
/// let buf = Bytes::from_static(b"abc");
|
||||
|
@ -47,6 +47,7 @@ impl<T> IntoIter<T> {
|
|||
pub fn new(inner: T) -> IntoIter<T> {
|
||||
IntoIter { inner }
|
||||
}
|
||||
|
||||
/// Consumes this `IntoIter`, returning the underlying value.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -109,7 +110,6 @@ impl<T> IntoIter<T> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T: Buf> Iterator for IntoIter<T> {
|
||||
type Item = u8;
|
||||
|
||||
|
@ -130,4 +130,4 @@ impl<T: Buf> Iterator for IntoIter<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Buf> ExactSizeIterator for IntoIter<T> { }
|
||||
impl<T: Buf> ExactSizeIterator for IntoIter<T> {}
|
||||
|
|
|
@ -24,8 +24,7 @@ mod vec_deque;
|
|||
|
||||
pub use self::buf_impl::Buf;
|
||||
pub use self::buf_mut::BufMut;
|
||||
pub use self::ext::{BufExt, BufMutExt};
|
||||
#[cfg(feature = "std")]
|
||||
pub use self::buf_mut::IoSliceMut;
|
||||
pub use self::ext::{BufExt, BufMutExt};
|
||||
pub use self::iter::IntoIter;
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
use core::{cmp, fmt, hash, mem, ptr, slice, usize};
|
||||
use core::iter::{FromIterator};
|
||||
use core::iter::FromIterator;
|
||||
use core::ops::{Deref, RangeBounds};
|
||||
use core::{cmp, fmt, hash, mem, ptr, slice, usize};
|
||||
|
||||
use alloc::{vec::Vec, string::String, boxed::Box, borrow::Borrow};
|
||||
use alloc::{borrow::Borrow, boxed::Box, string::String, vec::Vec};
|
||||
|
||||
use crate::Buf;
|
||||
use crate::buf::IntoIter;
|
||||
use crate::debug;
|
||||
#[allow(unused)]
|
||||
use crate::loom::sync::atomic::AtomicMut;
|
||||
use crate::loom::sync::atomic::{self, AtomicPtr, AtomicUsize, Ordering};
|
||||
use crate::Buf;
|
||||
|
||||
/// A reference counted contiguous slice of memory.
|
||||
///
|
||||
|
@ -96,8 +97,18 @@ impl Bytes {
|
|||
/// assert_eq!(&b[..], b"");
|
||||
/// ```
|
||||
#[inline]
|
||||
#[cfg(not(all(loom, test)))]
|
||||
pub const fn new() -> Bytes {
|
||||
// Make it a named const to work around
|
||||
// "unsizing casts are not allowed in const fn"
|
||||
const EMPTY: &[u8] = &[];
|
||||
Bytes::from_static(EMPTY)
|
||||
}
|
||||
|
||||
#[cfg(all(loom, test))]
|
||||
pub fn new() -> Bytes {
|
||||
Bytes::from_static(b"")
|
||||
const EMPTY: &[u8] = &[];
|
||||
Bytes::from_static(EMPTY)
|
||||
}
|
||||
|
||||
/// Creates a new `Bytes` from a static slice.
|
||||
|
@ -164,7 +175,6 @@ impl Bytes {
|
|||
self.len == 0
|
||||
}
|
||||
|
||||
|
||||
///Creates `Bytes` instance from slice, by copying it.
|
||||
pub fn copy_from_slice(data: &[u8]) -> Self {
|
||||
data.to_vec().into()
|
||||
|
@ -209,14 +219,23 @@ impl Bytes {
|
|||
Bound::Unbounded => len,
|
||||
};
|
||||
|
||||
assert!(begin <= end);
|
||||
assert!(end <= len);
|
||||
assert!(
|
||||
begin <= end,
|
||||
"range start must not be greater than end: {:?} <= {:?}",
|
||||
begin,
|
||||
end,
|
||||
);
|
||||
assert!(
|
||||
end <= len,
|
||||
"range end out of bounds: {:?} <= {:?}",
|
||||
end,
|
||||
len,
|
||||
);
|
||||
|
||||
if end == begin {
|
||||
return Bytes::new();
|
||||
}
|
||||
|
||||
|
||||
let mut ret = self.clone();
|
||||
|
||||
ret.len = end - begin;
|
||||
|
@ -251,6 +270,12 @@ impl Bytes {
|
|||
/// Requires that the given `sub` slice is in fact contained within the
|
||||
/// `Bytes` buffer; otherwise this function will panic.
|
||||
pub fn slice_ref(&self, subset: &[u8]) -> Bytes {
|
||||
// Empty slice and empty Bytes may have their pointers reset
|
||||
// so explicitly allow empty slice to be a subslice of any slice.
|
||||
if subset.is_empty() {
|
||||
return Bytes::new();
|
||||
}
|
||||
|
||||
let bytes_p = self.as_ptr() as usize;
|
||||
let bytes_len = self.len();
|
||||
|
||||
|
@ -302,7 +327,12 @@ impl Bytes {
|
|||
/// Panics if `at > len`.
|
||||
#[must_use = "consider Bytes::truncate if you don't need the other half"]
|
||||
pub fn split_off(&mut self, at: usize) -> Bytes {
|
||||
assert!(at <= self.len());
|
||||
assert!(
|
||||
at <= self.len(),
|
||||
"split_off out of bounds: {:?} <= {:?}",
|
||||
at,
|
||||
self.len(),
|
||||
);
|
||||
|
||||
if at == self.len() {
|
||||
return Bytes::new();
|
||||
|
@ -346,7 +376,12 @@ impl Bytes {
|
|||
/// Panics if `at > len`.
|
||||
#[must_use = "consider Bytes::advance if you don't need the other half"]
|
||||
pub fn split_to(&mut self, at: usize) -> Bytes {
|
||||
assert!(at <= self.len());
|
||||
assert!(
|
||||
at <= self.len(),
|
||||
"split_to out of bounds: {:?} <= {:?}",
|
||||
at,
|
||||
self.len(),
|
||||
);
|
||||
|
||||
if at == self.len() {
|
||||
return mem::replace(self, Bytes::new());
|
||||
|
@ -356,7 +391,6 @@ impl Bytes {
|
|||
return Bytes::new();
|
||||
}
|
||||
|
||||
|
||||
let mut ret = self.clone();
|
||||
|
||||
unsafe { self.inc_start(at) };
|
||||
|
@ -388,9 +422,18 @@ impl Bytes {
|
|||
#[inline]
|
||||
pub fn truncate(&mut self, len: usize) {
|
||||
if len < self.len {
|
||||
// The Vec "promotable" vtables do not store the capacity,
|
||||
// so we cannot truncate while using this repr. We *have* to
|
||||
// promote using `split_off` so the capacity can be stored.
|
||||
if self.vtable as *const Vtable == &PROMOTABLE_EVEN_VTABLE
|
||||
|| self.vtable as *const Vtable == &PROMOTABLE_ODD_VTABLE
|
||||
{
|
||||
drop(self.split_off(len));
|
||||
} else {
|
||||
self.len = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Clears the buffer, removing all data.
|
||||
///
|
||||
|
@ -409,7 +452,12 @@ impl Bytes {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn with_vtable(ptr: *const u8, len: usize, data: AtomicPtr<()>, vtable: &'static Vtable) -> Bytes {
|
||||
pub(crate) unsafe fn with_vtable(
|
||||
ptr: *const u8,
|
||||
len: usize,
|
||||
data: AtomicPtr<()>,
|
||||
vtable: &'static Vtable,
|
||||
) -> Bytes {
|
||||
Bytes {
|
||||
ptr,
|
||||
len,
|
||||
|
@ -422,15 +470,13 @@ impl Bytes {
|
|||
|
||||
#[inline]
|
||||
fn as_slice(&self) -> &[u8] {
|
||||
unsafe {
|
||||
slice::from_raw_parts(self.ptr, self.len)
|
||||
}
|
||||
unsafe { slice::from_raw_parts(self.ptr, self.len) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn inc_start(&mut self, by: usize) {
|
||||
// should already be asserted, but debug assert for tests
|
||||
debug_assert!(self.len >= by);
|
||||
debug_assert!(self.len >= by, "internal: inc_start out of bounds");
|
||||
self.len -= by;
|
||||
self.ptr = self.ptr.offset(by as isize);
|
||||
}
|
||||
|
@ -443,24 +489,14 @@ unsafe impl Sync for Bytes {}
|
|||
impl Drop for Bytes {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
(self.vtable.drop)(&mut self.data, self.ptr, self.len)
|
||||
}
|
||||
unsafe { (self.vtable.drop)(&mut self.data, self.ptr, self.len) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Bytes {
|
||||
#[inline]
|
||||
fn clone(&self) -> Bytes {
|
||||
unsafe {
|
||||
(self.vtable.clone)(&self.data, self.ptr, self.len)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Bytes {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&debug::BsDebug(&self.as_slice()), f)
|
||||
unsafe { (self.vtable.clone)(&self.data, self.ptr, self.len) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -477,7 +513,13 @@ impl Buf for Bytes {
|
|||
|
||||
#[inline]
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
assert!(cnt <= self.len(), "cannot advance past `remaining`");
|
||||
assert!(
|
||||
cnt <= self.len(),
|
||||
"cannot advance past `remaining`: {:?} <= {:?}",
|
||||
cnt,
|
||||
self.len(),
|
||||
);
|
||||
|
||||
unsafe {
|
||||
self.inc_start(cnt);
|
||||
}
|
||||
|
@ -505,7 +547,10 @@ impl AsRef<[u8]> for Bytes {
|
|||
}
|
||||
|
||||
impl hash::Hash for Bytes {
|
||||
fn hash<H>(&self, state: &mut H) where H: hash::Hasher {
|
||||
fn hash<H>(&self, state: &mut H)
|
||||
where
|
||||
H: hash::Hasher,
|
||||
{
|
||||
self.as_slice().hash(state);
|
||||
}
|
||||
}
|
||||
|
@ -582,7 +627,7 @@ impl PartialEq<Bytes> for [u8] {
|
|||
|
||||
impl PartialOrd<Bytes> for [u8] {
|
||||
fn partial_cmp(&self, other: &Bytes) -> Option<cmp::Ordering> {
|
||||
other.partial_cmp(self)
|
||||
<[u8] as PartialOrd<[u8]>>::partial_cmp(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -606,7 +651,7 @@ impl PartialEq<Bytes> for str {
|
|||
|
||||
impl PartialOrd<Bytes> for str {
|
||||
fn partial_cmp(&self, other: &Bytes) -> Option<cmp::Ordering> {
|
||||
other.partial_cmp(self)
|
||||
<[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -630,7 +675,7 @@ impl PartialEq<Bytes> for Vec<u8> {
|
|||
|
||||
impl PartialOrd<Bytes> for Vec<u8> {
|
||||
fn partial_cmp(&self, other: &Bytes) -> Option<cmp::Ordering> {
|
||||
other.partial_cmp(self)
|
||||
<[u8] as PartialOrd<[u8]>>::partial_cmp(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -654,7 +699,7 @@ impl PartialEq<Bytes> for String {
|
|||
|
||||
impl PartialOrd<Bytes> for String {
|
||||
fn partial_cmp(&self, other: &Bytes) -> Option<cmp::Ordering> {
|
||||
other.partial_cmp(self)
|
||||
<[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -666,7 +711,7 @@ impl PartialEq<Bytes> for &[u8] {
|
|||
|
||||
impl PartialOrd<Bytes> for &[u8] {
|
||||
fn partial_cmp(&self, other: &Bytes) -> Option<cmp::Ordering> {
|
||||
other.partial_cmp(self)
|
||||
<[u8] as PartialOrd<[u8]>>::partial_cmp(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -678,12 +723,13 @@ impl PartialEq<Bytes> for &str {
|
|||
|
||||
impl PartialOrd<Bytes> for &str {
|
||||
fn partial_cmp(&self, other: &Bytes) -> Option<cmp::Ordering> {
|
||||
other.partial_cmp(self)
|
||||
<[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> PartialEq<&'a T> for Bytes
|
||||
where Bytes: PartialEq<T>
|
||||
where
|
||||
Bytes: PartialEq<T>,
|
||||
{
|
||||
fn eq(&self, other: &&'a T) -> bool {
|
||||
*self == **other
|
||||
|
@ -691,7 +737,8 @@ impl<'a, T: ?Sized> PartialEq<&'a T> for Bytes
|
|||
}
|
||||
|
||||
impl<'a, T: ?Sized> PartialOrd<&'a T> for Bytes
|
||||
where Bytes: PartialOrd<T>
|
||||
where
|
||||
Bytes: PartialOrd<T>,
|
||||
{
|
||||
fn partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering> {
|
||||
self.partial_cmp(&**other)
|
||||
|
@ -731,20 +778,23 @@ impl From<Vec<u8>> for Bytes {
|
|||
let slice = vec.into_boxed_slice();
|
||||
let len = slice.len();
|
||||
let ptr = slice.as_ptr();
|
||||
|
||||
assert!(
|
||||
ptr as usize & KIND_VEC == 0,
|
||||
"Vec pointer should not have LSB set: {:p}",
|
||||
ptr,
|
||||
);
|
||||
drop(Box::into_raw(slice));
|
||||
|
||||
if ptr as usize & 0x1 == 0 {
|
||||
let data = ptr as usize | KIND_VEC;
|
||||
Bytes {
|
||||
ptr,
|
||||
len,
|
||||
data: AtomicPtr::new(data as *mut _),
|
||||
vtable: &SHARED_VTABLE,
|
||||
vtable: &PROMOTABLE_EVEN_VTABLE,
|
||||
}
|
||||
} else {
|
||||
Bytes {
|
||||
ptr,
|
||||
len,
|
||||
data: AtomicPtr::new(ptr as *mut _),
|
||||
vtable: &PROMOTABLE_ODD_VTABLE,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -782,6 +832,78 @@ unsafe fn static_drop(_: &mut AtomicPtr<()>, _: *const u8, _: usize) {
|
|||
// nothing to drop for &'static [u8]
|
||||
}
|
||||
|
||||
// ===== impl PromotableVtable =====
|
||||
|
||||
static PROMOTABLE_EVEN_VTABLE: Vtable = Vtable {
|
||||
clone: promotable_even_clone,
|
||||
drop: promotable_even_drop,
|
||||
};
|
||||
|
||||
static PROMOTABLE_ODD_VTABLE: Vtable = Vtable {
|
||||
clone: promotable_odd_clone,
|
||||
drop: promotable_odd_drop,
|
||||
};
|
||||
|
||||
unsafe fn promotable_even_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
|
||||
let shared = data.load(Ordering::Acquire);
|
||||
let kind = shared as usize & KIND_MASK;
|
||||
|
||||
if kind == KIND_ARC {
|
||||
shallow_clone_arc(shared as _, ptr, len)
|
||||
} else {
|
||||
debug_assert_eq!(kind, KIND_VEC);
|
||||
let buf = (shared as usize & !KIND_MASK) as *mut u8;
|
||||
shallow_clone_vec(data, shared, buf, ptr, len)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn promotable_even_drop(data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) {
|
||||
data.with_mut(|shared| {
|
||||
let shared = *shared;
|
||||
let kind = shared as usize & KIND_MASK;
|
||||
|
||||
if kind == KIND_ARC {
|
||||
release_shared(shared as *mut Shared);
|
||||
} else {
|
||||
debug_assert_eq!(kind, KIND_VEC);
|
||||
let buf = (shared as usize & !KIND_MASK) as *mut u8;
|
||||
drop(rebuild_boxed_slice(buf, ptr, len));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
unsafe fn promotable_odd_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
|
||||
let shared = data.load(Ordering::Acquire);
|
||||
let kind = shared as usize & KIND_MASK;
|
||||
|
||||
if kind == KIND_ARC {
|
||||
shallow_clone_arc(shared as _, ptr, len)
|
||||
} else {
|
||||
debug_assert_eq!(kind, KIND_VEC);
|
||||
shallow_clone_vec(data, shared, shared as *mut u8, ptr, len)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn promotable_odd_drop(data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) {
|
||||
data.with_mut(|shared| {
|
||||
let shared = *shared;
|
||||
let kind = shared as usize & KIND_MASK;
|
||||
|
||||
if kind == KIND_ARC {
|
||||
release_shared(shared as *mut Shared);
|
||||
} else {
|
||||
debug_assert_eq!(kind, KIND_VEC);
|
||||
|
||||
drop(rebuild_boxed_slice(shared as *mut u8, ptr, len));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
unsafe fn rebuild_boxed_slice(buf: *mut u8, offset: *const u8, len: usize) -> Box<[u8]> {
|
||||
let cap = (offset as usize - buf as usize) + len;
|
||||
Box::from_raw(slice::from_raw_parts_mut(buf, cap))
|
||||
}
|
||||
|
||||
// ===== impl SharedVtable =====
|
||||
|
||||
struct Shared {
|
||||
|
@ -790,6 +912,12 @@ struct Shared {
|
|||
ref_cnt: AtomicUsize,
|
||||
}
|
||||
|
||||
// Assert that the alignment of `Shared` is divisible by 2.
|
||||
// This is a necessary invariant since we depend on allocating `Shared` a
|
||||
// shared object to implicitly carry the `KIND_ARC` flag in its pointer.
|
||||
// This flag is set when the LSB is 0.
|
||||
const _: [(); 0 - mem::align_of::<Shared>() % 2] = []; // Assert that the alignment of `Shared` is divisible by 2.
|
||||
|
||||
static SHARED_VTABLE: Vtable = Vtable {
|
||||
clone: shared_clone,
|
||||
drop: shared_drop,
|
||||
|
@ -800,45 +928,14 @@ const KIND_VEC: usize = 0b1;
|
|||
const KIND_MASK: usize = 0b1;
|
||||
|
||||
unsafe fn shared_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
|
||||
let shared = data.load(Ordering::Acquire);
|
||||
let kind = shared as usize & KIND_MASK;
|
||||
|
||||
if kind == KIND_ARC {
|
||||
let shared = data.load(Ordering::Relaxed);
|
||||
shallow_clone_arc(shared as _, ptr, len)
|
||||
} else {
|
||||
debug_assert_eq!(kind, KIND_VEC);
|
||||
shallow_clone_vec(data, shared, ptr, len)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn shared_drop(data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) {
|
||||
let shared = *data.get_mut();
|
||||
let kind = shared as usize & KIND_MASK;
|
||||
|
||||
|
||||
if kind == KIND_ARC {
|
||||
release_shared(shared as *mut Shared);
|
||||
} else {
|
||||
debug_assert_eq!(kind, KIND_VEC);
|
||||
|
||||
drop(rebuild_vec(shared, ptr, len));
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn rebuild_vec(shared: *const (), offset: *const u8, len: usize) -> Vec<u8> {
|
||||
debug_assert!(
|
||||
shared as usize & KIND_MASK == KIND_VEC,
|
||||
"rebuild_vec should have beeen called with KIND_VEC",
|
||||
);
|
||||
debug_assert!(
|
||||
shared as usize & !KIND_MASK != 0,
|
||||
"rebuild_vec should be called with non-null pointer: {:p}",
|
||||
shared,
|
||||
);
|
||||
|
||||
let buf = (shared as usize & !KIND_MASK) as *mut u8;
|
||||
let cap = (offset as usize - buf as usize) + len;
|
||||
Vec::from_raw_parts(buf, cap, cap)
|
||||
unsafe fn shared_drop(data: &mut AtomicPtr<()>, _ptr: *const u8, _len: usize) {
|
||||
data.with_mut(|shared| {
|
||||
release_shared(*shared as *mut Shared);
|
||||
});
|
||||
}
|
||||
|
||||
unsafe fn shallow_clone_arc(shared: *mut Shared, ptr: *const u8, len: usize) -> Bytes {
|
||||
|
@ -857,13 +954,17 @@ unsafe fn shallow_clone_arc(shared: *mut Shared, ptr: *const u8, len: usize) ->
|
|||
}
|
||||
|
||||
#[cold]
|
||||
unsafe fn shallow_clone_vec(atom: &AtomicPtr<()>, ptr: *const (), offset: *const u8, len: usize) -> Bytes {
|
||||
unsafe fn shallow_clone_vec(
|
||||
atom: &AtomicPtr<()>,
|
||||
ptr: *const (),
|
||||
buf: *mut u8,
|
||||
offset: *const u8,
|
||||
len: usize,
|
||||
) -> Bytes {
|
||||
// If the buffer is still tracked in a `Vec<u8>`. It is time to
|
||||
// promote the vec to an `Arc`. This could potentially be called
|
||||
// concurrently, so some care must be taken.
|
||||
|
||||
debug_assert_eq!(ptr as usize & KIND_MASK, KIND_VEC);
|
||||
|
||||
// First, allocate a new `Shared` instance containing the
|
||||
// `Vec` fields. It's important to note that `ptr`, `len`,
|
||||
// and `cap` cannot be mutated without having `&mut self`.
|
||||
|
@ -871,7 +972,7 @@ unsafe fn shallow_clone_vec(atom: &AtomicPtr<()>, ptr: *const (), offset: *const
|
|||
// updated and since the buffer hasn't been promoted to an
|
||||
// `Arc`, those three fields still are the components of the
|
||||
// vector.
|
||||
let vec = rebuild_vec(ptr as *const (), offset, len);
|
||||
let vec = rebuild_boxed_slice(buf, offset, len).into_vec();
|
||||
let shared = Box::new(Shared {
|
||||
_vec: vec,
|
||||
// Initialize refcount to 2. One for this reference, and one
|
||||
|
@ -884,7 +985,10 @@ unsafe fn shallow_clone_vec(atom: &AtomicPtr<()>, ptr: *const (), offset: *const
|
|||
|
||||
// The pointer should be aligned, so this assert should
|
||||
// always succeed.
|
||||
debug_assert!(0 == (shared as usize & KIND_MASK));
|
||||
debug_assert!(
|
||||
0 == (shared as usize & KIND_MASK),
|
||||
"internal: Box<Shared> should have an aligned pointer",
|
||||
);
|
||||
|
||||
// Try compare & swapping the pointer into the `arc` field.
|
||||
// `Release` is used synchronize with other threads that
|
||||
|
@ -973,7 +1077,7 @@ fn _split_off_must_use() {}
|
|||
// fuzz tests
|
||||
#[cfg(all(test, loom))]
|
||||
mod fuzz {
|
||||
use std::sync::Arc;
|
||||
use loom::sync::Arc;
|
||||
use loom::thread;
|
||||
|
||||
use super::Bytes;
|
||||
|
|
|
@ -1,23 +1,33 @@
|
|||
use core::{cmp, fmt, hash, isize, slice, usize};
|
||||
use core::iter::{FromIterator, Iterator};
|
||||
use core::mem::{self, ManuallyDrop};
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::ptr::{self, NonNull};
|
||||
use core::iter::{FromIterator, Iterator};
|
||||
use core::{cmp, fmt, hash, isize, slice, usize};
|
||||
|
||||
use alloc::{vec::Vec, string::String, boxed::Box, borrow::{Borrow, BorrowMut}};
|
||||
use alloc::{
|
||||
borrow::{Borrow, BorrowMut},
|
||||
boxed::Box,
|
||||
string::String,
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
use crate::{Bytes, Buf, BufMut};
|
||||
use crate::bytes::Vtable;
|
||||
use crate::buf::IntoIter;
|
||||
use crate::debug;
|
||||
use crate::bytes::Vtable;
|
||||
#[allow(unused)]
|
||||
use crate::loom::sync::atomic::AtomicMut;
|
||||
use crate::loom::sync::atomic::{self, AtomicPtr, AtomicUsize, Ordering};
|
||||
use crate::{Buf, BufMut, Bytes};
|
||||
|
||||
/// A unique reference to a contiguous slice of memory.
|
||||
///
|
||||
/// `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. It is similar to a `Vec<u8>` but with less copies and
|
||||
/// allocations.
|
||||
/// mutate the memory.
|
||||
///
|
||||
/// `BytesMut` can be thought of as containing a `buf: Arc<Vec<u8>>`, an offset
|
||||
/// into `buf`, a slice length, and a guarantee that no other `BytesMut` for the
|
||||
/// same `buf` overlaps with its slice. That guarantee means that a write lock
|
||||
/// is not required.
|
||||
///
|
||||
/// # Growth
|
||||
///
|
||||
|
@ -108,8 +118,7 @@ impl BytesMut {
|
|||
/// Creates a new `BytesMut` with the specified capacity.
|
||||
///
|
||||
/// The returned `BytesMut` will be able to hold at least `capacity` bytes
|
||||
/// without reallocating. If `capacity` is under `4 * size_of::<usize>() - 1`,
|
||||
/// then `BytesMut` will not allocate.
|
||||
/// without reallocating.
|
||||
///
|
||||
/// It is important to note that this function does not specify the length
|
||||
/// of the returned `BytesMut`, but only the capacity.
|
||||
|
@ -234,7 +243,9 @@ impl BytesMut {
|
|||
let (off, _) = self.get_vec_pos();
|
||||
let vec = rebuild_vec(self.ptr.as_ptr(), self.len, self.cap, off);
|
||||
mem::forget(self);
|
||||
vec.into()
|
||||
let mut b: Bytes = vec.into();
|
||||
b.advance(off);
|
||||
b
|
||||
}
|
||||
} else {
|
||||
debug_assert_eq!(self.kind(), KIND_ARC);
|
||||
|
@ -243,9 +254,7 @@ impl BytesMut {
|
|||
let len = self.len;
|
||||
let data = AtomicPtr::new(self.data as _);
|
||||
mem::forget(self);
|
||||
unsafe {
|
||||
Bytes::with_vtable(ptr, len, data, &SHARED_VTABLE)
|
||||
}
|
||||
unsafe { Bytes::with_vtable(ptr, len, data, &SHARED_VTABLE) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,7 +286,12 @@ impl BytesMut {
|
|||
/// Panics if `at > capacity`.
|
||||
#[must_use = "consider BytesMut::truncate if you don't need the other half"]
|
||||
pub fn split_off(&mut self, at: usize) -> BytesMut {
|
||||
assert!(at <= self.capacity());
|
||||
assert!(
|
||||
at <= self.capacity(),
|
||||
"split_off out of bounds: {:?} <= {:?}",
|
||||
at,
|
||||
self.capacity(),
|
||||
);
|
||||
unsafe {
|
||||
let mut other = self.shallow_clone();
|
||||
other.set_start(at);
|
||||
|
@ -345,7 +359,12 @@ impl BytesMut {
|
|||
/// Panics if `at > len`.
|
||||
#[must_use = "consider BytesMut::advance if you don't need the other half"]
|
||||
pub fn split_to(&mut self, at: usize) -> BytesMut {
|
||||
assert!(at <= self.len());
|
||||
assert!(
|
||||
at <= self.len(),
|
||||
"split_to out of bounds: {:?} <= {:?}",
|
||||
at,
|
||||
self.len(),
|
||||
);
|
||||
|
||||
unsafe {
|
||||
let mut other = self.shallow_clone();
|
||||
|
@ -377,7 +396,9 @@ impl BytesMut {
|
|||
/// [`split_off`]: #method.split_off
|
||||
pub fn truncate(&mut self, len: usize) {
|
||||
if len <= self.len() {
|
||||
unsafe { self.set_len(len); }
|
||||
unsafe {
|
||||
self.set_len(len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -458,8 +479,9 @@ impl BytesMut {
|
|||
///
|
||||
/// assert_eq!(&b[..], b"hello world");
|
||||
/// ```
|
||||
#[inline]
|
||||
pub unsafe fn set_len(&mut self, len: usize) {
|
||||
debug_assert!(len <= self.cap);
|
||||
debug_assert!(len <= self.cap, "set_len out of bounds");
|
||||
self.len = len;
|
||||
}
|
||||
|
||||
|
@ -541,9 +563,8 @@ impl BytesMut {
|
|||
unsafe {
|
||||
let (off, prev) = self.get_vec_pos();
|
||||
|
||||
// Only reuse space if we stand to gain at least capacity/2
|
||||
// bytes of space back
|
||||
if off >= additional && off >= (self.cap / 2) {
|
||||
// Only reuse space if we can satisfy the requested additional space.
|
||||
if self.capacity() - self.len() + off >= additional {
|
||||
// There's space - reuse it
|
||||
//
|
||||
// Just move the pointer back to the start after copying
|
||||
|
@ -558,7 +579,8 @@ impl BytesMut {
|
|||
self.cap += off;
|
||||
} else {
|
||||
// No space - allocate more
|
||||
let mut v = ManuallyDrop::new(rebuild_vec(self.ptr.as_ptr(), self.len, self.cap, off));
|
||||
let mut v =
|
||||
ManuallyDrop::new(rebuild_vec(self.ptr.as_ptr(), self.len, self.cap, off));
|
||||
v.reserve(additional);
|
||||
|
||||
// Update the info
|
||||
|
@ -574,7 +596,6 @@ impl BytesMut {
|
|||
debug_assert_eq!(kind, KIND_ARC);
|
||||
let shared: *mut Shared = self.data as _;
|
||||
|
||||
|
||||
// Reserving involves abandoning the currently shared buffer and
|
||||
// allocating a new vector with the requested capacity.
|
||||
//
|
||||
|
@ -618,9 +639,7 @@ impl BytesMut {
|
|||
// check.
|
||||
let double = v.capacity().checked_shl(1).unwrap_or(new_cap);
|
||||
|
||||
new_cap = cmp::max(
|
||||
cmp::max(double, new_cap),
|
||||
original_capacity);
|
||||
new_cap = cmp::max(cmp::max(double, new_cap), original_capacity);
|
||||
} else {
|
||||
new_cap = cmp::max(new_cap, original_capacity);
|
||||
}
|
||||
|
@ -643,10 +662,11 @@ impl BytesMut {
|
|||
self.len = v.len();
|
||||
self.cap = v.capacity();
|
||||
}
|
||||
/// Appends given bytes to this object.
|
||||
|
||||
/// Appends given bytes to this `BytesMut`.
|
||||
///
|
||||
/// If this `BytesMut` object has not enough capacity, it is resized first.
|
||||
/// So unlike `put_slice` operation, `extend_from_slice` does not panic.
|
||||
/// If this `BytesMut` object does not have enough capacity, it is resized
|
||||
/// first.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -668,19 +688,21 @@ impl BytesMut {
|
|||
// Reserved above
|
||||
debug_assert!(dst.len() >= cnt);
|
||||
|
||||
ptr::copy_nonoverlapping(
|
||||
extend.as_ptr(),
|
||||
dst.as_mut_ptr() as *mut u8,
|
||||
cnt);
|
||||
|
||||
ptr::copy_nonoverlapping(extend.as_ptr(), dst.as_mut_ptr() as *mut u8, cnt);
|
||||
}
|
||||
|
||||
unsafe { self.advance_mut(cnt); }
|
||||
unsafe {
|
||||
self.advance_mut(cnt);
|
||||
}
|
||||
}
|
||||
|
||||
/// Combine splitted BytesMut objects back as contiguous.
|
||||
/// Absorbs a `BytesMut` that was previously split off.
|
||||
///
|
||||
/// If `BytesMut` objects were not contiguous originally, they will be extended.
|
||||
/// If the two `BytesMut` objects were previously contiguous, i.e., if
|
||||
/// `other` was created by calling `split_off` on this `BytesMut`, then
|
||||
/// this is an `O(1)` operation that just decreases a reference
|
||||
/// count and sets a few indices. Otherwise this method degenerates to
|
||||
/// `self.extend_from_slice(other.as_ref())`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -690,11 +712,11 @@ impl BytesMut {
|
|||
/// let mut buf = BytesMut::with_capacity(64);
|
||||
/// buf.extend_from_slice(b"aaabbbcccddd");
|
||||
///
|
||||
/// let splitted = buf.split_off(6);
|
||||
/// let split = buf.split_off(6);
|
||||
/// assert_eq!(b"aaabbb", &buf[..]);
|
||||
/// assert_eq!(b"cccddd", &splitted[..]);
|
||||
/// assert_eq!(b"cccddd", &split[..]);
|
||||
///
|
||||
/// buf.unsplit(splitted);
|
||||
/// buf.unsplit(split);
|
||||
/// assert_eq!(b"aaabbbcccddd", &buf[..]);
|
||||
/// ```
|
||||
pub fn unsplit(&mut self, other: BytesMut) {
|
||||
|
@ -736,16 +758,12 @@ impl BytesMut {
|
|||
|
||||
#[inline]
|
||||
fn as_slice(&self) -> &[u8] {
|
||||
unsafe {
|
||||
slice::from_raw_parts(self.ptr.as_ptr(), self.len)
|
||||
}
|
||||
unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_slice_mut(&mut self) -> &mut [u8] {
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len)
|
||||
}
|
||||
unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) }
|
||||
}
|
||||
|
||||
unsafe fn set_start(&mut self, start: usize) {
|
||||
|
@ -755,7 +773,7 @@ impl BytesMut {
|
|||
return;
|
||||
}
|
||||
|
||||
debug_assert!(start <= self.cap);
|
||||
debug_assert!(start <= self.cap, "internal: set_start out of bounds");
|
||||
|
||||
let kind = self.kind();
|
||||
|
||||
|
@ -774,7 +792,7 @@ impl BytesMut {
|
|||
// on 64 bit systems and will only happen on 32 bit systems
|
||||
// when shifting past 134,217,727 bytes. As such, we don't
|
||||
// worry too much about performance here.
|
||||
self.promote_to_shared(/*ref_count = */1);
|
||||
self.promote_to_shared(/*ref_count = */ 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -794,7 +812,7 @@ impl BytesMut {
|
|||
|
||||
unsafe fn set_end(&mut self, end: usize) {
|
||||
debug_assert_eq!(self.kind(), KIND_ARC);
|
||||
assert!(end <= self.cap);
|
||||
assert!(end <= self.cap, "set_end out of bounds");
|
||||
|
||||
self.cap = end;
|
||||
self.len = cmp::min(self.len, end);
|
||||
|
@ -806,10 +824,10 @@ impl BytesMut {
|
|||
}
|
||||
|
||||
let ptr = unsafe { self.ptr.as_ptr().offset(self.len as isize) };
|
||||
if ptr == other.ptr.as_ptr() &&
|
||||
self.kind() == KIND_ARC &&
|
||||
other.kind() == KIND_ARC &&
|
||||
self.data == other.data
|
||||
if ptr == other.ptr.as_ptr()
|
||||
&& self.kind() == KIND_ARC
|
||||
&& other.kind() == KIND_ARC
|
||||
&& self.data == other.data
|
||||
{
|
||||
// Contiguous blocks, just combine directly
|
||||
self.len += other.len;
|
||||
|
@ -870,7 +888,7 @@ impl BytesMut {
|
|||
increment_shared(self.data);
|
||||
ptr::read(self)
|
||||
} else {
|
||||
self.promote_to_shared(/*ref_count = */2);
|
||||
self.promote_to_shared(/*ref_count = */ 2);
|
||||
ptr::read(self)
|
||||
}
|
||||
}
|
||||
|
@ -932,8 +950,15 @@ impl Buf for BytesMut {
|
|||
|
||||
#[inline]
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
assert!(cnt <= self.remaining(), "cannot advance past `remaining`");
|
||||
unsafe { self.set_start(cnt); }
|
||||
assert!(
|
||||
cnt <= self.remaining(),
|
||||
"cannot advance past `remaining`: {:?} <= {:?}",
|
||||
cnt,
|
||||
self.remaining(),
|
||||
);
|
||||
unsafe {
|
||||
self.set_start(cnt);
|
||||
}
|
||||
}
|
||||
|
||||
fn to_bytes(&mut self) -> crate::Bytes {
|
||||
|
@ -950,7 +975,12 @@ impl BufMut for BytesMut {
|
|||
#[inline]
|
||||
unsafe fn advance_mut(&mut self, cnt: usize) {
|
||||
let new_len = self.len() + cnt;
|
||||
assert!(new_len <= self.cap, "new_len = {}; capacity = {}", new_len, self.cap);
|
||||
assert!(
|
||||
new_len <= self.cap,
|
||||
"new_len = {}; capacity = {}",
|
||||
new_len,
|
||||
self.cap
|
||||
);
|
||||
self.len = new_len;
|
||||
}
|
||||
|
||||
|
@ -965,7 +995,10 @@ impl BufMut for BytesMut {
|
|||
// Specialize these methods so they can skip checking `remaining_mut`
|
||||
// and `advance_mut`.
|
||||
|
||||
fn put<T: crate::Buf>(&mut self, mut src: T) where Self: Sized {
|
||||
fn put<T: crate::Buf>(&mut self, mut src: T)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
while src.has_remaining() {
|
||||
let s = src.bytes();
|
||||
let l = s.len();
|
||||
|
@ -996,6 +1029,7 @@ impl Deref for BytesMut {
|
|||
}
|
||||
|
||||
impl AsMut<[u8]> for BytesMut {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut [u8] {
|
||||
self.as_slice_mut()
|
||||
}
|
||||
|
@ -1020,6 +1054,12 @@ impl<'a> From<&'a str> for BytesMut {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<BytesMut> for Bytes {
|
||||
fn from(src: BytesMut) -> Bytes {
|
||||
src.freeze()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for BytesMut {
|
||||
fn eq(&self, other: &BytesMut) -> bool {
|
||||
self.as_slice() == other.as_slice()
|
||||
|
@ -1038,8 +1078,7 @@ impl Ord for BytesMut {
|
|||
}
|
||||
}
|
||||
|
||||
impl Eq for BytesMut {
|
||||
}
|
||||
impl Eq for BytesMut {}
|
||||
|
||||
impl Default for BytesMut {
|
||||
#[inline]
|
||||
|
@ -1048,14 +1087,11 @@ impl Default for BytesMut {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for BytesMut {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&debug::BsDebug(&self.as_slice()), fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl hash::Hash for BytesMut {
|
||||
fn hash<H>(&self, state: &mut H) where H: hash::Hasher {
|
||||
fn hash<H>(&self, state: &mut H)
|
||||
where
|
||||
H: hash::Hasher,
|
||||
{
|
||||
let s: &[u8] = self.as_ref();
|
||||
s.hash(state);
|
||||
}
|
||||
|
@ -1115,7 +1151,10 @@ impl<'a> IntoIterator for &'a BytesMut {
|
|||
}
|
||||
|
||||
impl Extend<u8> for BytesMut {
|
||||
fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item = u8> {
|
||||
fn extend<T>(&mut self, iter: T)
|
||||
where
|
||||
T: IntoIterator<Item = u8>,
|
||||
{
|
||||
let iter = iter.into_iter();
|
||||
|
||||
let (lower, _) = iter.size_hint();
|
||||
|
@ -1132,7 +1171,10 @@ impl Extend<u8> for BytesMut {
|
|||
}
|
||||
|
||||
impl<'a> Extend<&'a u8> for BytesMut {
|
||||
fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item = &'a u8> {
|
||||
fn extend<T>(&mut self, iter: T)
|
||||
where
|
||||
T: IntoIterator<Item = &'a u8>,
|
||||
{
|
||||
self.extend(iter.into_iter().map(|b| *b))
|
||||
}
|
||||
}
|
||||
|
@ -1210,7 +1252,10 @@ impl Shared {
|
|||
|
||||
fn original_capacity_to_repr(cap: usize) -> usize {
|
||||
let width = PTR_WIDTH - ((cap >> MIN_ORIGINAL_CAPACITY_WIDTH).leading_zeros() as usize);
|
||||
cmp::min(width, MAX_ORIGINAL_CAPACITY_WIDTH - MIN_ORIGINAL_CAPACITY_WIDTH)
|
||||
cmp::min(
|
||||
width,
|
||||
MAX_ORIGINAL_CAPACITY_WIDTH - MIN_ORIGINAL_CAPACITY_WIDTH,
|
||||
)
|
||||
}
|
||||
|
||||
fn original_capacity_from_repr(repr: usize) -> usize {
|
||||
|
@ -1301,7 +1346,7 @@ impl PartialEq<BytesMut> for [u8] {
|
|||
|
||||
impl PartialOrd<BytesMut> for [u8] {
|
||||
fn partial_cmp(&self, other: &BytesMut) -> Option<cmp::Ordering> {
|
||||
other.partial_cmp(self)
|
||||
<[u8] as PartialOrd<[u8]>>::partial_cmp(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1325,7 +1370,7 @@ impl PartialEq<BytesMut> for str {
|
|||
|
||||
impl PartialOrd<BytesMut> for str {
|
||||
fn partial_cmp(&self, other: &BytesMut) -> Option<cmp::Ordering> {
|
||||
other.partial_cmp(self)
|
||||
<[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1373,12 +1418,13 @@ impl PartialEq<BytesMut> for String {
|
|||
|
||||
impl PartialOrd<BytesMut> for String {
|
||||
fn partial_cmp(&self, other: &BytesMut) -> Option<cmp::Ordering> {
|
||||
other.partial_cmp(self)
|
||||
<[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> PartialEq<&'a T> for BytesMut
|
||||
where BytesMut: PartialEq<T>
|
||||
where
|
||||
BytesMut: PartialEq<T>,
|
||||
{
|
||||
fn eq(&self, other: &&'a T) -> bool {
|
||||
*self == **other
|
||||
|
@ -1386,7 +1432,8 @@ impl<'a, T: ?Sized> PartialEq<&'a T> for BytesMut
|
|||
}
|
||||
|
||||
impl<'a, T: ?Sized> PartialOrd<&'a T> for BytesMut
|
||||
where BytesMut: PartialOrd<T>
|
||||
where
|
||||
BytesMut: PartialOrd<T>,
|
||||
{
|
||||
fn partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering> {
|
||||
self.partial_cmp(*other)
|
||||
|
@ -1401,7 +1448,7 @@ impl PartialEq<BytesMut> for &[u8] {
|
|||
|
||||
impl PartialOrd<BytesMut> for &[u8] {
|
||||
fn partial_cmp(&self, other: &BytesMut) -> Option<cmp::Ordering> {
|
||||
other.partial_cmp(self)
|
||||
<[u8] as PartialOrd<[u8]>>::partial_cmp(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1453,7 +1500,7 @@ static SHARED_VTABLE: Vtable = Vtable {
|
|||
};
|
||||
|
||||
unsafe fn shared_v_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
|
||||
let shared = data.load(Ordering::Acquire) as *mut Shared;
|
||||
let shared = data.load(Ordering::Relaxed) as *mut Shared;
|
||||
increment_shared(shared);
|
||||
|
||||
let data = AtomicPtr::new(shared as _);
|
||||
|
@ -1461,8 +1508,9 @@ unsafe fn shared_v_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> By
|
|||
}
|
||||
|
||||
unsafe fn shared_v_drop(data: &mut AtomicPtr<()>, _ptr: *const u8, _len: usize) {
|
||||
let shared = (*data.get_mut()) as *mut Shared;
|
||||
release_shared(shared as *mut Shared);
|
||||
data.with_mut(|shared| {
|
||||
release_shared(*shared as *mut Shared);
|
||||
});
|
||||
}
|
||||
|
||||
// compile-fails
|
||||
|
@ -1500,11 +1548,11 @@ fn _split_must_use() {}
|
|||
// fuzz tests
|
||||
#[cfg(all(test, loom))]
|
||||
mod fuzz {
|
||||
use std::sync::Arc;
|
||||
use loom::sync::Arc;
|
||||
use loom::thread;
|
||||
|
||||
use crate::Bytes;
|
||||
use super::BytesMut;
|
||||
use crate::Bytes;
|
||||
|
||||
#[test]
|
||||
fn bytes_mut_cloning_frozen() {
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
use core::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 fmt::Debug for BsDebug<'_> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
write!(fmt, "b\"")?;
|
||||
for &c in self.0 {
|
||||
// https://doc.rust-lang.org/reference.html#byte-escapes
|
||||
if c == b'\n' {
|
||||
write!(fmt, "\\n")?;
|
||||
} else if c == b'\r' {
|
||||
write!(fmt, "\\r")?;
|
||||
} else if c == b'\t' {
|
||||
write!(fmt, "\\t")?;
|
||||
} else if c == b'\\' || c == b'"' {
|
||||
write!(fmt, "\\{}", c as char)?;
|
||||
} else if c == b'\0' {
|
||||
write!(fmt, "\\0")?;
|
||||
// ASCII printable
|
||||
} else if c >= 0x20 && c < 0x7f {
|
||||
write!(fmt, "{}", c as char)?;
|
||||
} else {
|
||||
write!(fmt, "\\x{:02x}", c)?;
|
||||
}
|
||||
}
|
||||
write!(fmt, "\"")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
use core::fmt::{Debug, Formatter, Result};
|
||||
|
||||
use super::BytesRef;
|
||||
use crate::{Bytes, BytesMut};
|
||||
|
||||
/// Alternative implementation of `std::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.
|
||||
impl Debug for BytesRef<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
write!(f, "b\"")?;
|
||||
for &b in self.0 {
|
||||
// https://doc.rust-lang.org/reference/tokens.html#byte-escapes
|
||||
if b == b'\n' {
|
||||
write!(f, "\\n")?;
|
||||
} else if b == b'\r' {
|
||||
write!(f, "\\r")?;
|
||||
} else if b == b'\t' {
|
||||
write!(f, "\\t")?;
|
||||
} else if b == b'\\' || b == b'"' {
|
||||
write!(f, "\\{}", b as char)?;
|
||||
} else if b == b'\0' {
|
||||
write!(f, "\\0")?;
|
||||
// ASCII printable
|
||||
} else if b >= 0x20 && b < 0x7f {
|
||||
write!(f, "{}", b as char)?;
|
||||
} else {
|
||||
write!(f, "\\x{:02x}", b)?;
|
||||
}
|
||||
}
|
||||
write!(f, "\"")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Bytes {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
Debug::fmt(&BytesRef(&self.as_ref()), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for BytesMut {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
Debug::fmt(&BytesRef(&self.as_ref()), f)
|
||||
}
|
||||
}
|
|
@ -1,20 +1,20 @@
|
|||
use crate::{Bytes, BytesMut};
|
||||
use core::fmt::{Formatter, LowerHex, Result, UpperHex};
|
||||
|
||||
struct BytesRef<'a>(&'a [u8]);
|
||||
use super::BytesRef;
|
||||
use crate::{Bytes, BytesMut};
|
||||
|
||||
impl<'a> LowerHex for BytesRef<'a> {
|
||||
impl LowerHex for BytesRef<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
for b in self.0 {
|
||||
for &b in self.0 {
|
||||
write!(f, "{:02x}", b)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> UpperHex for BytesRef<'a> {
|
||||
impl UpperHex for BytesRef<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
for b in self.0 {
|
||||
for &b in self.0 {
|
||||
write!(f, "{:02X}", b)?;
|
||||
}
|
||||
Ok(())
|
|
@ -0,0 +1,5 @@
|
|||
mod debug;
|
||||
mod hex;
|
||||
|
||||
/// `BytesRef` is not a part of public API of bytes crate.
|
||||
struct BytesRef<'a>(&'a [u8]);
|
|
@ -1,5 +1,9 @@
|
|||
#![deny(warnings, missing_docs, missing_debug_implementations, rust_2018_idioms)]
|
||||
#![doc(html_root_url = "https://docs.rs/bytes/0.5.3")]
|
||||
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
|
||||
#![doc(test(
|
||||
no_crate_inject,
|
||||
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
|
||||
))]
|
||||
#![doc(html_root_url = "https://docs.rs/bytes/0.5.6")]
|
||||
#![no_std]
|
||||
|
||||
//! Provides abstractions for working with bytes.
|
||||
|
@ -72,25 +76,20 @@
|
|||
//! perform a syscall, which has the potential of failing. Operations on `Buf`
|
||||
//! and `BufMut` are infallible.
|
||||
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate std;
|
||||
|
||||
pub mod buf;
|
||||
pub use crate::buf::{
|
||||
Buf,
|
||||
BufMut,
|
||||
};
|
||||
pub use crate::buf::{Buf, BufMut};
|
||||
|
||||
mod bytes_mut;
|
||||
mod bytes;
|
||||
mod debug;
|
||||
mod hex;
|
||||
mod bytes_mut;
|
||||
mod fmt;
|
||||
mod loom;
|
||||
pub use crate::bytes_mut::BytesMut;
|
||||
pub use crate::bytes::Bytes;
|
||||
pub use crate::bytes_mut::BytesMut;
|
||||
|
||||
// Optional Serde support
|
||||
#[cfg(feature = "serde")]
|
||||
|
|
|
@ -2,8 +2,29 @@
|
|||
pub(crate) mod sync {
|
||||
pub(crate) mod atomic {
|
||||
pub(crate) use core::sync::atomic::{fence, AtomicPtr, AtomicUsize, Ordering};
|
||||
|
||||
pub(crate) trait AtomicMut<T> {
|
||||
fn with_mut<F, R>(&mut self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut *mut T) -> R;
|
||||
}
|
||||
|
||||
impl<T> AtomicMut<T> for AtomicPtr<T> {
|
||||
fn with_mut<F, R>(&mut self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut *mut T) -> R,
|
||||
{
|
||||
f(self.get_mut())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(test, loom))]
|
||||
pub(crate) use ::loom::sync;
|
||||
pub(crate) mod sync {
|
||||
pub(crate) mod atomic {
|
||||
pub(crate) use loom::sync::atomic::{fence, AtomicPtr, AtomicUsize, Ordering};
|
||||
|
||||
pub(crate) trait AtomicMut<T> {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
use super::{Bytes, BytesMut};
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use core::{cmp, fmt};
|
||||
use serde::{Serialize, Serializer, Deserialize, Deserializer, de};
|
||||
use super::{Bytes, BytesMut};
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
macro_rules! serde_impl {
|
||||
($ty:ident, $visitor_ty:ident, $from_slice:ident, $from_vec: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>
|
||||
where S: Serializer
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_bytes(&self)
|
||||
}
|
||||
|
@ -26,7 +27,8 @@ macro_rules! serde_impl {
|
|||
|
||||
#[inline]
|
||||
fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
|
||||
where V: de::SeqAccess<'de>
|
||||
where
|
||||
V: de::SeqAccess<'de>,
|
||||
{
|
||||
let len = cmp::min(seq.size_hint().unwrap_or(0), 4096);
|
||||
let mut values: Vec<u8> = Vec::with_capacity(len);
|
||||
|
@ -40,28 +42,32 @@ macro_rules! serde_impl {
|
|||
|
||||
#[inline]
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||
where E: de::Error
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok($ty::$from_slice(v))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||
where E: de::Error
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok($ty::$from_vec(v))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where E: de::Error
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok($ty::$from_slice(v.as_bytes()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||
where E: de::Error
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok($ty::$from_vec(v.into_bytes()))
|
||||
}
|
||||
|
@ -70,12 +76,13 @@ macro_rules! serde_impl {
|
|||
impl<'de> Deserialize<'de> for $ty {
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: D) -> Result<$ty, D::Error>
|
||||
where D: Deserializer<'de>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_byte_buf($visitor_ty)
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
serde_impl!(Bytes, BytesVisitor, copy_from_slice, from);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#![deny(warnings, rust_2018_idioms)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use bytes::Buf;
|
||||
#[cfg(feature = "std")]
|
||||
use std::io::IoSlice;
|
||||
|
||||
#[test]
|
||||
|
@ -42,6 +43,7 @@ fn test_get_u16_buffer_underflow() {
|
|||
buf.get_u16();
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn test_bufs_vec() {
|
||||
let buf = &b"hello world"[..];
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#![deny(warnings, rust_2018_idioms)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use bytes::{buf::IoSliceMut, BufMut, BytesMut};
|
||||
use std::usize;
|
||||
use std::fmt::Write;
|
||||
#[cfg(feature = "std")]
|
||||
use bytes::buf::IoSliceMut;
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use core::fmt::Write;
|
||||
use core::usize;
|
||||
|
||||
#[test]
|
||||
fn test_vec_as_mut_buf() {
|
||||
|
@ -45,13 +47,12 @@ fn test_put_u16() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "cannot advance")]
|
||||
fn test_vec_advance_mut() {
|
||||
// Regression test for carllerche/bytes#108.
|
||||
// Verify fix for #354
|
||||
let mut buf = Vec::with_capacity(8);
|
||||
unsafe {
|
||||
buf.advance_mut(12);
|
||||
assert_eq!(buf.len(), 12);
|
||||
assert!(buf.capacity() >= 12, "capacity: {}", buf.capacity());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,6 +66,7 @@ fn test_clone() {
|
|||
assert!(buf != buf2);
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn test_bufs_vec_mut() {
|
||||
let b1: &mut [u8] = &mut [];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![deny(warnings, rust_2018_idioms)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use bytes::{Bytes, BytesMut, Buf, BufMut};
|
||||
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
||||
|
||||
use std::usize;
|
||||
|
||||
|
@ -44,7 +44,6 @@ fn test_layout() {
|
|||
mem::size_of::<Option<BytesMut>>(),
|
||||
"BytesMut should be same size as Option<BytesMut>",
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -87,13 +86,11 @@ fn fmt_write() {
|
|||
write!(a, "{}", &s[..64]).unwrap();
|
||||
assert_eq!(a, s[..64].as_bytes());
|
||||
|
||||
|
||||
let mut b = BytesMut::with_capacity(64);
|
||||
write!(b, "{}", &s[..32]).unwrap();
|
||||
write!(b, "{}", &s[32..64]).unwrap();
|
||||
assert_eq!(b, s[..64].as_bytes());
|
||||
|
||||
|
||||
let mut c = BytesMut::with_capacity(64);
|
||||
write!(c, "{}", s).unwrap();
|
||||
assert_eq!(c, s[..].as_bytes());
|
||||
|
@ -305,11 +302,13 @@ fn split_off_to_at_gt_len() {
|
|||
|
||||
assert!(panic::catch_unwind(move || {
|
||||
let _ = make_bytes().split_to(5);
|
||||
}).is_err());
|
||||
})
|
||||
.is_err());
|
||||
|
||||
assert!(panic::catch_unwind(move || {
|
||||
let _ = make_bytes().split_off(5);
|
||||
}).is_err());
|
||||
})
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -342,6 +341,72 @@ fn freeze_clone_unique() {
|
|||
assert_eq!(c, s);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn freeze_after_advance() {
|
||||
let s = &b"abcdefgh"[..];
|
||||
let mut b = BytesMut::from(s);
|
||||
b.advance(1);
|
||||
assert_eq!(b, s[1..]);
|
||||
let b = b.freeze();
|
||||
// Verify fix for #352. Previously, freeze would ignore the start offset
|
||||
// for BytesMuts in Vec mode.
|
||||
assert_eq!(b, s[1..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn freeze_after_advance_arc() {
|
||||
let s = &b"abcdefgh"[..];
|
||||
let mut b = BytesMut::from(s);
|
||||
// Make b Arc
|
||||
let _ = b.split_to(0);
|
||||
b.advance(1);
|
||||
assert_eq!(b, s[1..]);
|
||||
let b = b.freeze();
|
||||
assert_eq!(b, s[1..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn freeze_after_split_to() {
|
||||
let s = &b"abcdefgh"[..];
|
||||
let mut b = BytesMut::from(s);
|
||||
let _ = b.split_to(1);
|
||||
assert_eq!(b, s[1..]);
|
||||
let b = b.freeze();
|
||||
assert_eq!(b, s[1..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn freeze_after_truncate() {
|
||||
let s = &b"abcdefgh"[..];
|
||||
let mut b = BytesMut::from(s);
|
||||
b.truncate(7);
|
||||
assert_eq!(b, s[..7]);
|
||||
let b = b.freeze();
|
||||
assert_eq!(b, s[..7]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn freeze_after_truncate_arc() {
|
||||
let s = &b"abcdefgh"[..];
|
||||
let mut b = BytesMut::from(s);
|
||||
// Make b Arc
|
||||
let _ = b.split_to(0);
|
||||
b.truncate(7);
|
||||
assert_eq!(b, s[..7]);
|
||||
let b = b.freeze();
|
||||
assert_eq!(b, s[..7]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn freeze_after_split_off() {
|
||||
let s = &b"abcdefgh"[..];
|
||||
let mut b = BytesMut::from(s);
|
||||
let _ = b.split_off(7);
|
||||
assert_eq!(b, s[..7]);
|
||||
let b = b.freeze();
|
||||
assert_eq!(b, s[..7]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fns_defined_for_bytes_mut() {
|
||||
let mut bytes = BytesMut::from(&b"hello world"[..]);
|
||||
|
@ -798,7 +863,6 @@ fn slice_ref_works() {
|
|||
test_slice_ref(&bytes, 9, 9, b"");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn slice_ref_empty() {
|
||||
let bytes = Bytes::from(&b""[..]);
|
||||
|
@ -808,6 +872,16 @@ fn slice_ref_empty() {
|
|||
assert_eq!(&sub[..], b"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slice_ref_empty_subslice() {
|
||||
let bytes = Bytes::from(&b"abcde"[..]);
|
||||
let subbytes = bytes.slice(0..0);
|
||||
let slice = &subbytes[..];
|
||||
// The `slice` object is derived from the original `bytes` object
|
||||
// so `slice_ref` should work.
|
||||
assert_eq!(Bytes::new(), bytes.slice_ref(slice));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn slice_ref_catches_not_a_subset() {
|
||||
|
@ -818,30 +892,19 @@ fn slice_ref_catches_not_a_subset() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn slice_ref_catches_not_an_empty_subset() {
|
||||
fn slice_ref_not_an_empty_subset() {
|
||||
let bytes = Bytes::from(&b"012345678"[..]);
|
||||
let slice = &b""[0..0];
|
||||
|
||||
bytes.slice_ref(slice);
|
||||
assert_eq!(Bytes::new(), bytes.slice_ref(slice));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn empty_slice_ref_catches_not_an_empty_subset() {
|
||||
fn empty_slice_ref_not_an_empty_subset() {
|
||||
let bytes = Bytes::new();
|
||||
let slice = &b"some other slice"[0..0];
|
||||
|
||||
// Protect this test against Bytes internals.
|
||||
//
|
||||
// This should panic *because* the slice's ptr doesn't fit in the range
|
||||
// of the `bytes`.
|
||||
if bytes.as_ptr() as usize == slice.as_ptr() as usize {
|
||||
// don't panic, failing the test
|
||||
return;
|
||||
}
|
||||
|
||||
bytes.slice_ref(slice);
|
||||
assert_eq!(Bytes::new(), bytes.slice_ref(slice));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -866,6 +929,22 @@ fn bytes_buf_mut_advance() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_buf_mut_reuse_when_fully_consumed() {
|
||||
use bytes::{Buf, BytesMut};
|
||||
let mut buf = BytesMut::new();
|
||||
buf.reserve(8192);
|
||||
buf.extend_from_slice(&[0u8; 100][..]);
|
||||
|
||||
let p = &buf[0] as *const u8;
|
||||
buf.advance(100);
|
||||
|
||||
buf.reserve(8192);
|
||||
buf.extend_from_slice(b" ");
|
||||
|
||||
assert_eq!(&buf[0] as *const u8, p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn bytes_reserve_overflow() {
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
//! Test using `Bytes` with an allocator that hands out "odd" pointers for
|
||||
//! vectors (pointers where the LSB is set).
|
||||
|
||||
use std::alloc::{GlobalAlloc, Layout, System};
|
||||
use std::ptr;
|
||||
|
||||
use bytes::Bytes;
|
||||
|
||||
#[global_allocator]
|
||||
static ODD: Odd = Odd;
|
||||
|
||||
struct Odd;
|
||||
|
||||
unsafe impl GlobalAlloc for Odd {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
if layout.align() == 1 && layout.size() > 0 {
|
||||
// Allocate slightly bigger so that we can offset the pointer by 1
|
||||
let size = layout.size() + 1;
|
||||
let new_layout = match Layout::from_size_align(size, 1) {
|
||||
Ok(layout) => layout,
|
||||
Err(_err) => return ptr::null_mut(),
|
||||
};
|
||||
let ptr = System.alloc(new_layout);
|
||||
if !ptr.is_null() {
|
||||
let ptr = ptr.offset(1);
|
||||
ptr
|
||||
} else {
|
||||
ptr
|
||||
}
|
||||
} else {
|
||||
System.alloc(layout)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||
if layout.align() == 1 && layout.size() > 0 {
|
||||
let size = layout.size() + 1;
|
||||
let new_layout = match Layout::from_size_align(size, 1) {
|
||||
Ok(layout) => layout,
|
||||
Err(_err) => std::process::abort(),
|
||||
};
|
||||
System.dealloc(ptr.offset(-1), new_layout);
|
||||
} else {
|
||||
System.dealloc(ptr, layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sanity_check_odd_allocator() {
|
||||
let vec = vec![33u8; 1024];
|
||||
let p = vec.as_ptr() as usize;
|
||||
assert!(p & 0x1 == 0x1, "{:#b}", p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bytes_from_vec_drop() {
|
||||
let vec = vec![33u8; 1024];
|
||||
let _b = Bytes::from(vec);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bytes_clone_drop() {
|
||||
let vec = vec![33u8; 1024];
|
||||
let b1 = Bytes::from(vec);
|
||||
let _b2 = b1.clone();
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
use std::alloc::{GlobalAlloc, Layout, System};
|
||||
use std::{mem, ptr};
|
||||
|
||||
use bytes::{Buf, Bytes};
|
||||
|
||||
#[global_allocator]
|
||||
static LEDGER: Ledger = Ledger;
|
||||
|
||||
struct Ledger;
|
||||
|
||||
const USIZE_SIZE: usize = mem::size_of::<usize>();
|
||||
|
||||
unsafe impl GlobalAlloc for Ledger {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
if layout.align() == 1 && layout.size() > 0 {
|
||||
// Allocate extra space to stash a record of
|
||||
// how much space there was.
|
||||
let orig_size = layout.size();
|
||||
let size = orig_size + USIZE_SIZE;
|
||||
let new_layout = match Layout::from_size_align(size, 1) {
|
||||
Ok(layout) => layout,
|
||||
Err(_err) => return ptr::null_mut(),
|
||||
};
|
||||
let ptr = System.alloc(new_layout);
|
||||
if !ptr.is_null() {
|
||||
(ptr as *mut usize).write(orig_size);
|
||||
let ptr = ptr.offset(USIZE_SIZE as isize);
|
||||
ptr
|
||||
} else {
|
||||
ptr
|
||||
}
|
||||
} else {
|
||||
System.alloc(layout)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||
if layout.align() == 1 && layout.size() > 0 {
|
||||
let off_ptr = (ptr as *mut usize).offset(-1);
|
||||
let orig_size = off_ptr.read();
|
||||
if orig_size != layout.size() {
|
||||
panic!(
|
||||
"bad dealloc: alloc size was {}, dealloc size is {}",
|
||||
orig_size,
|
||||
layout.size()
|
||||
);
|
||||
}
|
||||
|
||||
let new_layout = match Layout::from_size_align(layout.size() + USIZE_SIZE, 1) {
|
||||
Ok(layout) => layout,
|
||||
Err(_err) => std::process::abort(),
|
||||
};
|
||||
System.dealloc(off_ptr as *mut u8, new_layout);
|
||||
} else {
|
||||
System.dealloc(ptr, layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn test_bytes_advance() {
|
||||
let mut bytes = Bytes::from(vec![10, 20, 30]);
|
||||
bytes.advance(1);
|
||||
drop(bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bytes_truncate() {
|
||||
let mut bytes = Bytes::from(vec![10, 20, 30]);
|
||||
bytes.truncate(2);
|
||||
drop(bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bytes_truncate_and_advance() {
|
||||
let mut bytes = Bytes::from(vec![10, 20, 30]);
|
||||
bytes.truncate(2);
|
||||
bytes.advance(1);
|
||||
drop(bytes);
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
#![deny(warnings, rust_2018_idioms)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use bytes::{Buf, BufMut, Bytes};
|
||||
use bytes::buf::{BufExt, BufMutExt};
|
||||
use bytes::{Buf, BufMut, Bytes};
|
||||
#[cfg(feature = "std")]
|
||||
use std::io::IoSlice;
|
||||
|
||||
#[test]
|
||||
|
@ -42,6 +43,7 @@ fn iterating_two_bufs() {
|
|||
assert_eq!(res, &b"helloworld"[..]);
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn vectored_read() {
|
||||
let a = Bytes::from(&b"hello"[..]);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![deny(warnings, rust_2018_idioms)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use bytes::Bytes;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![deny(warnings, rust_2018_idioms)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use bytes::Bytes;
|
||||
|
||||
|
@ -11,7 +11,6 @@ fn iter_len() {
|
|||
assert_eq!(iter.len(), 11);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn empty_iter_len() {
|
||||
let buf = Bytes::from_static(b"");
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#![deny(warnings, rust_2018_idioms)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![cfg(feature = "std")]
|
||||
|
||||
use std::io::{BufRead, Read};
|
||||
|
||||
use bytes::buf::{BufExt};
|
||||
use bytes::buf::BufExt;
|
||||
|
||||
#[test]
|
||||
fn read() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#![cfg(feature = "serde")]
|
||||
#![deny(warnings, rust_2018_idioms)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use serde_test::{Token, assert_tokens};
|
||||
use serde_test::{assert_tokens, Token};
|
||||
|
||||
#[test]
|
||||
fn test_ser_de_empty() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![deny(warnings, rust_2018_idioms)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use bytes::buf::{Buf, BufExt};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче