diff -Nru rust-bytes-0.4.12/benches/buf.rs rust-bytes-1.1.0/benches/buf.rs --- rust-bytes-0.4.12/benches/buf.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/benches/buf.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,186 @@ +#![feature(test)] +#![warn(rust_2018_idioms)] + +extern crate test; + +use bytes::Buf; +use test::Bencher; + +/// Dummy Buf implementation +struct TestBuf { + buf: &'static [u8], + readlens: &'static [usize], + init_pos: usize, + pos: usize, + readlen_pos: usize, + readlen: usize, +} +impl TestBuf { + fn new(buf: &'static [u8], readlens: &'static [usize], init_pos: usize) -> TestBuf { + let mut buf = TestBuf { + buf, + readlens, + init_pos, + pos: 0, + readlen_pos: 0, + readlen: 0, + }; + buf.reset(); + buf + } + fn reset(&mut self) { + self.pos = self.init_pos; + self.readlen_pos = 0; + self.next_readlen(); + } + /// Compute the length of the next read : + /// - use the next value specified in readlens (capped by remaining) if any + /// - else the remaining + fn next_readlen(&mut self) { + self.readlen = self.buf.len() - self.pos; + if let Some(readlen) = self.readlens.get(self.readlen_pos) { + self.readlen = std::cmp::min(self.readlen, *readlen); + self.readlen_pos += 1; + } + } +} +impl Buf for TestBuf { + fn remaining(&self) -> usize { + return self.buf.len() - self.pos; + } + fn advance(&mut self, cnt: usize) { + self.pos += cnt; + assert!(self.pos <= self.buf.len()); + self.next_readlen(); + } + fn chunk(&self) -> &[u8] { + if self.readlen == 0 { + Default::default() + } else { + &self.buf[self.pos..self.pos + self.readlen] + } + } +} + +/// Dummy Buf implementation +/// version with methods forced to not be inlined (to simulate costly calls) +struct TestBufC { + inner: TestBuf, +} +impl TestBufC { + fn new(buf: &'static [u8], readlens: &'static [usize], init_pos: usize) -> TestBufC { + TestBufC { + inner: TestBuf::new(buf, readlens, init_pos), + } + } + fn reset(&mut self) { + self.inner.reset() + } +} +impl Buf for TestBufC { + #[inline(never)] + fn remaining(&self) -> usize { + self.inner.remaining() + } + #[inline(never)] + fn advance(&mut self, cnt: usize) { + self.inner.advance(cnt) + } + #[inline(never)] + fn chunk(&self) -> &[u8] { + self.inner.chunk() + } +} + +macro_rules! bench { + ($fname:ident, testbuf $testbuf:ident $readlens:expr, $method:ident $(,$arg:expr)*) => ( + #[bench] + fn $fname(b: &mut Bencher) { + let mut bufs = [ + $testbuf::new(&[1u8; 8+0], $readlens, 0), + $testbuf::new(&[1u8; 8+1], $readlens, 1), + $testbuf::new(&[1u8; 8+2], $readlens, 2), + $testbuf::new(&[1u8; 8+3], $readlens, 3), + $testbuf::new(&[1u8; 8+4], $readlens, 4), + $testbuf::new(&[1u8; 8+5], $readlens, 5), + $testbuf::new(&[1u8; 8+6], $readlens, 6), + $testbuf::new(&[1u8; 8+7], $readlens, 7), + ]; + b.iter(|| { + for i in 0..8 { + bufs[i].reset(); + let buf: &mut dyn Buf = &mut bufs[i]; // type erasure + test::black_box(buf.$method($($arg,)*)); + } + }) + } + ); + ($fname:ident, slice, $method:ident $(,$arg:expr)*) => ( + #[bench] + fn $fname(b: &mut Bencher) { + // buf must be long enough for one read of 8 bytes starting at pos 7 + let arr = [1u8; 8+7]; + b.iter(|| { + for i in 0..8 { + let mut buf = &arr[i..]; + let buf = &mut buf as &mut dyn Buf; // type erasure + test::black_box(buf.$method($($arg,)*)); + } + }) + } + ); + ($fname:ident, option) => ( + #[bench] + fn $fname(b: &mut Bencher) { + let data = [1u8; 1]; + b.iter(|| { + for _ in 0..8 { + let mut buf = Some(data); + let buf = &mut buf as &mut dyn Buf; // type erasure + test::black_box(buf.get_u8()); + } + }) + } + ); +} + +macro_rules! bench_group { + ($method:ident $(,$arg:expr)*) => ( + bench!(slice, slice, $method $(,$arg)*); + bench!(tbuf_1, testbuf TestBuf &[], $method $(,$arg)*); + bench!(tbuf_1_costly, testbuf TestBufC &[], $method $(,$arg)*); + bench!(tbuf_2, testbuf TestBuf &[1], $method $(,$arg)*); + bench!(tbuf_2_costly, testbuf TestBufC &[1], $method $(,$arg)*); + // bench!(tbuf_onebyone, testbuf TestBuf &[1,1,1,1,1,1,1,1], $method $(,$arg)*); + // bench!(tbuf_onebyone_costly, testbuf TestBufC &[1,1,1,1,1,1,1,1], $method $(,$arg)*); + ); +} + +mod get_u8 { + use super::*; + bench_group!(get_u8); +} +mod get_u16 { + use super::*; + bench_group!(get_u16); +} +mod get_u32 { + use super::*; + bench_group!(get_u32); +} +mod get_u64 { + use super::*; + bench_group!(get_u64); +} +mod get_f32 { + use super::*; + bench_group!(get_f32); +} +mod get_f64 { + use super::*; + bench_group!(get_f64); +} +mod get_uint24 { + use super::*; + bench_group!(get_uint, 3); +} diff -Nru rust-bytes-0.4.12/benches/bytes_mut.rs rust-bytes-1.1.0/benches/bytes_mut.rs --- rust-bytes-0.4.12/benches/bytes_mut.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/benches/bytes_mut.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,266 @@ +#![feature(test)] +#![warn(rust_2018_idioms)] + +extern crate test; + +use bytes::{BufMut, BytesMut}; +use test::Bencher; + +#[bench] +fn alloc_small(b: &mut Bencher) { + b.iter(|| { + for _ in 0..1024 { + test::black_box(BytesMut::with_capacity(12)); + } + }) +} + +#[bench] +fn alloc_mid(b: &mut Bencher) { + b.iter(|| { + test::black_box(BytesMut::with_capacity(128)); + }) +} + +#[bench] +fn alloc_big(b: &mut Bencher) { + b.iter(|| { + test::black_box(BytesMut::with_capacity(4096)); + }) +} + +#[bench] +fn deref_unique(b: &mut Bencher) { + let mut buf = BytesMut::with_capacity(4096); + buf.put(&[0u8; 1024][..]); + + b.iter(|| { + for _ in 0..1024 { + test::black_box(&buf[..]); + } + }) +} + +#[bench] +fn deref_unique_unroll(b: &mut Bencher) { + let mut buf = BytesMut::with_capacity(4096); + buf.put(&[0u8; 1024][..]); + + b.iter(|| { + for _ in 0..128 { + test::black_box(&buf[..]); + test::black_box(&buf[..]); + test::black_box(&buf[..]); + test::black_box(&buf[..]); + test::black_box(&buf[..]); + test::black_box(&buf[..]); + test::black_box(&buf[..]); + test::black_box(&buf[..]); + } + }) +} + +#[bench] +fn deref_shared(b: &mut Bencher) { + let mut buf = BytesMut::with_capacity(4096); + buf.put(&[0u8; 1024][..]); + let _b2 = buf.split_off(1024); + + b.iter(|| { + for _ in 0..1024 { + test::black_box(&buf[..]); + } + }) +} + +#[bench] +fn deref_two(b: &mut Bencher) { + let mut buf1 = BytesMut::with_capacity(8); + buf1.put(&[0u8; 8][..]); + + let mut buf2 = BytesMut::with_capacity(4096); + buf2.put(&[0u8; 1024][..]); + + b.iter(|| { + for _ in 0..512 { + test::black_box(&buf1[..]); + test::black_box(&buf2[..]); + } + }) +} + +#[bench] +fn clone_frozen(b: &mut Bencher) { + let bytes = BytesMut::from(&b"hello world 1234567890 and have a good byte 0987654321"[..]) + .split() + .freeze(); + + b.iter(|| { + for _ in 0..1024 { + test::black_box(&bytes.clone()); + } + }) +} + +#[bench] +fn alloc_write_split_to_mid(b: &mut Bencher) { + b.iter(|| { + let mut buf = BytesMut::with_capacity(128); + buf.put_slice(&[0u8; 64]); + test::black_box(buf.split_to(64)); + }) +} + +#[bench] +fn drain_write_drain(b: &mut Bencher) { + let data = [0u8; 128]; + + b.iter(|| { + let mut buf = BytesMut::with_capacity(1024); + let mut parts = Vec::with_capacity(8); + + for _ in 0..8 { + buf.put(&data[..]); + parts.push(buf.split_to(128)); + } + + test::black_box(parts); + }) +} + +#[bench] +fn fmt_write(b: &mut Bencher) { + use std::fmt::Write; + let mut buf = BytesMut::with_capacity(128); + let s = "foo bar baz quux lorem ipsum dolor et"; + + b.bytes = s.len() as u64; + b.iter(|| { + let _ = write!(buf, "{}", s); + test::black_box(&buf); + unsafe { + buf.set_len(0); + } + }) +} + +#[bench] +fn bytes_mut_extend(b: &mut Bencher) { + let mut buf = BytesMut::with_capacity(256); + let data = [33u8; 32]; + + b.bytes = data.len() as u64 * 4; + b.iter(|| { + for _ in 0..4 { + buf.extend(&data); + } + test::black_box(&buf); + unsafe { + buf.set_len(0); + } + }); +} + +// BufMut for BytesMut vs Vec + +#[bench] +fn put_slice_bytes_mut(b: &mut Bencher) { + let mut buf = BytesMut::with_capacity(256); + let data = [33u8; 32]; + + b.bytes = data.len() as u64 * 4; + b.iter(|| { + for _ in 0..4 { + buf.put_slice(&data); + } + test::black_box(&buf); + unsafe { + buf.set_len(0); + } + }); +} + +#[bench] +fn put_u8_bytes_mut(b: &mut Bencher) { + let mut buf = BytesMut::with_capacity(256); + let cnt = 128; + + b.bytes = cnt as u64; + b.iter(|| { + for _ in 0..cnt { + buf.put_u8(b'x'); + } + test::black_box(&buf); + unsafe { + buf.set_len(0); + } + }); +} + +#[bench] +fn put_slice_vec(b: &mut Bencher) { + let mut buf = Vec::::with_capacity(256); + let data = [33u8; 32]; + + b.bytes = data.len() as u64 * 4; + b.iter(|| { + for _ in 0..4 { + buf.put_slice(&data); + } + test::black_box(&buf); + unsafe { + buf.set_len(0); + } + }); +} + +#[bench] +fn put_u8_vec(b: &mut Bencher) { + let mut buf = Vec::::with_capacity(256); + let cnt = 128; + + b.bytes = cnt as u64; + b.iter(|| { + for _ in 0..cnt { + buf.put_u8(b'x'); + } + test::black_box(&buf); + unsafe { + buf.set_len(0); + } + }); +} + +#[bench] +fn put_slice_vec_extend(b: &mut Bencher) { + let mut buf = Vec::::with_capacity(256); + let data = [33u8; 32]; + + b.bytes = data.len() as u64 * 4; + b.iter(|| { + for _ in 0..4 { + buf.extend_from_slice(&data); + } + test::black_box(&buf); + unsafe { + buf.set_len(0); + } + }); +} + +#[bench] +fn put_u8_vec_push(b: &mut Bencher) { + let mut buf = Vec::::with_capacity(256); + let cnt = 128; + + b.bytes = cnt as u64; + b.iter(|| { + for _ in 0..cnt { + buf.push(b'x'); + } + test::black_box(&buf); + unsafe { + buf.set_len(0); + } + }); +} diff -Nru rust-bytes-0.4.12/benches/bytes.rs rust-bytes-1.1.0/benches/bytes.rs --- rust-bytes-0.4.12/benches/bytes.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/benches/bytes.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,50 +1,14 @@ #![feature(test)] +#![warn(rust_2018_idioms)] -extern crate bytes; extern crate test; +use bytes::Bytes; use test::Bencher; -use bytes::{Bytes, BytesMut, BufMut}; - -#[bench] -fn alloc_small(b: &mut Bencher) { - b.iter(|| { - for _ in 0..1024 { - test::black_box(BytesMut::with_capacity(12)); - } - }) -} - -#[bench] -fn alloc_mid(b: &mut Bencher) { - b.iter(|| { - test::black_box(BytesMut::with_capacity(128)); - }) -} - -#[bench] -fn alloc_big(b: &mut Bencher) { - b.iter(|| { - test::black_box(BytesMut::with_capacity(4096)); - }) -} - -#[bench] -fn split_off_and_drop(b: &mut Bencher) { - b.iter(|| { - for _ in 0..1024 { - let v = vec![10; 200]; - let mut b = Bytes::from(v); - test::black_box(b.split_off(100)); - test::black_box(b); - } - }) -} #[bench] fn deref_unique(b: &mut Bencher) { - let mut buf = BytesMut::with_capacity(4096); - buf.put(&[0u8; 1024][..]); + let buf = Bytes::from(vec![0; 1024]); b.iter(|| { for _ in 0..1024 { @@ -54,29 +18,9 @@ } #[bench] -fn deref_unique_unroll(b: &mut Bencher) { - let mut buf = BytesMut::with_capacity(4096); - buf.put(&[0u8; 1024][..]); - - b.iter(|| { - for _ in 0..128 { - test::black_box(&buf[..]); - test::black_box(&buf[..]); - test::black_box(&buf[..]); - test::black_box(&buf[..]); - test::black_box(&buf[..]); - test::black_box(&buf[..]); - test::black_box(&buf[..]); - test::black_box(&buf[..]); - } - }) -} - -#[bench] fn deref_shared(b: &mut Bencher) { - let mut buf = BytesMut::with_capacity(4096); - buf.put(&[0u8; 1024][..]); - let _b2 = buf.split_off(1024); + let buf = Bytes::from(vec![0; 1024]); + let _b2 = buf.clone(); b.iter(|| { for _ in 0..1024 { @@ -86,9 +30,8 @@ } #[bench] -fn deref_inline(b: &mut Bencher) { - let mut buf = BytesMut::with_capacity(8); - buf.put(&[0u8; 8][..]); +fn deref_static(b: &mut Bencher) { + let buf = Bytes::from_static(b"hello world"); b.iter(|| { for _ in 0..1024 { @@ -98,24 +41,9 @@ } #[bench] -fn deref_two(b: &mut Bencher) { - let mut buf1 = BytesMut::with_capacity(8); - buf1.put(&[0u8; 8][..]); - - let mut buf2 = BytesMut::with_capacity(4096); - buf2.put(&[0u8; 1024][..]); - - b.iter(|| { - for _ in 0..512 { - test::black_box(&buf1[..]); - test::black_box(&buf2[..]); - } - }) -} - -#[bench] -fn clone_inline(b: &mut Bencher) { - let bytes = Bytes::from_static(b"hello world"); +fn clone_static(b: &mut Bencher) { + let bytes = + Bytes::from_static("hello world 1234567890 and have a good byte 0987654321".as_bytes()); b.iter(|| { for _ in 0..1024 { @@ -125,8 +53,8 @@ } #[bench] -fn clone_static(b: &mut Bencher) { - let bytes = Bytes::from_static("hello world 1234567890 and have a good byte 0987654321".as_bytes()); +fn clone_shared(b: &mut Bencher) { + let bytes = Bytes::from(b"hello world 1234567890 and have a good byte 0987654321".to_vec()); b.iter(|| { for _ in 0..1024 { @@ -136,8 +64,9 @@ } #[bench] -fn clone_arc(b: &mut Bencher) { - let bytes = Bytes::from("hello world 1234567890 and have a good byte 0987654321".as_bytes()); +fn clone_arc_vec(b: &mut Bencher) { + use std::sync::Arc; + let bytes = Arc::new(b"hello world 1234567890 and have a good byte 0987654321".to_vec()); b.iter(|| { for _ in 0..1024 { @@ -147,51 +76,11 @@ } #[bench] -fn alloc_write_split_to_mid(b: &mut Bencher) { - b.iter(|| { - let mut buf = BytesMut::with_capacity(128); - buf.put_slice(&[0u8; 64]); - test::black_box(buf.split_to(64)); - }) -} - -#[bench] -fn drain_write_drain(b: &mut Bencher) { - let data = [0u8; 128]; - - b.iter(|| { - let mut buf = BytesMut::with_capacity(1024); - let mut parts = Vec::with_capacity(8); - - for _ in 0..8 { - buf.put(&data[..]); - parts.push(buf.split_to(128)); - } - - test::black_box(parts); - }) -} - -#[bench] -fn fmt_write(b: &mut Bencher) { - use std::fmt::Write; - let mut buf = BytesMut::with_capacity(128); - let s = "foo bar baz quux lorem ipsum dolor et"; - - b.bytes = s.len() as u64; - b.iter(|| { - let _ = write!(buf, "{}", s); - test::black_box(&buf); - unsafe { buf.set_len(0); } - }) -} - -#[bench] fn from_long_slice(b: &mut Bencher) { let data = [0u8; 128]; b.bytes = data.len() as u64; b.iter(|| { - let buf = BytesMut::from(&data[..]); + let buf = Bytes::copy_from_slice(&data[..]); test::black_box(buf); }) } @@ -201,7 +90,7 @@ b.iter(|| { let b = Bytes::from(vec![17; 1024]).clone(); for i in 0..1000 { - test::black_box(b.slice(i % 100, i % 100)); + test::black_box(b.slice(i % 100..i % 100)); } }) } @@ -212,39 +101,19 @@ // `clone` is to convert to ARC let b = Bytes::from(vec![17; 1024]).clone(); for i in 0..1000 { - test::black_box(b.slice(1, 2 + i % 10)); + test::black_box(b.slice(1..2 + i % 10)); } }) } -// Keep in sync with bytes.rs -#[cfg(target_pointer_width = "64")] -const INLINE_CAP: usize = 4 * 8 - 1; -#[cfg(target_pointer_width = "32")] -const INLINE_CAP: usize = 4 * 4 - 1; - #[bench] -fn slice_avg_le_inline_from_arc(b: &mut Bencher) { - b.iter(|| { - // `clone` is to convert to ARC - let b = Bytes::from(vec![17; 1024]).clone(); - for i in 0..1000 { - // [1, INLINE_CAP] - let len = 1 + i % (INLINE_CAP - 1); - test::black_box(b.slice(i % 10, i % 10 + len)); - } - }) -} - -#[bench] -fn slice_large_le_inline_from_arc(b: &mut Bencher) { +fn split_off_and_drop(b: &mut Bencher) { b.iter(|| { - // `clone` is to convert to ARC - let b = Bytes::from(vec![17; 1024]).clone(); - for i in 0..1000 { - // [INLINE_CAP - 10, INLINE_CAP] - let len = INLINE_CAP - 9 + i % 10; - test::black_box(b.slice(i % 10, i % 10 + len)); + for _ in 0..1024 { + let v = vec![10; 200]; + let mut b = Bytes::from(v); + test::black_box(b.split_off(100)); + test::black_box(b); } }) } diff -Nru rust-bytes-0.4.12/Cargo.toml rust-bytes-1.1.0/Cargo.toml --- rust-bytes-0.4.12/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/Cargo.toml 1970-01-01 00:00:01.000000000 +0000 @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -11,36 +11,28 @@ # will likely look very different (and much more reasonable) [package] +edition = "2018" name = "bytes" -version = "0.4.12" -authors = ["Carl Lerche "] -exclude = [".gitignore", ".travis.yml", "deploy.sh", "bench/**/*", "test/**/*"] +version = "1.1.0" +authors = ["Carl Lerche ", "Sean McArthur "] description = "Types and traits for working with bytes" -homepage = "https://github.com/carllerche/bytes" -documentation = "https://docs.rs/bytes/0.4.12/bytes" readme = "README.md" keywords = ["buffers", "zero-copy", "io"] categories = ["network-programming", "data-structures"] license = "MIT" -repository = "https://github.com/carllerche/bytes" +repository = "https://github.com/tokio-rs/bytes" [package.metadata.docs.rs] -features = ["i128"] -[dependencies.byteorder] -version = "1.1.0" - -[dependencies.either] -version = "1.5" -optional = true -default-features = false - -[dependencies.iovec] -version = "0.1" - +rustdoc-args = ["--cfg", "docsrs"] [dependencies.serde] -version = "1.0" +version = "1.0.60" +features = ["alloc"] optional = true +default-features = false [dev-dependencies.serde_test] version = "1.0" [features] -i128 = ["byteorder/i128"] +default = ["std"] +std = [] +[target."cfg(loom)".dev-dependencies.loom] +version = "0.5" diff -Nru rust-bytes-0.4.12/Cargo.toml.orig rust-bytes-1.1.0/Cargo.toml.orig --- rust-bytes-0.4.12/Cargo.toml.orig 2019-03-06 20:42:31.000000000 +0000 +++ rust-bytes-1.1.0/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -1,40 +1,34 @@ [package] -name = "bytes" +name = "bytes" # When releasing to crates.io: -# - Update html_root_url. # - Update CHANGELOG.md. -# - Update doc URL. -# - Create "v0.4.x" git tag. -version = "0.4.12" -license = "MIT" -authors = ["Carl Lerche "] -description = "Types and traits for working with bytes" -documentation = "https://docs.rs/bytes/0.4.12/bytes" -homepage = "https://github.com/carllerche/bytes" -repository = "https://github.com/carllerche/bytes" -readme = "README.md" -keywords = ["buffers", "zero-copy", "io"] -exclude = [ - ".gitignore", - ".travis.yml", - "deploy.sh", - "bench/**/*", - "test/**/*" +# - Create "v1.x.y" git tag. +version = "1.1.0" +license = "MIT" +authors = [ + "Carl Lerche ", + "Sean McArthur ", ] +description = "Types and traits for working with bytes" +repository = "https://github.com/tokio-rs/bytes" +readme = "README.md" +keywords = ["buffers", "zero-copy", "io"] categories = ["network-programming", "data-structures"] +edition = "2018" -[package.metadata.docs.rs] -features = ["i128"] +[features] +default = ["std"] +std = [] [dependencies] -byteorder = "1.1.0" -iovec = "0.1" -serde = { version = "1.0", optional = true } -either = { version = "1.5", default-features = false, optional = true } +serde = { version = "1.0.60", optional = true, default-features = false, features = ["alloc"] } [dev-dependencies] serde_test = "1.0" -[features] -i128 = ["byteorder/i128"] +[target.'cfg(loom)'.dev-dependencies] +loom = "0.5" + +[package.metadata.docs.rs] +rustdoc-args = ["--cfg", "docsrs"] diff -Nru rust-bytes-0.4.12/.cargo_vcs_info.json rust-bytes-1.1.0/.cargo_vcs_info.json --- rust-bytes-0.4.12/.cargo_vcs_info.json 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/.cargo_vcs_info.json 1970-01-01 00:00:01.000000000 +0000 @@ -1,5 +1,5 @@ { "git": { - "sha1": "4948b1053b1af8f474a107b958dd0086ada06b17" + "sha1": "ebc61e5af14cd9b436ba880cf19e849b05a04c29" } } diff -Nru rust-bytes-0.4.12/CHANGELOG.md rust-bytes-1.1.0/CHANGELOG.md --- rust-bytes-0.4.12/CHANGELOG.md 2019-03-06 20:42:31.000000000 +0000 +++ rust-bytes-1.1.0/CHANGELOG.md 1973-11-29 21:33:09.000000000 +0000 @@ -1,4 +1,138 @@ -# 0.4.12 (March 6, 2018) +# 1.1.0 (August 25, 2021) + +### Added + +- `BufMut::put_bytes(self, val, cnt)` (#487) +- Implement `From>` for `Bytes` (#504) + +### Changed + +- Override `put_slice` for `&mut [u8]` (#483) +- Panic on integer overflow in `Chain::remaining` (#482) +- Add inline tags to `UninitSlice` methods (#443) +- Override `copy_to_bytes` for Chain and Take (#481) +- Keep capacity when unsplit on empty other buf (#502) + +### Documented + +- Clarify `BufMut` allocation guarantees (#501) +- Clarify `BufMut::put_int` behavior (#486) +- Clarify actions of `clear` and `truncate`. (#508) + +# 1.0.1 (January 11, 2021) + +### Changed +- mark `Vec::put_slice` with `#[inline]` (#459) + +### Fixed +- Fix deprecation warning (#457) +- use `Box::into_raw` instead of `mem::forget`-in-disguise (#458) + +# 1.0.0 (December 22, 2020) + +### Changed +- Rename `Buf`/`BufMut` methods `bytes()` and `bytes_mut()` to `chunk()` and `chunk_mut()` (#450) + +### Removed +- remove unused Buf implementation. (#449) + +# 0.6.0 (October 21, 2020) + +API polish in preparation for a 1.0 release. + +### Changed +- `BufMut` is now an `unsafe` trait (#432). +- `BufMut::bytes_mut()` returns `&mut UninitSlice`, a type owned by `bytes` to + avoid undefined behavior (#433). +- `Buf::copy_to_bytes(len)` replaces `Buf::into_bytes()` (#439). +- `Buf`/`BufMut` utility methods are moved onto the trait and `*Ext` traits are + removed (#431). + +### Removed +- `BufMut::bytes_vectored_mut()` (#430). +- `new` methods on combinator types (#434). + +# 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` 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 +- `must_use` attributes to `split`, `split_off`, and `split_to` methods (#337). + +### Fix +- Potential freeing of a null pointer in `Bytes` when constructed with an empty `Vec` (#341, #342). +- Calling `Bytes::truncate` with a size large than the length will no longer clear the `Bytes` (#333). + +# 0.5.2 (November 27, 2019) + +### Added +- `Limit` methods `into_inner`, `get_ref`, `get_mut`, `limit`, and `set_limit` (#325). + +# 0.5.1 (November 25, 2019) + +### Fix +- Growth documentation for `BytesMut` (#321) + +# 0.5.0 (November 25, 2019) + +### Fix +- Potential overflow in `copy_to_slice` + +### Changed +- Increased minimum supported Rust version to 1.39. +- `Bytes` is now a "trait object", allowing for custom allocation strategies (#298) +- `BytesMut` implicitly grows internal storage. `remaining_mut()` returns + `usize::MAX` (#316). +- `BufMut::bytes_mut` returns `&mut [MaybeUninit]` to reflect the unknown + initialization state (#305). +- `Buf` / `BufMut` implementations for `&[u8]` and `&mut [u8]` + respectively (#261). +- Move `Buf` / `BufMut` "extra" functions to an extension trait (#306). +- `BufMutExt::limit` (#309). +- `Bytes::slice` takes a `RangeBounds` argument (#265). +- `Bytes::from_static` is now a `const fn` (#311). +- A multitude of smaller performance optimizations. + +### Added +- `no_std` support (#281). +- `get_*`, `put_*`, `get_*_le`, and `put_*le` accessors for handling byte order. +- `BorrowMut` implementation for `BytesMut` (#185). + +### Removed +- `IntoBuf` (#288). +- `Buf` implementation for `&str` (#301). +- `byteorder` dependency (#280). +- `iovec` dependency, use `std::IoSlice` instead (#263). +- optional `either` dependency (#315). +- optional `i128` feature -- now available on stable. (#276). + +# 0.4.12 (March 6, 2019) ### Added - Implement `FromIterator<&'a u8>` for `BytesMut`/`Bytes` (#244). diff -Nru rust-bytes-0.4.12/ci/before_deploy.ps1 rust-bytes-1.1.0/ci/before_deploy.ps1 --- rust-bytes-0.4.12/ci/before_deploy.ps1 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/ci/before_deploy.ps1 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -# This script takes care of packaging the build artifacts that will go in the -# release zipfile - -$SRC_DIR = $PWD.Path -$STAGE = [System.Guid]::NewGuid().ToString() - -Set-Location $ENV:Temp -New-Item -Type Directory -Name $STAGE -Set-Location $STAGE - -$ZIP = "$SRC_DIR\$($Env:CRATE_NAME)-$($Env:APPVEYOR_REPO_TAG_NAME)-$($Env:TARGET).zip" - -# TODO Update this to package the right artifacts -Copy-Item "$SRC_DIR\target\$($Env:TARGET)\release\hello.exe" '.\' - -7z a "$ZIP" * - -Push-AppveyorArtifact "$ZIP" - -Remove-Item *.* -Force -Set-Location .. -Remove-Item $STAGE -Set-Location $SRC_DIR diff -Nru rust-bytes-0.4.12/ci/before_deploy.sh rust-bytes-1.1.0/ci/before_deploy.sh --- rust-bytes-0.4.12/ci/before_deploy.sh 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/ci/before_deploy.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -# This script takes care of building your crate and packaging it for release - -set -ex - -main() { - local src=$(pwd) \ - stage= - - case $TRAVIS_OS_NAME in - linux) - stage=$(mktemp -d) - ;; - osx) - stage=$(mktemp -d -t tmp) - ;; - esac - - test -f Cargo.lock || cargo generate-lockfile - - # TODO Update this to build the artifacts that matter to you - cross rustc --bin hello --target $TARGET --release -- -C lto - - # TODO Update this to package the right artifacts - cp target/$TARGET/release/hello $stage/ - - cd $stage - tar czf $src/$CRATE_NAME-$TRAVIS_TAG-$TARGET.tar.gz * - cd $src - - rm -rf $stage -} - -main diff -Nru rust-bytes-0.4.12/ci/install.sh rust-bytes-1.1.0/ci/install.sh --- rust-bytes-0.4.12/ci/install.sh 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/ci/install.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -set -ex - -main() { - curl https://sh.rustup.rs -sSf | \ - sh -s -- -y --default-toolchain $TRAVIS_RUST_VERSION - - local target= - if [ $TRAVIS_OS_NAME = linux ]; then - target=x86_64-unknown-linux-gnu - sort=sort - else - target=x86_64-apple-darwin - sort=gsort # for `sort --sort-version`, from brew's coreutils. - fi - - # This fetches latest stable release - local tag=$(git ls-remote --tags --refs --exit-code https://github.com/japaric/cross \ - | cut -d/ -f3 \ - | grep -E '^v[0-9.]+$' \ - | $sort --version-sort \ - | tail -n1) - echo cross version: $tag - curl -LSfs https://japaric.github.io/trust/install.sh | \ - sh -s -- \ - --force \ - --git japaric/cross \ - --tag $tag \ - --target $target -} - -main diff -Nru rust-bytes-0.4.12/ci/miri.sh rust-bytes-1.1.0/ci/miri.sh --- rust-bytes-0.4.12/ci/miri.sh 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/ci/miri.sh 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,11 @@ +#!/bin/bash +set -e + +MIRI_NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri) +echo "Installing latest nightly with Miri: $MIRI_NIGHTLY" +rustup set profile minimal +rustup default "$MIRI_NIGHTLY" +rustup component add miri + +cargo miri test +cargo miri test --target mips64-unknown-linux-gnuabi64 diff -Nru rust-bytes-0.4.12/ci/script.sh rust-bytes-1.1.0/ci/script.sh --- rust-bytes-0.4.12/ci/script.sh 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/ci/script.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -# This script takes care of testing your crate - -set -ex - -main() { - cross build --target $TARGET $EXTRA_ARGS - - if [ ! -z $DISABLE_TESTS ]; then - return - fi - - cross test --target $TARGET $EXTRA_ARGS -} - -# we don't run the "test phase" when doing deploys -if [ -z $TRAVIS_TAG ]; then - main -fi diff -Nru rust-bytes-0.4.12/ci/test-stable.sh rust-bytes-1.1.0/ci/test-stable.sh --- rust-bytes-0.4.12/ci/test-stable.sh 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/ci/test-stable.sh 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,28 @@ +#!/bin/bash + +set -ex + +cmd="${1:-test}" + +# Install cargo-hack for feature flag test +host=$(rustc -Vv | grep host | sed 's/host: //') +curl -LsSf https://github.com/taiki-e/cargo-hack/releases/latest/download/cargo-hack-$host.tar.gz | tar xzf - -C ~/.cargo/bin + +# Run with each feature +# * --each-feature includes both default/no-default features +# * --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 diff -Nru rust-bytes-0.4.12/ci/tsan rust-bytes-1.1.0/ci/tsan --- rust-bytes-0.4.12/ci/tsan 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/ci/tsan 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +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 - -# Some test runtime races. Allocation should be race free -race:alloc::alloc - -# 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 - -# 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 diff -Nru rust-bytes-0.4.12/ci/tsan.sh rust-bytes-1.1.0/ci/tsan.sh --- rust-bytes-0.4.12/ci/tsan.sh 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/ci/tsan.sh 1973-11-29 21:33:09.000000000 +0000 @@ -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 diff -Nru rust-bytes-0.4.12/debian/cargo-checksum.json rust-bytes-1.1.0/debian/cargo-checksum.json --- rust-bytes-0.4.12/debian/cargo-checksum.json 2019-07-12 12:29:35.000000000 +0000 +++ rust-bytes-1.1.0/debian/cargo-checksum.json 2021-11-28 22:37:58.000000000 +0000 @@ -1 +1 @@ -{"package":"206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c","files":{}} +{"package":"c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8","files":{}} diff -Nru rust-bytes-0.4.12/debian/changelog rust-bytes-1.1.0/debian/changelog --- rust-bytes-0.4.12/debian/changelog 2019-07-12 12:29:35.000000000 +0000 +++ rust-bytes-1.1.0/debian/changelog 2021-11-28 22:37:58.000000000 +0000 @@ -1,3 +1,10 @@ +rust-bytes (1.1.0-1) unstable; urgency=medium + + * Team upload. + * Package bytes 1.1.0 from crates.io using debcargo 2.4.4 + + -- Henry-Nicolas Tourneur Sun, 28 Nov 2021 23:37:58 +0100 + rust-bytes (0.4.12-1) unstable; urgency=medium * Package bytes 0.4.12 from crates.io using debcargo 2.2.10 diff -Nru rust-bytes-0.4.12/debian/compat rust-bytes-1.1.0/debian/compat --- rust-bytes-0.4.12/debian/compat 2019-07-12 12:29:35.000000000 +0000 +++ rust-bytes-1.1.0/debian/compat 2021-11-28 22:37:58.000000000 +0000 @@ -1 +1 @@ -11 +12 diff -Nru rust-bytes-0.4.12/debian/control rust-bytes-1.1.0/debian/control --- rust-bytes-0.4.12/debian/control 2019-07-12 12:29:35.000000000 +0000 +++ rust-bytes-1.1.0/debian/control 2021-11-28 22:37:58.000000000 +0000 @@ -1,87 +1,55 @@ Source: rust-bytes Section: rust Priority: optional -Build-Depends: debhelper (>= 11), - dh-cargo (>= 15), +Build-Depends: debhelper (>= 12), + dh-cargo (>= 24), cargo:native , rustc:native , - libstd-rust-dev , - librust-byteorder-1+default-dev (>= 1.1.0-~~) , - librust-iovec-0.1+default-dev + libstd-rust-dev Maintainer: Debian Rust Maintainers Uploaders: Ximin Luo , kpcyrd , Robin Krahl -Standards-Version: 4.2.0 +Standards-Version: 4.5.1 Vcs-Git: https://salsa.debian.org/rust-team/debcargo-conf.git [src/bytes] Vcs-Browser: https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/bytes -Homepage: https://github.com/carllerche/bytes +Rules-Requires-Root: no Package: librust-bytes-dev Architecture: any Multi-Arch: same Depends: - ${misc:Depends}, - librust-byteorder-1+default-dev (>= 1.1.0-~~), - librust-iovec-0.1+default-dev + ${misc:Depends} Suggests: - librust-bytes+either-dev (= ${binary:Version}), - librust-bytes+i128-dev (= ${binary:Version}), librust-bytes+serde-dev (= ${binary:Version}) Provides: librust-bytes+default-dev (= ${binary:Version}), - librust-bytes-0-dev (= ${binary:Version}), - librust-bytes-0+default-dev (= ${binary:Version}), - librust-bytes-0.4-dev (= ${binary:Version}), - librust-bytes-0.4+default-dev (= ${binary:Version}), - librust-bytes-0.4.12-dev (= ${binary:Version}), - librust-bytes-0.4.12+default-dev (= ${binary:Version}) + librust-bytes+std-dev (= ${binary:Version}), + librust-bytes-1-dev (= ${binary:Version}), + librust-bytes-1+default-dev (= ${binary:Version}), + librust-bytes-1+std-dev (= ${binary:Version}), + librust-bytes-1.1-dev (= ${binary:Version}), + librust-bytes-1.1+default-dev (= ${binary:Version}), + librust-bytes-1.1+std-dev (= ${binary:Version}), + librust-bytes-1.1.0-dev (= ${binary:Version}), + librust-bytes-1.1.0+default-dev (= ${binary:Version}), + librust-bytes-1.1.0+std-dev (= ${binary:Version}) Description: Types and traits for working with bytes - Rust source code This package contains the source for the Rust bytes crate, packaged by debcargo for use with cargo and dh-cargo. -Package: librust-bytes+either-dev -Architecture: any -Multi-Arch: same -Depends: - ${misc:Depends}, - librust-bytes-dev (= ${binary:Version}), - librust-either-1-dev (>= 1.5-~~) -Provides: - librust-bytes-0+either-dev (= ${binary:Version}), - librust-bytes-0.4+either-dev (= ${binary:Version}), - librust-bytes-0.4.12+either-dev (= ${binary:Version}) -Description: Types and traits for working with bytes - feature "either" - This metapackage enables feature either for the Rust bytes crate, by pulling in - any additional dependencies needed by that feature. - -Package: librust-bytes+i128-dev -Architecture: any -Multi-Arch: same -Depends: - ${misc:Depends}, - librust-bytes-dev (= ${binary:Version}), - librust-byteorder-1+i128-dev (>= 1.1.0-~~) -Provides: - librust-bytes-0+i128-dev (= ${binary:Version}), - librust-bytes-0.4+i128-dev (= ${binary:Version}), - librust-bytes-0.4.12+i128-dev (= ${binary:Version}) -Description: Types and traits for working with bytes - feature "i128" - This metapackage enables feature i128 for the Rust bytes crate, by pulling in - any additional dependencies needed by that feature. - Package: librust-bytes+serde-dev Architecture: any Multi-Arch: same Depends: ${misc:Depends}, librust-bytes-dev (= ${binary:Version}), - librust-serde-1+default-dev + librust-serde-1+alloc-dev (>= 1.0.60-~~) Provides: - librust-bytes-0+serde-dev (= ${binary:Version}), - librust-bytes-0.4+serde-dev (= ${binary:Version}), - librust-bytes-0.4.12+serde-dev (= ${binary:Version}) + librust-bytes-1+serde-dev (= ${binary:Version}), + librust-bytes-1.1+serde-dev (= ${binary:Version}), + librust-bytes-1.1.0+serde-dev (= ${binary:Version}) Description: Types and traits for working with bytes - feature "serde" - This metapackage enables feature serde for the Rust bytes crate, by pulling in - any additional dependencies needed by that feature. + This metapackage enables feature "serde" for the Rust bytes crate, by pulling + in any additional dependencies needed by that feature. diff -Nru rust-bytes-0.4.12/debian/copyright.debcargo.hint rust-bytes-1.1.0/debian/copyright.debcargo.hint --- rust-bytes-0.4.12/debian/copyright.debcargo.hint 2019-07-12 12:29:35.000000000 +0000 +++ rust-bytes-1.1.0/debian/copyright.debcargo.hint 2021-11-28 22:37:58.000000000 +0000 @@ -1,10 +1,14 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: bytes -Upstream-Contact: Carl Lerche -Source: https://github.com/carllerche/bytes +Upstream-Contact: + Carl Lerche + Sean McArthur +Source: https://github.com/tokio-rs/bytes Files: * -Copyright: FIXME (overlay) UNKNOWN-YEARS Carl Lerche +Copyright: + FIXME (overlay) UNKNOWN-YEARS Carl Lerche + FIXME (overlay) UNKNOWN-YEARS Sean McArthur License: MIT Comment: FIXME (overlay): Since upstream copyright years are not available in @@ -21,10 +25,10 @@ Files: debian/* Copyright: - 2018-2019 Debian Rust Maintainers - 2018-2019 Ximin Luo - 2018-2019 kpcyrd - 2018-2019 Robin Krahl + 2018-2021 Debian Rust Maintainers + 2018-2021 Ximin Luo + 2018-2021 kpcyrd + 2018-2021 Robin Krahl License: MIT License: MIT diff -Nru rust-bytes-0.4.12/debian/tests/control rust-bytes-1.1.0/debian/tests/control --- rust-bytes-0.4.12/debian/tests/control 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/debian/tests/control 2021-11-28 22:37:58.000000000 +0000 @@ -0,0 +1,24 @@ +Test-Command: /usr/share/cargo/bin/cargo-auto-test bytes 1.1.0 --all-targets --all-features +Features: test-name=rust-bytes:@ +Depends: dh-cargo (>= 18), librust-loom-0.5+default-dev, librust-serde-test-1+default-dev, @ +Restrictions: allow-stderr, skip-not-installable + +Test-Command: /usr/share/cargo/bin/cargo-auto-test bytes 1.1.0 --all-targets +Features: test-name=librust-bytes-dev:default +Depends: dh-cargo (>= 18), librust-loom-0.5+default-dev, librust-serde-test-1+default-dev, @ +Restrictions: allow-stderr, skip-not-installable + +Test-Command: /usr/share/cargo/bin/cargo-auto-test bytes 1.1.0 --all-targets --no-default-features --features std +Features: test-name=librust-bytes-dev:std +Depends: dh-cargo (>= 18), librust-loom-0.5+default-dev, librust-serde-test-1+default-dev, @ +Restrictions: allow-stderr, skip-not-installable + +Test-Command: /usr/share/cargo/bin/cargo-auto-test bytes 1.1.0 --all-targets --no-default-features +Features: test-name=librust-bytes-dev: +Depends: dh-cargo (>= 18), librust-loom-0.5+default-dev, librust-serde-test-1+default-dev, @ +Restrictions: allow-stderr, skip-not-installable + +Test-Command: /usr/share/cargo/bin/cargo-auto-test bytes 1.1.0 --all-targets --no-default-features --features serde +Features: test-name=librust-bytes+serde-dev:serde +Depends: dh-cargo (>= 18), librust-loom-0.5+default-dev, librust-serde-test-1+default-dev, @ +Restrictions: allow-stderr, skip-not-installable diff -Nru rust-bytes-0.4.12/debian/watch rust-bytes-1.1.0/debian/watch --- rust-bytes-0.4.12/debian/watch 2019-07-12 12:29:35.000000000 +0000 +++ rust-bytes-1.1.0/debian/watch 2021-11-28 22:37:58.000000000 +0000 @@ -2,4 +2,3 @@ opts=filenamemangle=s/.*\/(.*)\/download/bytes-$1\.tar\.gz/g,\ uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha)\d*)$/$1~$2/ \ https://qa.debian.org/cgi-bin/fakeupstream.cgi?upstream=crates.io/bytes .*/crates/bytes/@ANY_VERSION@/download - diff -Nru rust-bytes-0.4.12/.github/workflows/ci.yml rust-bytes-1.1.0/.github/workflows/ci.yml --- rust-bytes-0.4.12/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/.github/workflows/ci.yml 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,172 @@ +name: CI + +on: + pull_request: + branches: + - master + push: + branches: + - master + +env: + RUSTFLAGS: -Dwarnings + RUST_BACKTRACE: 1 + nightly: nightly-2021-04-13 + +defaults: + run: + shell: bash + +jobs: + # Check formatting + rustfmt: + name: rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Rust + run: rustup update stable && rustup default stable + - name: Check formatting + run: cargo fmt --all -- --check + + # TODO + # # Apply clippy lints + # clippy: + # name: clippy + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v2 + # - name: Apply clippy lints + # run: cargo clippy --all-features + + # 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. + minrust: + name: minrust + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Rust + run: rustup update 1.39.0 && rustup default 1.39.0 + - name: Check + run: . ci/test-stable.sh check + + # Stable + stable: + name: stable + strategy: + matrix: + os: + - ubuntu-latest + - macos-latest + - windows-latest + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - name: Install Rust + # --no-self-update is necessary because the windows environment cannot self-update rustup.exe. + run: rustup update stable --no-self-update && rustup default stable + - name: Test + run: . ci/test-stable.sh test + + # Nightly + nightly: + name: nightly + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Rust + run: rustup update $nightly && rustup default $nightly + - name: Test + run: . ci/test-stable.sh test + + # Run tests on some extra platforms + cross: + name: cross + strategy: + matrix: + target: + - i686-unknown-linux-gnu + - armv7-unknown-linux-gnueabihf + - powerpc-unknown-linux-gnu + - powerpc64-unknown-linux-gnu + - wasm32-unknown-unknown + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Rust + run: rustup update stable && rustup default stable + - name: cross build --target ${{ matrix.target }} + run: | + cargo install cross + cross build --target ${{ matrix.target }} + if: matrix.target != 'wasm32-unknown-unknown' + # WASM support + - name: cargo build --target ${{ matrix.target }} + run: | + rustup target add ${{ matrix.target }} + cargo build --target ${{ matrix.target }} + if: matrix.target == 'wasm32-unknown-unknown' + + # Sanitizers + tsan: + name: tsan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Rust + run: rustup update $nightly && rustup default $nightly + - name: Install rust-src + run: rustup component add rust-src + - name: ASAN / TSAN + run: . ci/tsan.sh + miri: + name: miri + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Miri + run: ci/miri.sh + + # Loom + loom: + name: loom + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Rust + run: rustup update $nightly && rustup default $nightly + - name: Loom tests + run: RUSTFLAGS="--cfg loom -Dwarnings" cargo test --lib + + publish_docs: + name: Publish Documentation + needs: + - rustfmt + # - clippy + - stable + - nightly + - minrust + - cross + - tsan + - loom + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Rust + run: rustup update stable && rustup default stable + - name: Build documentation + run: cargo doc --no-deps --all-features + env: + RUSTDOCFLAGS: --cfg docsrs + - name: Publish documentation + run: | + cd target/doc + git init + git add . + git -c user.name='ci' -c user.email='ci' commit -m 'Deploy Bytes API documentation' + git push -f -q https://git:${{ secrets.github_token }}@github.com/${{ github.repository }} HEAD:gh-pages + if: github.event_name == 'push' && github.event.ref == 'refs/heads/master' && github.repository == 'tokio-rs/bytes' diff -Nru rust-bytes-0.4.12/.gitignore rust-bytes-1.1.0/.gitignore --- rust-bytes-0.4.12/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/.gitignore 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff -Nru rust-bytes-0.4.12/README.md rust-bytes-1.1.0/README.md --- rust-bytes-0.4.12/README.md 2019-03-06 20:42:31.000000000 +0000 +++ rust-bytes-1.1.0/README.md 1973-11-29 21:33:09.000000000 +0000 @@ -2,10 +2,15 @@ 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) +[![Crates.io][crates-badge]][crates-url] +[![Build Status][ci-badge]][ci-url] -[Documentation](https://docs.rs/bytes/0.4.12/bytes/) +[crates-badge]: https://img.shields.io/crates/v/bytes.svg +[crates-url]: https://crates.io/crates/bytes +[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) ## Usage @@ -13,14 +18,12 @@ ```toml [dependencies] -bytes = "0.4.12" +bytes = "1" ``` Next, add this to your crate: ```rust -extern crate bytes; - use bytes::{Bytes, BytesMut, Buf, BufMut}; ``` @@ -30,7 +33,7 @@ ```toml [dependencies] -bytes = { version = "0.4.12", features = ["serde"] } +bytes = { version = "1", features = ["serde"] } ``` ## License @@ -42,4 +45,3 @@ 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. - diff -Nru rust-bytes-0.4.12/src/buf/buf_impl.rs rust-bytes-1.1.0/src/buf/buf_impl.rs --- rust-bytes-0.4.12/src/buf/buf_impl.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/src/buf/buf_impl.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,1074 @@ +#[cfg(feature = "std")] +use crate::buf::{reader, Reader}; +use crate::buf::{take, Chain, Take}; + +use core::{cmp, mem, ptr}; + +#[cfg(feature = "std")] +use std::io::IoSlice; + +use alloc::boxed::Box; + +macro_rules! buf_get_impl { + ($this:ident, $typ:tt::$conv:tt) => {{ + const SIZE: usize = mem::size_of::<$typ>(); + // try to convert directly from the bytes + // this Option trick is to avoid keeping a borrow on self + // when advance() is called (mut borrow) and to call bytes() only once + let ret = $this + .chunk() + .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 + $this.advance(SIZE); + return ret; + } else { + // if not we copy the bytes in a temp buffer then convert + let mut buf = [0; SIZE]; + $this.copy_to_slice(&mut buf); // (do the advance) + return $typ::$conv(buf); + } + }}; + (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. + // It seems to be linked to the way the method is optimised by the compiler + 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)..]); + return $typ::from_be_bytes(buf); + }}; +} + +/// Read bytes from a buffer. +/// +/// A buffer stores bytes in memory such that read operations are infallible. +/// The underlying storage may or may not be in contiguous memory. A `Buf` value +/// is a cursor into the buffer. Reading from `Buf` advances the cursor +/// position. It can be thought of as an efficient `Iterator` for collections of +/// bytes. +/// +/// The simplest `Buf` is a `&[u8]`. +/// +/// ``` +/// use bytes::Buf; +/// +/// let mut buf = &b"hello world"[..]; +/// +/// assert_eq!(b'h', buf.get_u8()); +/// assert_eq!(b'e', buf.get_u8()); +/// assert_eq!(b'l', buf.get_u8()); +/// +/// let mut rest = [0; 8]; +/// buf.copy_to_slice(&mut rest); +/// +/// assert_eq!(&rest[..], &b"lo world"[..]); +/// ``` +pub trait Buf { + /// Returns the number of bytes between the current position and the end of + /// the buffer. + /// + /// This value is greater than or equal to the length of the slice returned + /// by `chunk()`. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"hello world"[..]; + /// + /// assert_eq!(buf.remaining(), 11); + /// + /// buf.get_u8(); + /// + /// assert_eq!(buf.remaining(), 10); + /// ``` + /// + /// # Implementer notes + /// + /// Implementations of `remaining` should ensure that the return value does + /// not change unless a call is made to `advance` or any other function that + /// is documented to change the `Buf`'s current position. + fn remaining(&self) -> usize; + + /// Returns a slice starting at the current position and of length between 0 + /// 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. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"hello world"[..]; + /// + /// assert_eq!(buf.chunk(), &b"hello world"[..]); + /// + /// buf.advance(6); + /// + /// assert_eq!(buf.chunk(), &b"world"[..]); + /// ``` + /// + /// # Implementer notes + /// + /// This function should never panic. Once the end of the buffer is reached, + /// i.e., `Buf::remaining` returns 0, calls to `chunk()` should return an + /// empty slice. + // The `chunk` method was previously called `bytes`. This alias makes the rename + // more easily discoverable. + #[cfg_attr(docsrs, doc(alias = "bytes"))] + fn chunk(&self) -> &[u8]; + + /// Fills `dst` with potentially multiple slices starting at `self`'s + /// current position. + /// + /// If the `Buf` is backed by disjoint slices of bytes, `chunk_vectored` enables + /// fetching more than one slice at once. `dst` is a slice of `IoSlice` + /// references, enabling the slice to be directly used with [`writev`] + /// without any further conversion. The sum of the lengths of all the + /// buffers in `dst` will be less than or equal to `Buf::remaining()`. + /// + /// The entries in `dst` will be overwritten, but the data **contained** by + /// the slices **will not** be modified. If `chunk_vectored` does not fill every + /// entry in `dst`, then `dst` is guaranteed to contain all remaining slices + /// in `self. + /// + /// This is a lower level function. Most operations are done with other + /// functions. + /// + /// # Implementer notes + /// + /// This function should never panic. Once the end of the buffer is reached, + /// i.e., `Buf::remaining` returns 0, calls to `chunk_vectored` must return 0 + /// without mutating `dst`. + /// + /// Implementations should also take care to properly handle being called + /// with `dst` being a zero length slice. + /// + /// [`writev`]: http://man7.org/linux/man-pages/man2/readv.2.html + #[cfg(feature = "std")] + fn chunks_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize { + if dst.is_empty() { + return 0; + } + + if self.has_remaining() { + dst[0] = IoSlice::new(self.chunk()); + 1 + } else { + 0 + } + } + + /// Advance the internal cursor of the Buf + /// + /// The next call to `chunk()` will return a slice starting `cnt` bytes + /// further into the underlying buffer. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"hello world"[..]; + /// + /// assert_eq!(buf.chunk(), &b"hello world"[..]); + /// + /// buf.advance(6); + /// + /// assert_eq!(buf.chunk(), &b"world"[..]); + /// ``` + /// + /// # Panics + /// + /// This function **may** panic if `cnt > self.remaining()`. + /// + /// # Implementer notes + /// + /// It is recommended for implementations of `advance` to panic if `cnt > + /// self.remaining()`. If the implementation does not panic, the call must + /// behave as if `cnt == self.remaining()`. + /// + /// A call with `cnt == 0` should never panic and be a no-op. + fn advance(&mut self, cnt: usize); + + /// Returns true if there are any more bytes to consume + /// + /// This is equivalent to `self.remaining() != 0`. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"a"[..]; + /// + /// assert!(buf.has_remaining()); + /// + /// buf.get_u8(); + /// + /// assert!(!buf.has_remaining()); + /// ``` + fn has_remaining(&self) -> bool { + self.remaining() > 0 + } + + /// Copies bytes from `self` into `dst`. + /// + /// The cursor is advanced by the number of bytes copied. `self` must have + /// enough remaining bytes to fill `dst`. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"hello world"[..]; + /// let mut dst = [0; 5]; + /// + /// buf.copy_to_slice(&mut dst); + /// assert_eq!(&b"hello"[..], &dst); + /// assert_eq!(6, buf.remaining()); + /// ``` + /// + /// # Panics + /// + /// This function panics if `self.remaining() < dst.len()` + fn copy_to_slice(&mut self, dst: &mut [u8]) { + let mut off = 0; + + assert!(self.remaining() >= dst.len()); + + while off < dst.len() { + let cnt; + + unsafe { + let src = self.chunk(); + cnt = cmp::min(src.len(), dst.len() - off); + + ptr::copy_nonoverlapping(src.as_ptr(), dst[off..].as_mut_ptr(), cnt); + + off += cnt; + } + + self.advance(cnt); + } + } + + /// Gets an unsigned 8 bit integer from `self`. + /// + /// The current position is advanced by 1. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08 hello"[..]; + /// assert_eq!(8, buf.get_u8()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is no more remaining data in `self`. + fn get_u8(&mut self) -> u8 { + assert!(self.remaining() >= 1); + let ret = self.chunk()[0]; + self.advance(1); + ret + } + + /// Gets a signed 8 bit integer from `self`. + /// + /// The current position is advanced by 1. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08 hello"[..]; + /// assert_eq!(8, buf.get_i8()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is no more remaining data in `self`. + fn get_i8(&mut self) -> i8 { + assert!(self.remaining() >= 1); + let ret = self.chunk()[0] as i8; + self.advance(1); + ret + } + + /// Gets an unsigned 16 bit integer from `self` in big-endian byte order. + /// + /// The current position is advanced by 2. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08\x09 hello"[..]; + /// assert_eq!(0x0809, buf.get_u16()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_u16(&mut self) -> u16 { + buf_get_impl!(self, u16::from_be_bytes); + } + + /// Gets an unsigned 16 bit integer from `self` in little-endian byte order. + /// + /// The current position is advanced by 2. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x09\x08 hello"[..]; + /// assert_eq!(0x0809, buf.get_u16_le()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_u16_le(&mut self) -> u16 { + buf_get_impl!(self, u16::from_le_bytes); + } + + /// Gets a signed 16 bit integer from `self` in big-endian byte order. + /// + /// The current position is advanced by 2. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08\x09 hello"[..]; + /// assert_eq!(0x0809, buf.get_i16()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_i16(&mut self) -> i16 { + buf_get_impl!(self, i16::from_be_bytes); + } + + /// Gets a signed 16 bit integer from `self` in little-endian byte order. + /// + /// The current position is advanced by 2. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x09\x08 hello"[..]; + /// assert_eq!(0x0809, buf.get_i16_le()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_i16_le(&mut self) -> i16 { + buf_get_impl!(self, i16::from_le_bytes); + } + + /// Gets an unsigned 32 bit integer from `self` in the big-endian byte order. + /// + /// The current position is advanced by 4. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08\x09\xA0\xA1 hello"[..]; + /// assert_eq!(0x0809A0A1, buf.get_u32()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_u32(&mut self) -> u32 { + buf_get_impl!(self, u32::from_be_bytes); + } + + /// Gets an unsigned 32 bit integer from `self` in the little-endian byte order. + /// + /// The current position is advanced by 4. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\xA1\xA0\x09\x08 hello"[..]; + /// assert_eq!(0x0809A0A1, buf.get_u32_le()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_u32_le(&mut self) -> u32 { + buf_get_impl!(self, u32::from_le_bytes); + } + + /// Gets a signed 32 bit integer from `self` in big-endian byte order. + /// + /// The current position is advanced by 4. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08\x09\xA0\xA1 hello"[..]; + /// assert_eq!(0x0809A0A1, buf.get_i32()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_i32(&mut self) -> i32 { + buf_get_impl!(self, i32::from_be_bytes); + } + + /// Gets a signed 32 bit integer from `self` in little-endian byte order. + /// + /// The current position is advanced by 4. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\xA1\xA0\x09\x08 hello"[..]; + /// assert_eq!(0x0809A0A1, buf.get_i32_le()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_i32_le(&mut self) -> i32 { + buf_get_impl!(self, i32::from_le_bytes); + } + + /// Gets an unsigned 64 bit integer from `self` in big-endian byte order. + /// + /// The current position is advanced by 8. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08 hello"[..]; + /// assert_eq!(0x0102030405060708, buf.get_u64()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_u64(&mut self) -> u64 { + buf_get_impl!(self, u64::from_be_bytes); + } + + /// Gets an unsigned 64 bit integer from `self` in little-endian byte order. + /// + /// The current position is advanced by 8. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08\x07\x06\x05\x04\x03\x02\x01 hello"[..]; + /// assert_eq!(0x0102030405060708, buf.get_u64_le()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_u64_le(&mut self) -> u64 { + buf_get_impl!(self, u64::from_le_bytes); + } + + /// Gets a signed 64 bit integer from `self` in big-endian byte order. + /// + /// The current position is advanced by 8. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08 hello"[..]; + /// assert_eq!(0x0102030405060708, buf.get_i64()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_i64(&mut self) -> i64 { + buf_get_impl!(self, i64::from_be_bytes); + } + + /// Gets a signed 64 bit integer from `self` in little-endian byte order. + /// + /// The current position is advanced by 8. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x08\x07\x06\x05\x04\x03\x02\x01 hello"[..]; + /// assert_eq!(0x0102030405060708, buf.get_i64_le()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_i64_le(&mut self) -> i64 { + buf_get_impl!(self, i64::from_le_bytes); + } + + /// Gets an unsigned 128 bit integer from `self` in big-endian byte order. + /// + /// The current position is advanced by 16. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16 hello"[..]; + /// assert_eq!(0x01020304050607080910111213141516, buf.get_u128()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_u128(&mut self) -> u128 { + buf_get_impl!(self, u128::from_be_bytes); + } + + /// Gets an unsigned 128 bit integer from `self` in little-endian byte order. + /// + /// The current position is advanced by 16. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01 hello"[..]; + /// assert_eq!(0x01020304050607080910111213141516, buf.get_u128_le()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_u128_le(&mut self) -> u128 { + buf_get_impl!(self, u128::from_le_bytes); + } + + /// Gets a signed 128 bit integer from `self` in big-endian byte order. + /// + /// The current position is advanced by 16. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16 hello"[..]; + /// assert_eq!(0x01020304050607080910111213141516, buf.get_i128()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_i128(&mut self) -> i128 { + buf_get_impl!(self, i128::from_be_bytes); + } + + /// Gets a signed 128 bit integer from `self` in little-endian byte order. + /// + /// The current position is advanced by 16. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01 hello"[..]; + /// assert_eq!(0x01020304050607080910111213141516, buf.get_i128_le()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_i128_le(&mut self) -> i128 { + buf_get_impl!(self, i128::from_le_bytes); + } + + /// Gets an unsigned n-byte integer from `self` in big-endian byte order. + /// + /// The current position is advanced by `nbytes`. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x01\x02\x03 hello"[..]; + /// assert_eq!(0x010203, buf.get_uint(3)); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_uint(&mut self, nbytes: usize) -> u64 { + buf_get_impl!(be => self, u64, nbytes); + } + + /// Gets an unsigned n-byte integer from `self` in little-endian byte order. + /// + /// The current position is advanced by `nbytes`. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x03\x02\x01 hello"[..]; + /// assert_eq!(0x010203, buf.get_uint_le(3)); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_uint_le(&mut self, nbytes: usize) -> u64 { + buf_get_impl!(le => self, u64, nbytes); + } + + /// Gets a signed n-byte integer from `self` in big-endian byte order. + /// + /// The current position is advanced by `nbytes`. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x01\x02\x03 hello"[..]; + /// assert_eq!(0x010203, buf.get_int(3)); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_int(&mut self, nbytes: usize) -> i64 { + buf_get_impl!(be => self, i64, nbytes); + } + + /// Gets a signed n-byte integer from `self` in little-endian byte order. + /// + /// The current position is advanced by `nbytes`. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x03\x02\x01 hello"[..]; + /// assert_eq!(0x010203, buf.get_int_le(3)); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_int_le(&mut self, nbytes: usize) -> i64 { + buf_get_impl!(le => self, i64, nbytes); + } + + /// Gets an IEEE754 single-precision (4 bytes) floating point number from + /// `self` in big-endian byte order. + /// + /// The current position is advanced by 4. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x3F\x99\x99\x9A hello"[..]; + /// assert_eq!(1.2f32, buf.get_f32()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_f32(&mut self) -> f32 { + f32::from_bits(Self::get_u32(self)) + } + + /// Gets an IEEE754 single-precision (4 bytes) floating point number from + /// `self` in little-endian byte order. + /// + /// The current position is advanced by 4. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x9A\x99\x99\x3F hello"[..]; + /// assert_eq!(1.2f32, buf.get_f32_le()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_f32_le(&mut self) -> f32 { + f32::from_bits(Self::get_u32_le(self)) + } + + /// Gets an IEEE754 double-precision (8 bytes) floating point number from + /// `self` in big-endian byte order. + /// + /// The current position is advanced by 8. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x3F\xF3\x33\x33\x33\x33\x33\x33 hello"[..]; + /// assert_eq!(1.2f64, buf.get_f64()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_f64(&mut self) -> f64 { + f64::from_bits(Self::get_u64(self)) + } + + /// Gets an IEEE754 double-precision (8 bytes) floating point number from + /// `self` in little-endian byte order. + /// + /// The current position is advanced by 8. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut buf = &b"\x33\x33\x33\x33\x33\x33\xF3\x3F hello"[..]; + /// assert_eq!(1.2f64, buf.get_f64_le()); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining data in `self`. + fn get_f64_le(&mut self) -> f64 { + f64::from_bits(Self::get_u64_le(self)) + } + + /// Consumes `len` bytes inside self and returns new instance of `Bytes` + /// with this data. + /// + /// This function may be optimized by the underlying type to avoid actual + /// copies. For example, `Bytes` implementation will do a shallow copy + /// (ref-count increment). + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let bytes = (&b"hello world"[..]).copy_to_bytes(5); + /// assert_eq!(&bytes[..], &b"hello"[..]); + /// ``` + fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes { + use super::BufMut; + + assert!(len <= self.remaining(), "`len` greater than remaining"); + + let mut ret = crate::BytesMut::with_capacity(len); + ret.put(self.take(len)); + ret.freeze() + } + + /// Creates an adaptor which will read at most `limit` bytes from `self`. + /// + /// This function returns a new instance of `Buf` which will read at most + /// `limit` bytes. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Buf, BufMut}; + /// + /// let mut buf = b"hello world"[..].take(5); + /// let mut dst = vec![]; + /// + /// dst.put(&mut buf); + /// assert_eq!(dst, b"hello"); + /// + /// let mut buf = buf.into_inner(); + /// dst.clear(); + /// dst.put(&mut buf); + /// assert_eq!(dst, b" world"); + /// ``` + fn take(self, limit: usize) -> Take + where + Self: Sized, + { + take::new(self, limit) + } + + /// Creates an adaptor which will chain this buffer with another. + /// + /// The returned `Buf` instance will first consume all bytes from `self`. + /// Afterwards the output is equivalent to the output of next. + /// + /// # Examples + /// + /// ``` + /// use bytes::Buf; + /// + /// let mut chain = b"hello "[..].chain(&b"world"[..]); + /// + /// let full = chain.copy_to_bytes(11); + /// assert_eq!(full.chunk(), b"hello world"); + /// ``` + fn chain(self, next: U) -> Chain + where + Self: Sized, + { + Chain::new(self, next) + } + + /// Creates an adaptor which implements the `Read` trait for `self`. + /// + /// This function returns a new value which implements `Read` by adapting + /// the `Read` trait functions to the `Buf` trait functions. Given that + /// `Buf` operations are infallible, none of the `Read` functions will + /// return with `Err`. + /// + /// # Examples + /// + /// ``` + /// use bytes::{Bytes, Buf}; + /// use std::io::Read; + /// + /// let buf = Bytes::from("hello world"); + /// + /// let mut reader = buf.reader(); + /// let mut dst = [0; 1024]; + /// + /// let num = reader.read(&mut dst).unwrap(); + /// + /// assert_eq!(11, num); + /// assert_eq!(&dst[..11], &b"hello world"[..]); + /// ``` + #[cfg(feature = "std")] + fn reader(self) -> Reader + where + Self: Sized, + { + reader::new(self) + } +} + +macro_rules! deref_forward_buf { + () => { + fn remaining(&self) -> usize { + (**self).remaining() + } + + fn chunk(&self) -> &[u8] { + (**self).chunk() + } + + #[cfg(feature = "std")] + fn chunks_vectored<'b>(&'b self, dst: &mut [IoSlice<'b>]) -> usize { + (**self).chunks_vectored(dst) + } + + fn advance(&mut self, cnt: usize) { + (**self).advance(cnt) + } + + fn has_remaining(&self) -> bool { + (**self).has_remaining() + } + + fn copy_to_slice(&mut self, dst: &mut [u8]) { + (**self).copy_to_slice(dst) + } + + fn get_u8(&mut self) -> u8 { + (**self).get_u8() + } + + fn get_i8(&mut self) -> i8 { + (**self).get_i8() + } + + fn get_u16(&mut self) -> u16 { + (**self).get_u16() + } + + fn get_u16_le(&mut self) -> u16 { + (**self).get_u16_le() + } + + fn get_i16(&mut self) -> i16 { + (**self).get_i16() + } + + fn get_i16_le(&mut self) -> i16 { + (**self).get_i16_le() + } + + fn get_u32(&mut self) -> u32 { + (**self).get_u32() + } + + fn get_u32_le(&mut self) -> u32 { + (**self).get_u32_le() + } + + fn get_i32(&mut self) -> i32 { + (**self).get_i32() + } + + fn get_i32_le(&mut self) -> i32 { + (**self).get_i32_le() + } + + fn get_u64(&mut self) -> u64 { + (**self).get_u64() + } + + fn get_u64_le(&mut self) -> u64 { + (**self).get_u64_le() + } + + fn get_i64(&mut self) -> i64 { + (**self).get_i64() + } + + fn get_i64_le(&mut self) -> i64 { + (**self).get_i64_le() + } + + fn get_uint(&mut self, nbytes: usize) -> u64 { + (**self).get_uint(nbytes) + } + + fn get_uint_le(&mut self, nbytes: usize) -> u64 { + (**self).get_uint_le(nbytes) + } + + fn get_int(&mut self, nbytes: usize) -> i64 { + (**self).get_int(nbytes) + } + + fn get_int_le(&mut self, nbytes: usize) -> i64 { + (**self).get_int_le(nbytes) + } + + fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes { + (**self).copy_to_bytes(len) + } + }; +} + +impl Buf for &mut T { + deref_forward_buf!(); +} + +impl Buf for Box { + deref_forward_buf!(); +} + +impl Buf for &[u8] { + #[inline] + fn remaining(&self) -> usize { + self.len() + } + + #[inline] + fn chunk(&self) -> &[u8] { + self + } + + #[inline] + fn advance(&mut self, cnt: usize) { + *self = &self[cnt..]; + } +} + +#[cfg(feature = "std")] +impl> Buf for std::io::Cursor { + fn remaining(&self) -> usize { + let len = self.get_ref().as_ref().len(); + let pos = self.position(); + + if pos >= len as u64 { + return 0; + } + + len - pos as usize + } + + fn chunk(&self) -> &[u8] { + let len = self.get_ref().as_ref().len(); + let pos = self.position(); + + if pos >= len as u64 { + return &[]; + } + + &self.get_ref().as_ref()[pos as usize..] + } + + fn advance(&mut self, cnt: usize) { + let pos = (self.position() as usize) + .checked_add(cnt) + .expect("overflow"); + + assert!(pos <= self.get_ref().as_ref().len()); + self.set_position(pos as u64); + } +} + +// The existence of this function makes the compiler catch if the Buf +// trait is "object-safe" or not. +fn _assert_trait_object(_b: &dyn Buf) {} diff -Nru rust-bytes-0.4.12/src/buf/buf_mut.rs rust-bytes-1.1.0/src/buf/buf_mut.rs --- rust-bytes-0.4.12/src/buf/buf_mut.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/src/buf/buf_mut.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,8 +1,10 @@ -use super::{IntoBuf, Writer}; -use byteorder::{LittleEndian, ByteOrder, BigEndian}; -use iovec::IoVec; +use crate::buf::{limit, Chain, Limit, UninitSlice}; +#[cfg(feature = "std")] +use crate::buf::{writer, Writer}; -use std::{cmp, io, ptr, usize}; +use core::{cmp, mem, ptr, usize}; + +use alloc::{boxed::Box, vec::Vec}; /// A trait for values that provide sequential write access to bytes. /// @@ -20,30 +22,33 @@ /// /// let mut buf = vec![]; /// -/// buf.put("hello world"); +/// buf.put(&b"hello world"[..]); /// /// assert_eq!(buf, b"hello world"); /// ``` -pub trait BufMut { +pub unsafe trait BufMut { /// Returns the number of bytes that can be written from the current /// position until the end of the buffer is reached. /// /// This value is greater than or equal to the length of the slice returned - /// by `bytes_mut`. + /// by `chunk_mut()`. + /// + /// Writing to a `BufMut` may involve allocating more memory on the fly. + /// Implementations may fail before reaching the number of bytes indicated + /// by this method if they encounter an allocation failure. /// /// # Examples /// /// ``` /// use bytes::BufMut; - /// use std::io::Cursor; /// /// let mut dst = [0; 10]; - /// let mut buf = Cursor::new(&mut dst[..]); + /// let mut buf = &mut dst[..]; /// - /// assert_eq!(10, buf.remaining_mut()); - /// buf.put("hello"); + /// let original_remaining = buf.remaining_mut(); + /// buf.put(&b"hello"[..]); /// - /// assert_eq!(5, buf.remaining_mut()); + /// assert_eq!(original_remaining - 5, buf.remaining_mut()); /// ``` /// /// # Implementer notes @@ -55,7 +60,7 @@ /// Advance the internal cursor of the BufMut /// - /// The next call to `bytes_mut` will return a slice starting `cnt` bytes + /// The next call to `chunk_mut` will return a slice starting `cnt` bytes /// further into the underlying buffer. /// /// This function is unsafe because there is no guarantee that the bytes @@ -68,17 +73,14 @@ /// /// let mut buf = Vec::with_capacity(16); /// - /// unsafe { - /// buf.bytes_mut()[0] = b'h'; - /// buf.bytes_mut()[1] = b'e'; + /// // Write some data + /// buf.chunk_mut()[0..2].copy_from_slice(b"he"); + /// unsafe { buf.advance_mut(2) }; /// - /// buf.advance_mut(2); + /// // write more bytes + /// buf.chunk_mut()[0..3].copy_from_slice(b"llo"); /// - /// buf.bytes_mut()[0] = b'l'; - /// buf.bytes_mut()[1..3].copy_from_slice(b"lo"); - /// - /// buf.advance_mut(3); - /// } + /// unsafe { buf.advance_mut(3); } /// /// assert_eq!(5, buf.len()); /// assert_eq!(buf, b"hello"); @@ -105,14 +107,13 @@ /// /// ``` /// use bytes::BufMut; - /// use std::io::Cursor; /// /// let mut dst = [0; 5]; - /// let mut buf = Cursor::new(&mut dst); + /// let mut buf = &mut dst[..]; /// /// assert!(buf.has_remaining_mut()); /// - /// buf.put("hello"); + /// buf.put(&b"hello"[..]); /// /// assert!(!buf.has_remaining_mut()); /// ``` @@ -137,13 +138,15 @@ /// let mut buf = Vec::with_capacity(16); /// /// unsafe { - /// buf.bytes_mut()[0] = b'h'; - /// buf.bytes_mut()[1] = b'e'; + /// // MaybeUninit::as_mut_ptr + /// buf.chunk_mut()[0..].as_mut_ptr().write(b'h'); + /// buf.chunk_mut()[1..].as_mut_ptr().write(b'e'); /// /// buf.advance_mut(2); /// - /// buf.bytes_mut()[0] = b'l'; - /// buf.bytes_mut()[1..3].copy_from_slice(b"lo"); + /// buf.chunk_mut()[0..].as_mut_ptr().write(b'l'); + /// buf.chunk_mut()[1..].as_mut_ptr().write(b'l'); + /// buf.chunk_mut()[2..].as_mut_ptr().write(b'o'); /// /// buf.advance_mut(3); /// } @@ -154,53 +157,18 @@ /// /// # Implementer notes /// - /// This function should never panic. `bytes_mut` should return an empty - /// slice **if and only if** `remaining_mut` returns 0. In other words, - /// `bytes_mut` returning an empty slice implies that `remaining_mut` will - /// return 0 and `remaining_mut` returning 0 implies that `bytes_mut` will + /// This function should never panic. `chunk_mut` should return an empty + /// slice **if and only if** `remaining_mut()` returns 0. In other words, + /// `chunk_mut()` returning an empty slice implies that `remaining_mut()` will + /// return 0 and `remaining_mut()` returning 0 implies that `chunk_mut()` will /// return an empty slice. - unsafe fn bytes_mut(&mut self) -> &mut [u8]; - - /// Fills `dst` with potentially multiple mutable slices starting at `self`'s - /// current position. - /// - /// If the `BufMut` is backed by disjoint slices of bytes, `bytes_vec_mut` - /// enables fetching more than one slice at once. `dst` is a slice of - /// mutable `IoVec` references, enabling the slice to be directly used with - /// [`readv`] without any further conversion. The sum of the lengths of all - /// the buffers in `dst` will be less than or equal to - /// `Buf::remaining_mut()`. - /// - /// The entries in `dst` will be overwritten, but the data **contained** by - /// the slices **will not** be modified. If `bytes_vec_mut` does not fill every - /// entry in `dst`, then `dst` is guaranteed to contain all remaining slices - /// in `self. /// - /// This is a lower level function. Most operations are done with other - /// functions. - /// - /// # Implementer notes - /// - /// This function should never panic. Once the end of the buffer is reached, - /// i.e., `BufMut::remaining_mut` returns 0, calls to `bytes_vec_mut` must - /// return 0 without mutating `dst`. - /// - /// Implementations should also take care to properly handle being called - /// with `dst` being a zero length slice. - /// - /// [`readv`]: http://man7.org/linux/man-pages/man2/readv.2.html - unsafe fn bytes_vec_mut<'a>(&'a mut self, dst: &mut [&'a mut IoVec]) -> usize { - if dst.is_empty() { - return 0; - } - - if self.has_remaining_mut() { - dst[0] = self.bytes_mut().into(); - 1 - } else { - 0 - } - } + /// This function may trigger an out-of-memory abort if it tries to allocate + /// memory and fails to do so. + // The `chunk_mut` method was previously called `bytes_mut`. This alias makes the + // rename more easily discoverable. + #[cfg_attr(docsrs, doc(alias = "bytes_mut"))] + fn chunk_mut(&mut self) -> &mut UninitSlice; /// Transfer bytes into `self` from `src` and advance the cursor by the /// number of bytes written. @@ -212,9 +180,9 @@ /// /// let mut buf = vec![]; /// - /// buf.put(b'h'); + /// buf.put_u8(b'h'); /// buf.put(&b"ello"[..]); - /// buf.put(" world"); + /// buf.put(&b" world"[..]); /// /// assert_eq!(buf, b"hello world"); /// ``` @@ -222,29 +190,27 @@ /// # Panics /// /// Panics if `self` does not have enough capacity to contain `src`. - fn put(&mut self, src: T) where Self: Sized { - use super::Buf; - - let mut src = src.into_buf(); - + fn put(&mut self, mut src: T) + where + Self: Sized, + { assert!(self.remaining_mut() >= src.remaining()); while src.has_remaining() { let l; unsafe { - let s = src.bytes(); - let d = self.bytes_mut(); + let s = src.chunk(); + let d = self.chunk_mut(); l = cmp::min(s.len(), d.len()); - ptr::copy_nonoverlapping( - s.as_ptr(), - d.as_mut_ptr(), - 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); + } } } @@ -255,12 +221,11 @@ /// /// ``` /// use bytes::BufMut; - /// use std::io::Cursor; /// /// let mut dst = [0; 6]; /// /// { - /// let mut buf = Cursor::new(&mut dst); + /// let mut buf = &mut dst[..]; /// buf.put_slice(b"hello"); /// /// assert_eq!(1, buf.remaining_mut()); @@ -271,25 +236,59 @@ fn put_slice(&mut self, src: &[u8]) { let mut off = 0; - assert!(self.remaining_mut() >= src.len(), "buffer overflow"); + assert!( + self.remaining_mut() >= src.len(), + "buffer overflow; remaining = {}; src = {}", + self.remaining_mut(), + src.len() + ); while off < src.len() { let cnt; unsafe { - let dst = self.bytes_mut(); + let dst = self.chunk_mut(); cnt = cmp::min(dst.len(), src.len() - off); - ptr::copy_nonoverlapping( - src[off..].as_ptr(), - dst.as_mut_ptr(), - 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); } + /// Put `cnt` bytes `val` into `self`. + /// + /// Logically equivalent to calling `self.put_u8(val)` `cnt` times, but may work faster. + /// + /// `self` must have at least `cnt` remaining capacity. + /// + /// ``` + /// use bytes::BufMut; + /// + /// let mut dst = [0; 6]; + /// + /// { + /// let mut buf = &mut dst[..]; + /// buf.put_bytes(b'a', 4); + /// + /// assert_eq!(2, buf.remaining_mut()); + /// } + /// + /// assert_eq!(b"aaaa\0\0", &dst); + /// ``` + /// + /// # Panics + /// + /// This function panics if there is not enough remaining capacity in + /// `self`. + fn put_bytes(&mut self, val: u8, cnt: usize) { + for _ in 0..cnt { + self.put_u8(val); } } @@ -339,14 +338,6 @@ self.put_slice(&src) } - #[doc(hidden)] - #[deprecated(note="use put_u16_be or put_u16_le")] - fn put_u16(&mut self, n: u16) where Self: Sized { - let mut buf = [0; 2]; - T::write_u16(&mut buf, n); - self.put_slice(&buf) - } - /// Writes an unsigned 16 bit integer to `self` in big-endian byte order. /// /// The current position is advanced by 2. @@ -357,7 +348,7 @@ /// use bytes::BufMut; /// /// let mut buf = vec![]; - /// buf.put_u16_be(0x0809); + /// buf.put_u16(0x0809); /// assert_eq!(buf, b"\x08\x09"); /// ``` /// @@ -365,10 +356,8 @@ /// /// This function panics if there is not enough remaining capacity in /// `self`. - fn put_u16_be(&mut self, n: u16) { - let mut buf = [0; 2]; - BigEndian::write_u16(&mut buf, n); - self.put_slice(&buf) + fn put_u16(&mut self, n: u16) { + self.put_slice(&n.to_be_bytes()) } /// Writes an unsigned 16 bit integer to `self` in little-endian byte order. @@ -390,17 +379,7 @@ /// This function panics if there is not enough remaining capacity in /// `self`. fn put_u16_le(&mut self, n: u16) { - let mut buf = [0; 2]; - LittleEndian::write_u16(&mut buf, n); - self.put_slice(&buf) - } - - #[doc(hidden)] - #[deprecated(note="use put_i16_be or put_i16_le")] - fn put_i16(&mut self, n: i16) where Self: Sized { - let mut buf = [0; 2]; - T::write_i16(&mut buf, n); - self.put_slice(&buf) + self.put_slice(&n.to_le_bytes()) } /// Writes a signed 16 bit integer to `self` in big-endian byte order. @@ -413,7 +392,7 @@ /// use bytes::BufMut; /// /// let mut buf = vec![]; - /// buf.put_i16_be(0x0809); + /// buf.put_i16(0x0809); /// assert_eq!(buf, b"\x08\x09"); /// ``` /// @@ -421,10 +400,8 @@ /// /// This function panics if there is not enough remaining capacity in /// `self`. - fn put_i16_be(&mut self, n: i16) { - let mut buf = [0; 2]; - BigEndian::write_i16(&mut buf, n); - self.put_slice(&buf) + fn put_i16(&mut self, n: i16) { + self.put_slice(&n.to_be_bytes()) } /// Writes a signed 16 bit integer to `self` in little-endian byte order. @@ -446,17 +423,7 @@ /// This function panics if there is not enough remaining capacity in /// `self`. fn put_i16_le(&mut self, n: i16) { - let mut buf = [0; 2]; - LittleEndian::write_i16(&mut buf, n); - self.put_slice(&buf) - } - - #[doc(hidden)] - #[deprecated(note="use put_u32_be or put_u32_le")] - fn put_u32(&mut self, n: u32) where Self: Sized { - let mut buf = [0; 4]; - T::write_u32(&mut buf, n); - self.put_slice(&buf) + self.put_slice(&n.to_le_bytes()) } /// Writes an unsigned 32 bit integer to `self` in big-endian byte order. @@ -469,7 +436,7 @@ /// use bytes::BufMut; /// /// let mut buf = vec![]; - /// buf.put_u32_be(0x0809A0A1); + /// buf.put_u32(0x0809A0A1); /// assert_eq!(buf, b"\x08\x09\xA0\xA1"); /// ``` /// @@ -477,10 +444,8 @@ /// /// This function panics if there is not enough remaining capacity in /// `self`. - fn put_u32_be(&mut self, n: u32) { - let mut buf = [0; 4]; - BigEndian::write_u32(&mut buf, n); - self.put_slice(&buf) + fn put_u32(&mut self, n: u32) { + self.put_slice(&n.to_be_bytes()) } /// Writes an unsigned 32 bit integer to `self` in little-endian byte order. @@ -502,17 +467,7 @@ /// This function panics if there is not enough remaining capacity in /// `self`. fn put_u32_le(&mut self, n: u32) { - let mut buf = [0; 4]; - LittleEndian::write_u32(&mut buf, n); - self.put_slice(&buf) - } - - #[doc(hidden)] - #[deprecated(note="use put_i32_be or put_i32_le")] - fn put_i32(&mut self, n: i32) where Self: Sized { - let mut buf = [0; 4]; - T::write_i32(&mut buf, n); - self.put_slice(&buf) + self.put_slice(&n.to_le_bytes()) } /// Writes a signed 32 bit integer to `self` in big-endian byte order. @@ -525,7 +480,7 @@ /// use bytes::BufMut; /// /// let mut buf = vec![]; - /// buf.put_i32_be(0x0809A0A1); + /// buf.put_i32(0x0809A0A1); /// assert_eq!(buf, b"\x08\x09\xA0\xA1"); /// ``` /// @@ -533,10 +488,8 @@ /// /// This function panics if there is not enough remaining capacity in /// `self`. - fn put_i32_be(&mut self, n: i32) { - let mut buf = [0; 4]; - BigEndian::write_i32(&mut buf, n); - self.put_slice(&buf) + fn put_i32(&mut self, n: i32) { + self.put_slice(&n.to_be_bytes()) } /// Writes a signed 32 bit integer to `self` in little-endian byte order. @@ -558,17 +511,7 @@ /// This function panics if there is not enough remaining capacity in /// `self`. fn put_i32_le(&mut self, n: i32) { - let mut buf = [0; 4]; - LittleEndian::write_i32(&mut buf, n); - self.put_slice(&buf) - } - - #[doc(hidden)] - #[deprecated(note="use put_u64_be or put_u64_le")] - fn put_u64(&mut self, n: u64) where Self: Sized { - let mut buf = [0; 8]; - T::write_u64(&mut buf, n); - self.put_slice(&buf) + self.put_slice(&n.to_le_bytes()) } /// Writes an unsigned 64 bit integer to `self` in the big-endian byte order. @@ -581,7 +524,7 @@ /// use bytes::BufMut; /// /// let mut buf = vec![]; - /// buf.put_u64_be(0x0102030405060708); + /// buf.put_u64(0x0102030405060708); /// assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08"); /// ``` /// @@ -589,10 +532,8 @@ /// /// This function panics if there is not enough remaining capacity in /// `self`. - fn put_u64_be(&mut self, n: u64) { - let mut buf = [0; 8]; - BigEndian::write_u64(&mut buf, n); - self.put_slice(&buf) + fn put_u64(&mut self, n: u64) { + self.put_slice(&n.to_be_bytes()) } /// Writes an unsigned 64 bit integer to `self` in little-endian byte order. @@ -614,17 +555,7 @@ /// This function panics if there is not enough remaining capacity in /// `self`. fn put_u64_le(&mut self, n: u64) { - let mut buf = [0; 8]; - LittleEndian::write_u64(&mut buf, n); - self.put_slice(&buf) - } - - #[doc(hidden)] - #[deprecated(note="use put_i64_be or put_i64_le")] - fn put_i64(&mut self, n: i64) where Self: Sized { - let mut buf = [0; 8]; - T::write_i64(&mut buf, n); - self.put_slice(&buf) + self.put_slice(&n.to_le_bytes()) } /// Writes a signed 64 bit integer to `self` in the big-endian byte order. @@ -637,7 +568,7 @@ /// use bytes::BufMut; /// /// let mut buf = vec![]; - /// buf.put_i64_be(0x0102030405060708); + /// buf.put_i64(0x0102030405060708); /// assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08"); /// ``` /// @@ -645,10 +576,8 @@ /// /// This function panics if there is not enough remaining capacity in /// `self`. - fn put_i64_be(&mut self, n: i64) { - let mut buf = [0; 8]; - BigEndian::write_i64(&mut buf, n); - self.put_slice(&buf) + fn put_i64(&mut self, n: i64) { + self.put_slice(&n.to_be_bytes()) } /// Writes a signed 64 bit integer to `self` in little-endian byte order. @@ -670,14 +599,11 @@ /// This function panics if there is not enough remaining capacity in /// `self`. fn put_i64_le(&mut self, n: i64) { - let mut buf = [0; 8]; - LittleEndian::write_i64(&mut buf, n); - self.put_slice(&buf) + self.put_slice(&n.to_le_bytes()) } /// Writes an unsigned 128 bit integer to `self` in the big-endian byte order. /// - /// **NOTE:** This method requires the `i128` feature. /// The current position is advanced by 16. /// /// # Examples @@ -686,7 +612,7 @@ /// use bytes::BufMut; /// /// let mut buf = vec![]; - /// buf.put_u128_be(0x01020304050607080910111213141516); + /// buf.put_u128(0x01020304050607080910111213141516); /// assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16"); /// ``` /// @@ -694,16 +620,12 @@ /// /// This function panics if there is not enough remaining capacity in /// `self`. - #[cfg(feature = "i128")] - fn put_u128_be(&mut self, n: u128) { - let mut buf = [0; 16]; - BigEndian::write_u128(&mut buf, n); - self.put_slice(&buf) + fn put_u128(&mut self, n: u128) { + self.put_slice(&n.to_be_bytes()) } /// Writes an unsigned 128 bit integer to `self` in little-endian byte order. /// - /// **NOTE:** This method requires the `i128` feature. /// The current position is advanced by 16. /// /// # Examples @@ -720,16 +642,12 @@ /// /// This function panics if there is not enough remaining capacity in /// `self`. - #[cfg(feature = "i128")] fn put_u128_le(&mut self, n: u128) { - let mut buf = [0; 16]; - LittleEndian::write_u128(&mut buf, n); - self.put_slice(&buf) + self.put_slice(&n.to_le_bytes()) } /// Writes a signed 128 bit integer to `self` in the big-endian byte order. /// - /// **NOTE:** This method requires the `i128` feature. /// The current position is advanced by 16. /// /// # Examples @@ -738,7 +656,7 @@ /// use bytes::BufMut; /// /// let mut buf = vec![]; - /// buf.put_i128_be(0x01020304050607080910111213141516); + /// buf.put_i128(0x01020304050607080910111213141516); /// assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16"); /// ``` /// @@ -746,16 +664,12 @@ /// /// This function panics if there is not enough remaining capacity in /// `self`. - #[cfg(feature = "i128")] - fn put_i128_be(&mut self, n: i128) { - let mut buf = [0; 16]; - BigEndian::write_i128(&mut buf, n); - self.put_slice(&buf) + fn put_i128(&mut self, n: i128) { + self.put_slice(&n.to_be_bytes()) } /// Writes a signed 128 bit integer to `self` in little-endian byte order. /// - /// **NOTE:** This method requires the `i128` feature. /// The current position is advanced by 16. /// /// # Examples @@ -772,19 +686,8 @@ /// /// This function panics if there is not enough remaining capacity in /// `self`. - #[cfg(feature = "i128")] fn put_i128_le(&mut self, n: i128) { - let mut buf = [0; 16]; - LittleEndian::write_i128(&mut buf, n); - self.put_slice(&buf) - } - - #[doc(hidden)] - #[deprecated(note="use put_uint_be or put_uint_le")] - fn put_uint(&mut self, n: u64, nbytes: usize) where Self: Sized { - let mut buf = [0; 8]; - T::write_uint(&mut buf, n, nbytes); - self.put_slice(&buf[0..nbytes]) + self.put_slice(&n.to_le_bytes()) } /// Writes an unsigned n-byte integer to `self` in big-endian byte order. @@ -797,7 +700,7 @@ /// use bytes::BufMut; /// /// let mut buf = vec![]; - /// buf.put_uint_be(0x010203, 3); + /// buf.put_uint(0x010203, 3); /// assert_eq!(buf, b"\x01\x02\x03"); /// ``` /// @@ -805,10 +708,8 @@ /// /// This function panics if there is not enough remaining capacity in /// `self`. - fn put_uint_be(&mut self, n: u64, nbytes: usize) { - let mut buf = [0; 8]; - BigEndian::write_uint(&mut buf, n, nbytes); - self.put_slice(&buf[0..nbytes]) + fn put_uint(&mut self, n: u64, nbytes: usize) { + self.put_slice(&n.to_be_bytes()[mem::size_of_val(&n) - nbytes..]); } /// Writes an unsigned n-byte integer to `self` in the little-endian byte order. @@ -830,20 +731,10 @@ /// This function panics if there is not enough remaining capacity in /// `self`. fn put_uint_le(&mut self, n: u64, nbytes: usize) { - let mut buf = [0; 8]; - LittleEndian::write_uint(&mut buf, n, nbytes); - self.put_slice(&buf[0..nbytes]) + self.put_slice(&n.to_le_bytes()[0..nbytes]); } - #[doc(hidden)] - #[deprecated(note="use put_int_be or put_int_le")] - fn put_int(&mut self, n: i64, nbytes: usize) where Self: Sized { - let mut buf = [0; 8]; - T::write_int(&mut buf, n, nbytes); - self.put_slice(&buf[0..nbytes]) - } - - /// Writes a signed n-byte integer to `self` in big-endian byte order. + /// Writes low `nbytes` of a signed integer to `self` in big-endian byte order. /// /// The current position is advanced by `nbytes`. /// @@ -853,21 +744,19 @@ /// use bytes::BufMut; /// /// let mut buf = vec![]; - /// buf.put_int_be(0x010203, 3); + /// buf.put_int(0x0504010203, 3); /// assert_eq!(buf, b"\x01\x02\x03"); /// ``` /// /// # Panics /// /// This function panics if there is not enough remaining capacity in - /// `self`. - fn put_int_be(&mut self, n: i64, nbytes: usize) { - let mut buf = [0; 8]; - BigEndian::write_int(&mut buf, n, nbytes); - self.put_slice(&buf[0..nbytes]) + /// `self` or if `nbytes` is greater than 8. + fn put_int(&mut self, n: i64, nbytes: usize) { + self.put_slice(&n.to_be_bytes()[mem::size_of_val(&n) - nbytes..]); } - /// Writes a signed n-byte integer to `self` in little-endian byte order. + /// Writes low `nbytes` of a signed integer to `self` in little-endian byte order. /// /// The current position is advanced by `nbytes`. /// @@ -877,26 +766,16 @@ /// use bytes::BufMut; /// /// let mut buf = vec![]; - /// buf.put_int_le(0x010203, 3); + /// buf.put_int_le(0x0504010203, 3); /// assert_eq!(buf, b"\x03\x02\x01"); /// ``` /// /// # Panics /// /// This function panics if there is not enough remaining capacity in - /// `self`. + /// `self` or if `nbytes` is greater than 8. fn put_int_le(&mut self, n: i64, nbytes: usize) { - let mut buf = [0; 8]; - LittleEndian::write_int(&mut buf, n, nbytes); - self.put_slice(&buf[0..nbytes]) - } - - #[doc(hidden)] - #[deprecated(note="use put_f32_be or put_f32_le")] - fn put_f32(&mut self, n: f32) where Self: Sized { - let mut buf = [0; 4]; - T::write_f32(&mut buf, n); - self.put_slice(&buf) + self.put_slice(&n.to_le_bytes()[0..nbytes]); } /// Writes an IEEE754 single-precision (4 bytes) floating point number to @@ -910,7 +789,7 @@ /// use bytes::BufMut; /// /// let mut buf = vec![]; - /// buf.put_f32_be(1.2f32); + /// buf.put_f32(1.2f32); /// assert_eq!(buf, b"\x3F\x99\x99\x9A"); /// ``` /// @@ -918,10 +797,8 @@ /// /// This function panics if there is not enough remaining capacity in /// `self`. - fn put_f32_be(&mut self, n: f32) { - let mut buf = [0; 4]; - BigEndian::write_f32(&mut buf, n); - self.put_slice(&buf) + fn put_f32(&mut self, n: f32) { + self.put_u32(n.to_bits()); } /// Writes an IEEE754 single-precision (4 bytes) floating point number to @@ -944,17 +821,7 @@ /// This function panics if there is not enough remaining capacity in /// `self`. fn put_f32_le(&mut self, n: f32) { - let mut buf = [0; 4]; - LittleEndian::write_f32(&mut buf, n); - self.put_slice(&buf) - } - - #[doc(hidden)] - #[deprecated(note="use put_f64_be or put_f64_le")] - fn put_f64(&mut self, n: f64) where Self: Sized { - let mut buf = [0; 8]; - T::write_f64(&mut buf, n); - self.put_slice(&buf) + self.put_u32_le(n.to_bits()); } /// Writes an IEEE754 double-precision (8 bytes) floating point number to @@ -968,7 +835,7 @@ /// use bytes::BufMut; /// /// let mut buf = vec![]; - /// buf.put_f64_be(1.2f64); + /// buf.put_f64(1.2f64); /// assert_eq!(buf, b"\x3F\xF3\x33\x33\x33\x33\x33\x33"); /// ``` /// @@ -976,10 +843,8 @@ /// /// This function panics if there is not enough remaining capacity in /// `self`. - fn put_f64_be(&mut self, n: f64) { - let mut buf = [0; 8]; - BigEndian::write_f64(&mut buf, n); - self.put_slice(&buf) + fn put_f64(&mut self, n: f64) { + self.put_u64(n.to_bits()); } /// Writes an IEEE754 double-precision (8 bytes) floating point number to @@ -1002,38 +867,27 @@ /// This function panics if there is not enough remaining capacity in /// `self`. fn put_f64_le(&mut self, n: f64) { - let mut buf = [0; 8]; - LittleEndian::write_f64(&mut buf, n); - self.put_slice(&buf) + self.put_u64_le(n.to_bits()); } - /// Creates a "by reference" adaptor for this instance of `BufMut`. - /// - /// The returned adapter also implements `BufMut` and will simply borrow - /// `self`. + /// Creates an adaptor which can write at most `limit` bytes to `self`. /// /// # Examples /// /// ``` /// use bytes::BufMut; - /// use std::io; - /// - /// let mut buf = vec![]; - /// - /// { - /// let mut reference = buf.by_ref(); - /// - /// // Adapt reference to `std::io::Write`. - /// let mut writer = reference.writer(); /// - /// // Use the buffer as a writter - /// io::Write::write(&mut writer, &b"hello world"[..]).unwrap(); - /// } // drop our &mut reference so that we can use `buf` again + /// let arr = &mut [0u8; 128][..]; + /// assert_eq!(arr.remaining_mut(), 128); /// - /// assert_eq!(buf, &b"hello world"[..]); + /// let dst = arr.limit(10); + /// assert_eq!(dst.remaining_mut(), 10); /// ``` - fn by_ref(&mut self) -> &mut Self where Self: Sized { - self + fn limit(self, limit: usize) -> Limit + where + Self: Sized, + { + limit::new(self, limit) } /// Creates an adaptor which implements the `Write` trait for `self`. @@ -1058,98 +912,186 @@ /// /// assert_eq!(*buf, b"hello world"[..]); /// ``` - fn writer(self) -> Writer where Self: Sized { - super::writer::new(self) + #[cfg(feature = "std")] + fn writer(self) -> Writer + where + Self: Sized, + { + writer::new(self) } -} -impl<'a, T: BufMut + ?Sized> BufMut for &'a mut T { - fn remaining_mut(&self) -> usize { - (**self).remaining_mut() + /// Creates an adapter which will chain this buffer with another. + /// + /// The returned `BufMut` instance will first write to all bytes from + /// `self`. Afterwards, it will write to `next`. + /// + /// # Examples + /// + /// ``` + /// use bytes::BufMut; + /// + /// let mut a = [0u8; 5]; + /// let mut b = [0u8; 6]; + /// + /// let mut chain = (&mut a[..]).chain_mut(&mut b[..]); + /// + /// chain.put_slice(b"hello world"); + /// + /// assert_eq!(&a[..], b"hello"); + /// assert_eq!(&b[..], b" world"); + /// ``` + fn chain_mut(self, next: U) -> Chain + where + Self: Sized, + { + Chain::new(self, next) } +} - unsafe fn bytes_mut(&mut self) -> &mut [u8] { - (**self).bytes_mut() - } +macro_rules! deref_forward_bufmut { + () => { + fn remaining_mut(&self) -> usize { + (**self).remaining_mut() + } - unsafe fn bytes_vec_mut<'b>(&'b mut self, dst: &mut [&'b mut IoVec]) -> usize { - (**self).bytes_vec_mut(dst) - } + fn chunk_mut(&mut self) -> &mut UninitSlice { + (**self).chunk_mut() + } - unsafe fn advance_mut(&mut self, cnt: usize) { - (**self).advance_mut(cnt) - } -} + unsafe fn advance_mut(&mut self, cnt: usize) { + (**self).advance_mut(cnt) + } -impl BufMut for Box { - fn remaining_mut(&self) -> usize { - (**self).remaining_mut() - } + fn put_slice(&mut self, src: &[u8]) { + (**self).put_slice(src) + } - unsafe fn bytes_mut(&mut self) -> &mut [u8] { - (**self).bytes_mut() - } + fn put_u8(&mut self, n: u8) { + (**self).put_u8(n) + } - unsafe fn bytes_vec_mut<'b>(&'b mut self, dst: &mut [&'b mut IoVec]) -> usize { - (**self).bytes_vec_mut(dst) - } + fn put_i8(&mut self, n: i8) { + (**self).put_i8(n) + } - unsafe fn advance_mut(&mut self, cnt: usize) { - (**self).advance_mut(cnt) - } + fn put_u16(&mut self, n: u16) { + (**self).put_u16(n) + } + + fn put_u16_le(&mut self, n: u16) { + (**self).put_u16_le(n) + } + + fn put_i16(&mut self, n: i16) { + (**self).put_i16(n) + } + + fn put_i16_le(&mut self, n: i16) { + (**self).put_i16_le(n) + } + + fn put_u32(&mut self, n: u32) { + (**self).put_u32(n) + } + + fn put_u32_le(&mut self, n: u32) { + (**self).put_u32_le(n) + } + + fn put_i32(&mut self, n: i32) { + (**self).put_i32(n) + } + + fn put_i32_le(&mut self, n: i32) { + (**self).put_i32_le(n) + } + + fn put_u64(&mut self, n: u64) { + (**self).put_u64(n) + } + + fn put_u64_le(&mut self, n: u64) { + (**self).put_u64_le(n) + } + + fn put_i64(&mut self, n: i64) { + (**self).put_i64(n) + } + + fn put_i64_le(&mut self, n: i64) { + (**self).put_i64_le(n) + } + }; +} + +unsafe impl BufMut for &mut T { + deref_forward_bufmut!(); } -impl + AsRef<[u8]>> BufMut for io::Cursor { +unsafe impl BufMut for Box { + deref_forward_bufmut!(); +} + +unsafe impl BufMut for &mut [u8] { + #[inline] fn remaining_mut(&self) -> usize { - use Buf; - self.remaining() + self.len() } - /// Advance the internal cursor of the BufMut - unsafe fn advance_mut(&mut self, cnt: usize) { - use Buf; - self.advance(cnt); + #[inline] + fn chunk_mut(&mut self) -> &mut UninitSlice { + // UninitSlice is repr(transparent), so safe to transmute + unsafe { &mut *(*self as *mut [u8] as *mut _) } } - /// Returns a mutable slice starting at the current BufMut position and of - /// length between 0 and `BufMut::remaining()`. - /// - /// The returned byte slice may represent uninitialized memory. - unsafe fn bytes_mut(&mut self) -> &mut [u8] { - let len = self.get_ref().as_ref().len(); - let pos = self.position() as usize; + #[inline] + unsafe fn advance_mut(&mut self, cnt: usize) { + // Lifetime dance taken from `impl Write for &mut [u8]`. + let (_, b) = core::mem::replace(self, &mut []).split_at_mut(cnt); + *self = b; + } - if pos >= len { - return Default::default(); + #[inline] + fn put_slice(&mut self, src: &[u8]) { + self[..src.len()].copy_from_slice(src); + unsafe { + self.advance_mut(src.len()); } + } - &mut (self.get_mut().as_mut())[pos..] + fn put_bytes(&mut self, val: u8, cnt: usize) { + assert!(self.remaining_mut() >= cnt); + unsafe { + ptr::write_bytes(self.as_mut_ptr(), val, cnt); + self.advance_mut(cnt); + } } } -impl BufMut for Vec { +unsafe impl BufMut for Vec { #[inline] fn remaining_mut(&self) -> usize { - usize::MAX - self.len() + // A vector can never have more than isize::MAX bytes + core::isize::MAX as usize - self.len() } #[inline] 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); } #[inline] - unsafe fn bytes_mut(&mut self) -> &mut [u8] { - use std::slice; - + fn chunk_mut(&mut self) -> &mut UninitSlice { if self.capacity() == self.len() { self.reserve(64); // Grow the vec } @@ -1158,10 +1100,43 @@ let len = self.len(); let ptr = self.as_mut_ptr(); - &mut slice::from_raw_parts_mut(ptr, cap)[len..] + unsafe { &mut UninitSlice::from_raw_parts_mut(ptr, cap)[len..] } + } + + // Specialize these methods so they can skip checking `remaining_mut` + // and `advance_mut`. + fn put(&mut self, mut src: T) + where + Self: Sized, + { + // In case the src isn't contiguous, reserve upfront + self.reserve(src.remaining()); + + while src.has_remaining() { + let l; + + // a block to contain the src.bytes() borrow + { + let s = src.chunk(); + l = s.len(); + self.extend_from_slice(s); + } + + src.advance(l); + } + } + + #[inline] + fn put_slice(&mut self, src: &[u8]) { + self.extend_from_slice(src); + } + + fn put_bytes(&mut self, val: u8, cnt: usize) { + let new_len = self.len().checked_add(cnt).unwrap(); + self.resize(new_len, val); } } -// The existance of this function makes the compiler catch if the BufMut +// The existence of this function makes the compiler catch if the BufMut // trait is "object-safe" or not. -fn _assert_trait_object(_b: &BufMut) {} +fn _assert_trait_object(_b: &dyn BufMut) {} diff -Nru rust-bytes-0.4.12/src/buf/buf.rs rust-bytes-1.1.0/src/buf/buf.rs --- rust-bytes-0.4.12/src/buf/buf.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/src/buf/buf.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,1154 +0,0 @@ -use super::{IntoBuf, Take, Reader, Iter, FromBuf, Chain}; -use byteorder::{BigEndian, ByteOrder, LittleEndian}; -use iovec::IoVec; - -use std::{cmp, io, ptr}; - -macro_rules! buf_get_impl { - ($this:ident, $size:expr, $conv:path) => ({ - // try to convert directly from the bytes - let ret = { - // this Option trick is to avoid keeping a borrow on self - // when advance() is called (mut borrow) and to call bytes() only once - if let Some(src) = $this.bytes().get(..($size)) { - Some($conv(src)) - } else { - None - } - }; - if let Some(ret) = ret { - // if the direct convertion was possible, advance and return - $this.advance($size); - return ret; - } else { - // if not we copy the bytes in a temp buffer then convert - let mut buf = [0; ($size)]; - $this.copy_to_slice(&mut buf); // (do the advance) - return $conv(&buf); - } - }); - ($this:ident, $buf_size:expr, $conv:path, $len_to_read:expr) => ({ - // The same trick as above does not improve the best case speed. - // It seems to be linked to the way the method is optimised by the compiler - let mut buf = [0; ($buf_size)]; - $this.copy_to_slice(&mut buf[..($len_to_read)]); - return $conv(&buf[..($len_to_read)], $len_to_read); - }); -} - -/// Read bytes from a buffer. -/// -/// A buffer stores bytes in memory such that read operations are infallible. -/// The underlying storage may or may not be in contiguous memory. A `Buf` value -/// is a cursor into the buffer. Reading from `Buf` advances the cursor -/// position. It can be thought of as an efficient `Iterator` for collections of -/// bytes. -/// -/// The simplest `Buf` is a `Cursor` wrapping a `[u8]`. -/// -/// ``` -/// use bytes::Buf; -/// use std::io::Cursor; -/// -/// let mut buf = Cursor::new(b"hello world"); -/// -/// assert_eq!(b'h', buf.get_u8()); -/// assert_eq!(b'e', buf.get_u8()); -/// assert_eq!(b'l', buf.get_u8()); -/// -/// let mut rest = [0; 8]; -/// buf.copy_to_slice(&mut rest); -/// -/// assert_eq!(&rest[..], b"lo world"); -/// ``` -pub trait Buf { - /// Returns the number of bytes between the current position and the end of - /// the buffer. - /// - /// This value is greater than or equal to the length of the slice returned - /// by `bytes`. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"hello world"); - /// - /// assert_eq!(buf.remaining(), 11); - /// - /// buf.get_u8(); - /// - /// assert_eq!(buf.remaining(), 10); - /// ``` - /// - /// # Implementer notes - /// - /// Implementations of `remaining` should ensure that the return value does - /// not change unless a call is made to `advance` or any other function that - /// is documented to change the `Buf`'s current position. - fn remaining(&self) -> usize; - - /// Returns a slice starting at the current position and of length between 0 - /// 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. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"hello world"); - /// - /// assert_eq!(buf.bytes(), b"hello world"); - /// - /// buf.advance(6); - /// - /// assert_eq!(buf.bytes(), b"world"); - /// ``` - /// - /// # Implementer notes - /// - /// This function should never panic. Once the end of the buffer is reached, - /// i.e., `Buf::remaining` returns 0, calls to `bytes` should return an - /// empty slice. - fn bytes(&self) -> &[u8]; - - /// Fills `dst` with potentially multiple slices starting at `self`'s - /// current position. - /// - /// If the `Buf` is backed by disjoint slices of bytes, `bytes_vec` enables - /// fetching more than one slice at once. `dst` is a slice of `IoVec` - /// references, enabling the slice to be directly used with [`writev`] - /// without any further conversion. The sum of the lengths of all the - /// buffers in `dst` will be less than or equal to `Buf::remaining()`. - /// - /// The entries in `dst` will be overwritten, but the data **contained** by - /// the slices **will not** be modified. If `bytes_vec` does not fill every - /// entry in `dst`, then `dst` is guaranteed to contain all remaining slices - /// in `self. - /// - /// This is a lower level function. Most operations are done with other - /// functions. - /// - /// # Implementer notes - /// - /// This function should never panic. Once the end of the buffer is reached, - /// i.e., `Buf::remaining` returns 0, calls to `bytes_vec` must return 0 - /// without mutating `dst`. - /// - /// Implementations should also take care to properly handle being called - /// with `dst` being a zero length slice. - /// - /// [`writev`]: http://man7.org/linux/man-pages/man2/readv.2.html - fn bytes_vec<'a>(&'a self, dst: &mut [&'a IoVec]) -> usize { - if dst.is_empty() { - return 0; - } - - if self.has_remaining() { - dst[0] = self.bytes().into(); - 1 - } else { - 0 - } - } - - /// Advance the internal cursor of the Buf - /// - /// The next call to `bytes` will return a slice starting `cnt` bytes - /// further into the underlying buffer. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"hello world"); - /// - /// assert_eq!(buf.bytes(), b"hello world"); - /// - /// buf.advance(6); - /// - /// assert_eq!(buf.bytes(), b"world"); - /// ``` - /// - /// # Panics - /// - /// This function **may** panic if `cnt > self.remaining()`. - /// - /// # Implementer notes - /// - /// It is recommended for implementations of `advance` to panic if `cnt > - /// self.remaining()`. If the implementation does not panic, the call must - /// behave as if `cnt == self.remaining()`. - /// - /// A call with `cnt == 0` should never panic and be a no-op. - fn advance(&mut self, cnt: usize); - - /// Returns true if there are any more bytes to consume - /// - /// This is equivalent to `self.remaining() != 0`. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"a"); - /// - /// assert!(buf.has_remaining()); - /// - /// buf.get_u8(); - /// - /// assert!(!buf.has_remaining()); - /// ``` - fn has_remaining(&self) -> bool { - self.remaining() > 0 - } - - /// Copies bytes from `self` into `dst`. - /// - /// The cursor is advanced by the number of bytes copied. `self` must have - /// enough remaining bytes to fill `dst`. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"hello world"); - /// let mut dst = [0; 5]; - /// - /// buf.copy_to_slice(&mut dst); - /// assert_eq!(b"hello", &dst); - /// assert_eq!(6, buf.remaining()); - /// ``` - /// - /// # Panics - /// - /// This function panics if `self.remaining() < dst.len()` - fn copy_to_slice(&mut self, dst: &mut [u8]) { - let mut off = 0; - - assert!(self.remaining() >= dst.len()); - - while off < dst.len() { - let cnt; - - unsafe { - let src = self.bytes(); - cnt = cmp::min(src.len(), dst.len() - off); - - ptr::copy_nonoverlapping( - src.as_ptr(), dst[off..].as_mut_ptr(), cnt); - - off += src.len(); - } - - self.advance(cnt); - } - } - - /// Gets an unsigned 8 bit integer from `self`. - /// - /// The current position is advanced by 1. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x08 hello"); - /// assert_eq!(8, buf.get_u8()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is no more remaining data in `self`. - fn get_u8(&mut self) -> u8 { - assert!(self.remaining() >= 1); - let ret = self.bytes()[0]; - self.advance(1); - ret - } - - /// Gets a signed 8 bit integer from `self`. - /// - /// The current position is advanced by 1. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x08 hello"); - /// assert_eq!(8, buf.get_i8()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is no more remaining data in `self`. - fn get_i8(&mut self) -> i8 { - assert!(self.remaining() >= 1); - let ret = self.bytes()[0] as i8; - self.advance(1); - ret - } - - #[doc(hidden)] - #[deprecated(note="use get_u16_be or get_u16_le")] - fn get_u16(&mut self) -> u16 where Self: Sized { - let mut buf = [0; 2]; - self.copy_to_slice(&mut buf); - T::read_u16(&buf) - } - - /// Gets an unsigned 16 bit integer from `self` in big-endian byte order. - /// - /// The current position is advanced by 2. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x08\x09 hello"); - /// assert_eq!(0x0809, buf.get_u16_be()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_u16_be(&mut self) -> u16 { - buf_get_impl!(self, 2, BigEndian::read_u16); - } - - /// Gets an unsigned 16 bit integer from `self` in little-endian byte order. - /// - /// The current position is advanced by 2. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x09\x08 hello"); - /// assert_eq!(0x0809, buf.get_u16_le()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_u16_le(&mut self) -> u16 { - buf_get_impl!(self, 2, LittleEndian::read_u16); - } - - #[doc(hidden)] - #[deprecated(note="use get_i16_be or get_i16_le")] - fn get_i16(&mut self) -> i16 where Self: Sized { - let mut buf = [0; 2]; - self.copy_to_slice(&mut buf); - T::read_i16(&buf) - } - - /// Gets a signed 16 bit integer from `self` in big-endian byte order. - /// - /// The current position is advanced by 2. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x08\x09 hello"); - /// assert_eq!(0x0809, buf.get_i16_be()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_i16_be(&mut self) -> i16 { - buf_get_impl!(self, 2, BigEndian::read_i16); - } - - /// Gets a signed 16 bit integer from `self` in little-endian byte order. - /// - /// The current position is advanced by 2. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x09\x08 hello"); - /// assert_eq!(0x0809, buf.get_i16_le()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_i16_le(&mut self) -> i16 { - buf_get_impl!(self, 2, LittleEndian::read_i16); - } - - #[doc(hidden)] - #[deprecated(note="use get_u32_be or get_u32_le")] - fn get_u32(&mut self) -> u32 where Self: Sized { - let mut buf = [0; 4]; - self.copy_to_slice(&mut buf); - T::read_u32(&buf) - } - - /// Gets an unsigned 32 bit integer from `self` in the big-endian byte order. - /// - /// The current position is advanced by 4. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x08\x09\xA0\xA1 hello"); - /// assert_eq!(0x0809A0A1, buf.get_u32_be()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_u32_be(&mut self) -> u32 { - buf_get_impl!(self, 4, BigEndian::read_u32); - } - - /// Gets an unsigned 32 bit integer from `self` in the little-endian byte order. - /// - /// The current position is advanced by 4. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\xA1\xA0\x09\x08 hello"); - /// assert_eq!(0x0809A0A1, buf.get_u32_le()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_u32_le(&mut self) -> u32 { - buf_get_impl!(self, 4, LittleEndian::read_u32); - } - - #[doc(hidden)] - #[deprecated(note="use get_i32_be or get_i32_le")] - fn get_i32(&mut self) -> i32 where Self: Sized { - let mut buf = [0; 4]; - self.copy_to_slice(&mut buf); - T::read_i32(&buf) - } - - /// Gets a signed 32 bit integer from `self` in big-endian byte order. - /// - /// The current position is advanced by 4. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x08\x09\xA0\xA1 hello"); - /// assert_eq!(0x0809A0A1, buf.get_i32_be()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_i32_be(&mut self) -> i32 { - buf_get_impl!(self, 4, BigEndian::read_i32); - } - - /// Gets a signed 32 bit integer from `self` in little-endian byte order. - /// - /// The current position is advanced by 4. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\xA1\xA0\x09\x08 hello"); - /// assert_eq!(0x0809A0A1, buf.get_i32_le()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_i32_le(&mut self) -> i32 { - buf_get_impl!(self, 4, LittleEndian::read_i32); - } - - #[doc(hidden)] - #[deprecated(note="use get_u64_be or get_u64_le")] - fn get_u64(&mut self) -> u64 where Self: Sized { - let mut buf = [0; 8]; - self.copy_to_slice(&mut buf); - T::read_u64(&buf) - } - - /// Gets an unsigned 64 bit integer from `self` in big-endian byte order. - /// - /// The current position is advanced by 8. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x01\x02\x03\x04\x05\x06\x07\x08 hello"); - /// assert_eq!(0x0102030405060708, buf.get_u64_be()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_u64_be(&mut self) -> u64 { - buf_get_impl!(self, 8, BigEndian::read_u64); - } - - /// Gets an unsigned 64 bit integer from `self` in little-endian byte order. - /// - /// The current position is advanced by 8. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x08\x07\x06\x05\x04\x03\x02\x01 hello"); - /// assert_eq!(0x0102030405060708, buf.get_u64_le()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_u64_le(&mut self) -> u64 { - buf_get_impl!(self, 8, LittleEndian::read_u64); - } - - #[doc(hidden)] - #[deprecated(note="use get_i64_be or get_i64_le")] - fn get_i64(&mut self) -> i64 where Self: Sized { - let mut buf = [0; 8]; - self.copy_to_slice(&mut buf); - T::read_i64(&buf) - } - - /// Gets a signed 64 bit integer from `self` in big-endian byte order. - /// - /// The current position is advanced by 8. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x01\x02\x03\x04\x05\x06\x07\x08 hello"); - /// assert_eq!(0x0102030405060708, buf.get_i64_be()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_i64_be(&mut self) -> i64 { - buf_get_impl!(self, 8, BigEndian::read_i64); - } - - /// Gets a signed 64 bit integer from `self` in little-endian byte order. - /// - /// The current position is advanced by 8. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x08\x07\x06\x05\x04\x03\x02\x01 hello"); - /// assert_eq!(0x0102030405060708, buf.get_i64_le()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_i64_le(&mut self) -> i64 { - buf_get_impl!(self, 8, LittleEndian::read_i64); - } - - /// Gets an unsigned 128 bit integer from `self` in big-endian byte order. - /// - /// **NOTE:** This method requires the `i128` feature. - /// The current position is advanced by 16. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16 hello"); - /// assert_eq!(0x01020304050607080910111213141516, buf.get_u128_be()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - #[cfg(feature = "i128")] - fn get_u128_be(&mut self) -> u128 { - buf_get_impl!(self, 16, BigEndian::read_u128); - } - - /// Gets an unsigned 128 bit integer from `self` in little-endian byte order. - /// - /// **NOTE:** This method requires the `i128` feature. - /// The current position is advanced by 16. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01 hello"); - /// assert_eq!(0x01020304050607080910111213141516, buf.get_u128_le()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - #[cfg(feature = "i128")] - fn get_u128_le(&mut self) -> u128 { - buf_get_impl!(self, 16, LittleEndian::read_u128); - } - - /// Gets a signed 128 bit integer from `self` in big-endian byte order. - /// - /// **NOTE:** This method requires the `i128` feature. - /// The current position is advanced by 16. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16 hello"); - /// assert_eq!(0x01020304050607080910111213141516, buf.get_i128_be()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - #[cfg(feature = "i128")] - fn get_i128_be(&mut self) -> i128 { - buf_get_impl!(self, 16, BigEndian::read_i128); - } - - /// Gets a signed 128 bit integer from `self` in little-endian byte order. - /// - /// **NOTE:** This method requires the `i128` feature. - /// The current position is advanced by 16. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01 hello"); - /// assert_eq!(0x01020304050607080910111213141516, buf.get_i128_le()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - #[cfg(feature = "i128")] - fn get_i128_le(&mut self) -> i128 { - buf_get_impl!(self, 16, LittleEndian::read_i128); - } - - #[doc(hidden)] - #[deprecated(note="use get_uint_be or get_uint_le")] - fn get_uint(&mut self, nbytes: usize) -> u64 where Self: Sized { - let mut buf = [0; 8]; - self.copy_to_slice(&mut buf[..nbytes]); - T::read_uint(&buf[..nbytes], nbytes) - } - - /// Gets an unsigned n-byte integer from `self` in big-endian byte order. - /// - /// The current position is advanced by `nbytes`. - /// - /// # Examples - /// - /// ``` - /// use bytes::{Buf, BigEndian}; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x01\x02\x03 hello"); - /// assert_eq!(0x010203, buf.get_uint_be(3)); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_uint_be(&mut self, nbytes: usize) -> u64 { - buf_get_impl!(self, 8, BigEndian::read_uint, nbytes); - } - - /// Gets an unsigned n-byte integer from `self` in little-endian byte order. - /// - /// The current position is advanced by `nbytes`. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x03\x02\x01 hello"); - /// assert_eq!(0x010203, buf.get_uint_le(3)); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_uint_le(&mut self, nbytes: usize) -> u64 { - buf_get_impl!(self, 8, LittleEndian::read_uint, nbytes); - } - - #[doc(hidden)] - #[deprecated(note="use get_int_be or get_int_le")] - fn get_int(&mut self, nbytes: usize) -> i64 where Self: Sized { - let mut buf = [0; 8]; - self.copy_to_slice(&mut buf[..nbytes]); - T::read_int(&buf[..nbytes], nbytes) - } - - /// Gets a signed n-byte integer from `self` in big-endian byte order. - /// - /// The current position is advanced by `nbytes`. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x01\x02\x03 hello"); - /// assert_eq!(0x010203, buf.get_int_be(3)); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_int_be(&mut self, nbytes: usize) -> i64 { - buf_get_impl!(self, 8, BigEndian::read_int, nbytes); - } - - /// Gets a signed n-byte integer from `self` in little-endian byte order. - /// - /// The current position is advanced by `nbytes`. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x03\x02\x01 hello"); - /// assert_eq!(0x010203, buf.get_int_le(3)); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_int_le(&mut self, nbytes: usize) -> i64 { - buf_get_impl!(self, 8, LittleEndian::read_int, nbytes); - } - - #[doc(hidden)] - #[deprecated(note="use get_f32_be or get_f32_le")] - fn get_f32(&mut self) -> f32 where Self: Sized { - let mut buf = [0; 4]; - self.copy_to_slice(&mut buf); - T::read_f32(&buf) - } - - /// Gets an IEEE754 single-precision (4 bytes) floating point number from - /// `self` in big-endian byte order. - /// - /// The current position is advanced by 4. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x3F\x99\x99\x9A hello"); - /// assert_eq!(1.2f32, buf.get_f32_be()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_f32_be(&mut self) -> f32 { - buf_get_impl!(self, 4, BigEndian::read_f32); - } - - /// Gets an IEEE754 single-precision (4 bytes) floating point number from - /// `self` in little-endian byte order. - /// - /// The current position is advanced by 4. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x9A\x99\x99\x3F hello"); - /// assert_eq!(1.2f32, buf.get_f32_le()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_f32_le(&mut self) -> f32 { - buf_get_impl!(self, 4, LittleEndian::read_f32); - } - - #[doc(hidden)] - #[deprecated(note="use get_f64_be or get_f64_le")] - fn get_f64(&mut self) -> f64 where Self: Sized { - let mut buf = [0; 8]; - self.copy_to_slice(&mut buf); - T::read_f64(&buf) - } - - /// Gets an IEEE754 double-precision (8 bytes) floating point number from - /// `self` in big-endian byte order. - /// - /// The current position is advanced by 8. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x3F\xF3\x33\x33\x33\x33\x33\x33 hello"); - /// assert_eq!(1.2f64, buf.get_f64_be()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_f64_be(&mut self) -> f64 { - buf_get_impl!(self, 8, BigEndian::read_f64); - } - - /// Gets an IEEE754 double-precision (8 bytes) floating point number from - /// `self` in little-endian byte order. - /// - /// The current position is advanced by 8. - /// - /// # Examples - /// - /// ``` - /// use bytes::Buf; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new(b"\x33\x33\x33\x33\x33\x33\xF3\x3F hello"); - /// assert_eq!(1.2f64, buf.get_f64_le()); - /// ``` - /// - /// # Panics - /// - /// This function panics if there is not enough remaining data in `self`. - fn get_f64_le(&mut self) -> f64 { - buf_get_impl!(self, 8, LittleEndian::read_f64); - } - - /// Transforms a `Buf` into a concrete buffer. - /// - /// `collect()` can operate on any value that implements `Buf`, and turn it - /// into the relevent concrete buffer type. - /// - /// # Examples - /// - /// Collecting a buffer and loading the contents into a `Vec`. - /// - /// ``` - /// use bytes::{Buf, Bytes, IntoBuf}; - /// - /// let buf = Bytes::from(&b"hello world"[..]).into_buf(); - /// let vec: Vec = buf.collect(); - /// - /// assert_eq!(vec, &b"hello world"[..]); - /// ``` - fn collect(self) -> B - where Self: Sized, - B: FromBuf, - { - B::from_buf(self) - } - - /// Creates an adaptor which will read at most `limit` bytes from `self`. - /// - /// This function returns a new instance of `Buf` which will read at most - /// `limit` bytes. - /// - /// # Examples - /// - /// ``` - /// use bytes::{Buf, BufMut}; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new("hello world").take(5); - /// let mut dst = vec![]; - /// - /// dst.put(&mut buf); - /// assert_eq!(dst, b"hello"); - /// - /// let mut buf = buf.into_inner(); - /// dst.clear(); - /// dst.put(&mut buf); - /// assert_eq!(dst, b" world"); - /// ``` - fn take(self, limit: usize) -> Take - where Self: Sized - { - super::take::new(self, limit) - } - - /// Creates an adaptor which will chain this buffer with another. - /// - /// The returned `Buf` instance will first consume all bytes from `self`. - /// Afterwards the output is equivalent to the output of next. - /// - /// # Examples - /// - /// ``` - /// use bytes::{Bytes, Buf, IntoBuf}; - /// use bytes::buf::Chain; - /// - /// let buf = Bytes::from(&b"hello "[..]).into_buf() - /// .chain(Bytes::from(&b"world"[..])); - /// - /// let full: Bytes = buf.collect(); - /// assert_eq!(full[..], b"hello world"[..]); - /// ``` - fn chain(self, next: U) -> Chain - where U: IntoBuf, - Self: Sized, - { - Chain::new(self, next.into_buf()) - } - - /// Creates a "by reference" adaptor for this instance of `Buf`. - /// - /// The returned adaptor also implements `Buf` and will simply borrow `self`. - /// - /// # Examples - /// - /// ``` - /// use bytes::{Buf, BufMut}; - /// use std::io::Cursor; - /// - /// let mut buf = Cursor::new("hello world"); - /// let mut dst = vec![]; - /// - /// { - /// let mut reference = buf.by_ref(); - /// dst.put(&mut reference.take(5)); - /// assert_eq!(dst, b"hello"); - /// } // drop our &mut reference so we can use `buf` again - /// - /// dst.clear(); - /// dst.put(&mut buf); - /// assert_eq!(dst, b" world"); - /// ``` - fn by_ref(&mut self) -> &mut Self where Self: Sized { - self - } - - /// Creates an adaptor which implements the `Read` trait for `self`. - /// - /// This function returns a new value which implements `Read` by adapting - /// the `Read` trait functions to the `Buf` trait functions. Given that - /// `Buf` operations are infallible, none of the `Read` functions will - /// return with `Err`. - /// - /// # Examples - /// - /// ``` - /// use bytes::{Buf, IntoBuf, Bytes}; - /// use std::io::Read; - /// - /// let buf = Bytes::from("hello world").into_buf(); - /// - /// let mut reader = buf.reader(); - /// let mut dst = [0; 1024]; - /// - /// let num = reader.read(&mut dst).unwrap(); - /// - /// assert_eq!(11, num); - /// assert_eq!(&dst[..11], b"hello world"); - /// ``` - fn reader(self) -> Reader where Self: Sized { - super::reader::new(self) - } - - /// Returns an iterator over the bytes contained by the buffer. - /// - /// # Examples - /// - /// ``` - /// use bytes::{Buf, IntoBuf, Bytes}; - /// - /// let buf = Bytes::from(&b"abc"[..]).into_buf(); - /// let mut iter = buf.iter(); - /// - /// assert_eq!(iter.next(), Some(b'a')); - /// assert_eq!(iter.next(), Some(b'b')); - /// assert_eq!(iter.next(), Some(b'c')); - /// assert_eq!(iter.next(), None); - /// ``` - fn iter(self) -> Iter where Self: Sized { - super::iter::new(self) - } -} - -impl<'a, T: Buf + ?Sized> Buf for &'a mut T { - fn remaining(&self) -> usize { - (**self).remaining() - } - - fn bytes(&self) -> &[u8] { - (**self).bytes() - } - - fn bytes_vec<'b>(&'b self, dst: &mut [&'b IoVec]) -> usize { - (**self).bytes_vec(dst) - } - - fn advance(&mut self, cnt: usize) { - (**self).advance(cnt) - } -} - -impl Buf for Box { - fn remaining(&self) -> usize { - (**self).remaining() - } - - fn bytes(&self) -> &[u8] { - (**self).bytes() - } - - fn bytes_vec<'b>(&'b self, dst: &mut [&'b IoVec]) -> usize { - (**self).bytes_vec(dst) - } - - fn advance(&mut self, cnt: usize) { - (**self).advance(cnt) - } -} - -impl> Buf for io::Cursor { - fn remaining(&self) -> usize { - let len = self.get_ref().as_ref().len(); - let pos = self.position(); - - if pos >= len as u64 { - return 0; - } - - len - pos as usize - } - - fn bytes(&self) -> &[u8] { - let len = self.get_ref().as_ref().len(); - let pos = self.position() as usize; - - if pos >= len { - return Default::default(); - } - - &(self.get_ref().as_ref())[pos..] - } - - fn advance(&mut self, cnt: usize) { - let pos = (self.position() as usize) - .checked_add(cnt).expect("overflow"); - - assert!(pos <= self.get_ref().as_ref().len()); - - self.set_position(pos as u64); - } -} - -impl Buf for Option<[u8; 1]> { - fn remaining(&self) -> usize { - if self.is_some() { - 1 - } else { - 0 - } - } - - fn bytes(&self) -> &[u8] { - self.as_ref().map(AsRef::as_ref) - .unwrap_or(Default::default()) - } - - fn advance(&mut self, cnt: usize) { - if cnt == 0 { - return; - } - - if self.is_none() { - panic!("overflow"); - } else { - assert_eq!(1, cnt); - *self = None; - } - } -} - -// The existance of this function makes the compiler catch if the Buf -// trait is "object-safe" or not. -fn _assert_trait_object(_b: &Buf) {} diff -Nru rust-bytes-0.4.12/src/buf/chain.rs rust-bytes-1.1.0/src/buf/chain.rs --- rust-bytes-0.4.12/src/buf/chain.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/src/buf/chain.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,10 +1,13 @@ -use {Buf, BufMut}; -use iovec::IoVec; +use crate::buf::{IntoIter, UninitSlice}; +use crate::{Buf, BufMut, Bytes}; + +#[cfg(feature = "std")] +use std::io::IoSlice; /// A `Chain` sequences two buffers. /// /// `Chain` is an adapter that links two underlying buffers and provides a -/// continous view across both buffers. It is able to sequence either immutable +/// continuous view across both buffers. It is able to sequence either immutable /// buffers ([`Buf`] values) or mutable buffers ([`BufMut`] values). /// /// This struct is generally created by calling [`Buf::chain`]. Please see that @@ -13,13 +16,12 @@ /// # Examples /// /// ``` -/// use bytes::{Bytes, Buf, IntoBuf}; -/// use bytes::buf::Chain; +/// use bytes::{Bytes, Buf}; /// -/// let buf = Bytes::from(&b"hello "[..]).into_buf() -/// .chain(Bytes::from(&b"world"[..])); +/// let mut buf = (&b"hello "[..]) +/// .chain(&b"world"[..]); /// -/// let full: Bytes = buf.collect(); +/// let full: Bytes = buf.copy_to_bytes(11); /// assert_eq!(full[..], b"hello world"[..]); /// ``` /// @@ -34,24 +36,8 @@ impl Chain { /// Creates a new `Chain` sequencing the provided values. - /// - /// # Examples - /// - /// ``` - /// use bytes::BytesMut; - /// use bytes::buf::Chain; - /// - /// let buf = Chain::new( - /// BytesMut::with_capacity(1024), - /// BytesMut::with_capacity(1024)); - /// - /// // Use the chained buffer - /// ``` - pub fn new(a: T, b: U) -> Chain { - Chain { - a: a, - b: b, - } + pub(crate) fn new(a: T, b: U) -> Chain { + Chain { a, b } } /// Gets a reference to the first underlying `Buf`. @@ -59,12 +45,12 @@ /// # Examples /// /// ``` - /// use bytes::{Bytes, Buf, IntoBuf}; + /// use bytes::Buf; /// - /// let buf = Bytes::from(&b"hello"[..]).into_buf() - /// .chain(Bytes::from(&b"world"[..])); + /// let buf = (&b"hello"[..]) + /// .chain(&b"world"[..]); /// - /// assert_eq!(buf.first_ref().get_ref()[..], b"hello"[..]); + /// assert_eq!(buf.first_ref()[..], b"hello"[..]); /// ``` pub fn first_ref(&self) -> &T { &self.a @@ -75,15 +61,15 @@ /// # Examples /// /// ``` - /// use bytes::{Bytes, Buf, IntoBuf}; + /// use bytes::Buf; /// - /// let mut buf = Bytes::from(&b"hello "[..]).into_buf() - /// .chain(Bytes::from(&b"world"[..])); + /// let mut buf = (&b"hello"[..]) + /// .chain(&b"world"[..]); /// - /// buf.first_mut().set_position(1); + /// buf.first_mut().advance(1); /// - /// let full: Bytes = buf.collect(); - /// assert_eq!(full[..], b"ello world"[..]); + /// let full = buf.copy_to_bytes(9); + /// assert_eq!(full, b"elloworld"[..]); /// ``` pub fn first_mut(&mut self) -> &mut T { &mut self.a @@ -94,12 +80,12 @@ /// # Examples /// /// ``` - /// use bytes::{Bytes, Buf, IntoBuf}; + /// use bytes::Buf; /// - /// let buf = Bytes::from(&b"hello"[..]).into_buf() - /// .chain(Bytes::from(&b"world"[..])); + /// let buf = (&b"hello"[..]) + /// .chain(&b"world"[..]); /// - /// assert_eq!(buf.last_ref().get_ref()[..], b"world"[..]); + /// assert_eq!(buf.last_ref()[..], b"world"[..]); /// ``` pub fn last_ref(&self) -> &U { &self.b @@ -110,15 +96,15 @@ /// # Examples /// /// ``` - /// use bytes::{Bytes, Buf, IntoBuf}; + /// use bytes::Buf; /// - /// let mut buf = Bytes::from(&b"hello "[..]).into_buf() - /// .chain(Bytes::from(&b"world"[..])); + /// let mut buf = (&b"hello "[..]) + /// .chain(&b"world"[..]); /// - /// buf.last_mut().set_position(1); + /// buf.last_mut().advance(1); /// - /// let full: Bytes = buf.collect(); - /// assert_eq!(full[..], b"hello orld"[..]); + /// let full = buf.copy_to_bytes(10); + /// assert_eq!(full, b"hello orld"[..]); /// ``` pub fn last_mut(&mut self) -> &mut U { &mut self.b @@ -129,14 +115,14 @@ /// # Examples /// /// ``` - /// use bytes::{Bytes, Buf, IntoBuf}; + /// use bytes::Buf; /// - /// let buf = Bytes::from(&b"hello"[..]).into_buf() - /// .chain(Bytes::from(&b"world"[..])); + /// let chain = (&b"hello"[..]) + /// .chain(&b"world"[..]); /// - /// let (first, last) = buf.into_inner(); - /// assert_eq!(first.get_ref()[..], b"hello"[..]); - /// assert_eq!(last.get_ref()[..], b"world"[..]); + /// let (first, last) = chain.into_inner(); + /// assert_eq!(first[..], b"hello"[..]); + /// assert_eq!(last[..], b"world"[..]); /// ``` pub fn into_inner(self) -> (T, U) { (self.a, self.b) @@ -144,18 +130,19 @@ } impl Buf for Chain - where T: Buf, - U: Buf, +where + T: Buf, + U: Buf, { fn remaining(&self) -> usize { - self.a.remaining() + self.b.remaining() + self.a.remaining().checked_add(self.b.remaining()).unwrap() } - fn bytes(&self) -> &[u8] { + fn chunk(&self) -> &[u8] { if self.a.has_remaining() { - self.a.bytes() + self.a.chunk() } else { - self.b.bytes() + self.b.chunk() } } @@ -177,26 +164,49 @@ self.b.advance(cnt); } - fn bytes_vec<'a>(&'a self, dst: &mut [&'a IoVec]) -> usize { - let mut n = self.a.bytes_vec(dst); - n += self.b.bytes_vec(&mut dst[n..]); + #[cfg(feature = "std")] + fn chunks_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize { + let mut n = self.a.chunks_vectored(dst); + n += self.b.chunks_vectored(&mut dst[n..]); n } + + fn copy_to_bytes(&mut self, len: usize) -> Bytes { + let a_rem = self.a.remaining(); + if a_rem >= len { + self.a.copy_to_bytes(len) + } else if a_rem == 0 { + self.b.copy_to_bytes(len) + } else { + assert!( + len - a_rem <= self.b.remaining(), + "`len` greater than remaining" + ); + let mut ret = crate::BytesMut::with_capacity(len); + ret.put(&mut self.a); + ret.put((&mut self.b).take(len - a_rem)); + ret.freeze() + } + } } -impl BufMut for Chain - where T: BufMut, - U: BufMut, +unsafe impl BufMut for Chain +where + T: BufMut, + U: BufMut, { fn remaining_mut(&self) -> usize { - self.a.remaining_mut() + self.b.remaining_mut() + self.a + .remaining_mut() + .checked_add(self.b.remaining_mut()) + .unwrap() } - unsafe fn bytes_mut(&mut self) -> &mut [u8] { + fn chunk_mut(&mut self) -> &mut UninitSlice { if self.a.has_remaining_mut() { - self.a.bytes_mut() + self.a.chunk_mut() } else { - self.b.bytes_mut() + self.b.chunk_mut() } } @@ -217,10 +227,17 @@ self.b.advance_mut(cnt); } +} - unsafe fn bytes_vec_mut<'a>(&'a mut self, dst: &mut [&'a mut IoVec]) -> usize { - let mut n = self.a.bytes_vec_mut(dst); - n += self.b.bytes_vec_mut(&mut dst[n..]); - n +impl IntoIterator for Chain +where + T: Buf, + U: Buf, +{ + type Item = u8; + type IntoIter = IntoIter>; + + fn into_iter(self) -> Self::IntoIter { + IntoIter::new(self) } } diff -Nru rust-bytes-0.4.12/src/buf/from_buf.rs rust-bytes-1.1.0/src/buf/from_buf.rs --- rust-bytes-0.4.12/src/buf/from_buf.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/src/buf/from_buf.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,117 +0,0 @@ -use {Buf, BufMut, IntoBuf, Bytes, BytesMut}; - -/// Conversion from a [`Buf`] -/// -/// Implementing `FromBuf` for a type defines how it is created from a buffer. -/// This is common for types which represent byte storage of some kind. -/// -/// [`FromBuf::from_buf`] is rarely called explicitly, and it is instead used -/// through [`Buf::collect`]. See [`Buf::collect`] documentation for more examples. -/// -/// See also [`IntoBuf`]. -/// -/// # Examples -/// -/// Basic usage: -/// -/// ``` -/// use bytes::{Bytes, IntoBuf}; -/// use bytes::buf::FromBuf; -/// -/// let buf = Bytes::from(&b"hello world"[..]).into_buf(); -/// let vec = Vec::from_buf(buf); -/// -/// assert_eq!(vec, &b"hello world"[..]); -/// ``` -/// -/// Using [`Buf::collect`] to implicitly use `FromBuf`: -/// -/// ``` -/// use bytes::{Buf, Bytes, IntoBuf}; -/// -/// let buf = Bytes::from(&b"hello world"[..]).into_buf(); -/// let vec: Vec = buf.collect(); -/// -/// assert_eq!(vec, &b"hello world"[..]); -/// ``` -/// -/// Implementing `FromBuf` for your type: -/// -/// ``` -/// use bytes::{BufMut, Bytes}; -/// use bytes::buf::{IntoBuf, FromBuf}; -/// -/// // A sample buffer, that's just a wrapper over Vec -/// struct MyBuffer(Vec); -/// -/// impl FromBuf for MyBuffer { -/// fn from_buf(buf: B) -> Self where B: IntoBuf { -/// let mut v = Vec::new(); -/// v.put(buf.into_buf()); -/// MyBuffer(v) -/// } -/// } -/// -/// // Now we can make a new buf -/// let buf = Bytes::from(&b"hello world"[..]); -/// -/// // And make a MyBuffer out of it -/// let my_buf = MyBuffer::from_buf(buf); -/// -/// assert_eq!(my_buf.0, &b"hello world"[..]); -/// ``` -/// -/// [`Buf`]: trait.Buf.html -/// [`FromBuf::from_buf`]: #method.from_buf -/// [`Buf::collect`]: trait.Buf.html#method.collect -/// [`IntoBuf`]: trait.IntoBuf.html -pub trait FromBuf { - /// Creates a value from a buffer. - /// - /// See the [type-level documentation](#) for more details. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// use bytes::{Bytes, IntoBuf}; - /// use bytes::buf::FromBuf; - /// - /// let buf = Bytes::from(&b"hello world"[..]).into_buf(); - /// let vec = Vec::from_buf(buf); - /// - /// assert_eq!(vec, &b"hello world"[..]); - /// ``` - fn from_buf(buf: T) -> Self where T: IntoBuf; -} - -impl FromBuf for Vec { - fn from_buf(buf: T) -> Self - where T: IntoBuf - { - let buf = buf.into_buf(); - let mut ret = Vec::with_capacity(buf.remaining()); - ret.put(buf); - ret - } -} - -impl FromBuf for Bytes { - fn from_buf(buf: T) -> Self - where T: IntoBuf - { - BytesMut::from_buf(buf).freeze() - } -} - -impl FromBuf for BytesMut { - fn from_buf(buf: T) -> Self - where T: IntoBuf - { - let buf = buf.into_buf(); - let mut ret = BytesMut::with_capacity(buf.remaining()); - ret.put(buf); - ret - } -} diff -Nru rust-bytes-0.4.12/src/buf/into_buf.rs rust-bytes-1.1.0/src/buf/into_buf.rs --- rust-bytes-0.4.12/src/buf/into_buf.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/src/buf/into_buf.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,146 +0,0 @@ -use super::{Buf}; - -use std::io; - -/// Conversion into a `Buf` -/// -/// An `IntoBuf` implementation defines how to convert a value into a `Buf`. -/// This is common for types that represent byte storage of some kind. `IntoBuf` -/// may be implemented directly for types or on references for those types. -/// -/// # Examples -/// -/// ``` -/// use bytes::{Buf, IntoBuf, BigEndian}; -/// -/// let bytes = b"\x00\x01hello world"; -/// let mut buf = bytes.into_buf(); -/// -/// assert_eq!(1, buf.get_u16::()); -/// -/// let mut rest = [0; 11]; -/// buf.copy_to_slice(&mut rest); -/// -/// assert_eq!(b"hello world", &rest); -/// ``` -pub trait IntoBuf { - /// The `Buf` type that `self` is being converted into - type Buf: Buf; - - /// Creates a `Buf` from a value. - /// - /// # Examples - /// - /// ``` - /// use bytes::{Buf, IntoBuf, BigEndian}; - /// - /// let bytes = b"\x00\x01hello world"; - /// let mut buf = bytes.into_buf(); - /// - /// assert_eq!(1, buf.get_u16::()); - /// - /// let mut rest = [0; 11]; - /// buf.copy_to_slice(&mut rest); - /// - /// assert_eq!(b"hello world", &rest); - /// ``` - fn into_buf(self) -> Self::Buf; -} - -impl IntoBuf for T { - type Buf = Self; - - fn into_buf(self) -> Self { - self - } -} - -impl<'a> IntoBuf for &'a [u8] { - type Buf = io::Cursor<&'a [u8]>; - - fn into_buf(self) -> Self::Buf { - io::Cursor::new(self) - } -} - -impl<'a> IntoBuf for &'a mut [u8] { - type Buf = io::Cursor<&'a mut [u8]>; - - fn into_buf(self) -> Self::Buf { - io::Cursor::new(self) - } -} - -impl<'a> IntoBuf for &'a str { - type Buf = io::Cursor<&'a [u8]>; - - fn into_buf(self) -> Self::Buf { - self.as_bytes().into_buf() - } -} - -impl IntoBuf for Vec { - type Buf = io::Cursor>; - - fn into_buf(self) -> Self::Buf { - io::Cursor::new(self) - } -} - -impl<'a> IntoBuf for &'a Vec { - type Buf = io::Cursor<&'a [u8]>; - - fn into_buf(self) -> Self::Buf { - io::Cursor::new(&self[..]) - } -} - -// Kind of annoying... but this impl is required to allow passing `&'static -// [u8]` where for<'a> &'a T: IntoBuf is required. -impl<'a> IntoBuf for &'a &'static [u8] { - type Buf = io::Cursor<&'static [u8]>; - - fn into_buf(self) -> Self::Buf { - io::Cursor::new(self) - } -} - -impl<'a> IntoBuf for &'a &'static str { - type Buf = io::Cursor<&'static [u8]>; - - fn into_buf(self) -> Self::Buf { - self.as_bytes().into_buf() - } -} - -impl IntoBuf for String { - type Buf = io::Cursor>; - - fn into_buf(self) -> Self::Buf { - self.into_bytes().into_buf() - } -} - -impl<'a> IntoBuf for &'a String { - type Buf = io::Cursor<&'a [u8]>; - - fn into_buf(self) -> Self::Buf { - self.as_bytes().into_buf() - } -} - -impl IntoBuf for u8 { - type Buf = Option<[u8; 1]>; - - fn into_buf(self) -> Self::Buf { - Some([self]) - } -} - -impl IntoBuf for i8 { - type Buf = Option<[u8; 1]>; - - fn into_buf(self) -> Self::Buf { - Some([self as u8; 1]) - } -} diff -Nru rust-bytes-0.4.12/src/buf/iter.rs rust-bytes-1.1.0/src/buf/iter.rs --- rust-bytes-0.4.12/src/buf/iter.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/src/buf/iter.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,4 +1,4 @@ -use Buf; +use crate::Buf; /// Iterator over the bytes contained by the buffer. /// @@ -9,10 +9,10 @@ /// Basic usage: /// /// ``` -/// use bytes::{Buf, IntoBuf, Bytes}; +/// use bytes::Bytes; /// -/// let buf = Bytes::from(&b"abc"[..]).into_buf(); -/// let mut iter = buf.iter(); +/// let buf = Bytes::from(&b"abc"[..]); +/// let mut iter = buf.into_iter(); /// /// assert_eq!(iter.next(), Some(b'a')); /// assert_eq!(iter.next(), Some(b'b')); @@ -23,20 +23,39 @@ /// [`iter`]: trait.Buf.html#method.iter /// [`Buf`]: trait.Buf.html #[derive(Debug)] -pub struct Iter { +pub struct IntoIter { inner: T, } -impl Iter { - /// Consumes this `Iter`, returning the underlying value. +impl IntoIter { + /// Creates an iterator over the bytes contained by the buffer. + /// + /// # Examples + /// + /// ``` + /// use bytes::Bytes; + /// + /// let buf = Bytes::from_static(b"abc"); + /// let mut iter = buf.into_iter(); + /// + /// assert_eq!(iter.next(), Some(b'a')); + /// assert_eq!(iter.next(), Some(b'b')); + /// assert_eq!(iter.next(), Some(b'c')); + /// assert_eq!(iter.next(), None); + /// ``` + pub(crate) fn new(inner: T) -> IntoIter { + IntoIter { inner } + } + + /// Consumes this `IntoIter`, returning the underlying value. /// /// # Examples /// /// ```rust - /// use bytes::{Buf, IntoBuf, Bytes}; + /// use bytes::{Buf, Bytes}; /// - /// let buf = Bytes::from(&b"abc"[..]).into_buf(); - /// let mut iter = buf.iter(); + /// let buf = Bytes::from(&b"abc"[..]); + /// let mut iter = buf.into_iter(); /// /// assert_eq!(iter.next(), Some(b'a')); /// @@ -54,10 +73,10 @@ /// # Examples /// /// ```rust - /// use bytes::{Buf, IntoBuf, Bytes}; + /// use bytes::{Buf, Bytes}; /// - /// let buf = Bytes::from(&b"abc"[..]).into_buf(); - /// let mut iter = buf.iter(); + /// let buf = Bytes::from(&b"abc"[..]); + /// let mut iter = buf.into_iter(); /// /// assert_eq!(iter.next(), Some(b'a')); /// @@ -74,27 +93,23 @@ /// # Examples /// /// ```rust - /// use bytes::{Buf, IntoBuf, BytesMut}; + /// use bytes::{Buf, BytesMut}; /// - /// let buf = BytesMut::from(&b"abc"[..]).into_buf(); - /// let mut iter = buf.iter(); + /// let buf = BytesMut::from(&b"abc"[..]); + /// let mut iter = buf.into_iter(); /// /// assert_eq!(iter.next(), Some(b'a')); /// - /// iter.get_mut().set_position(0); + /// iter.get_mut().advance(1); /// - /// assert_eq!(iter.next(), Some(b'a')); + /// assert_eq!(iter.next(), Some(b'c')); /// ``` pub fn get_mut(&mut self) -> &mut T { &mut self.inner } } -pub fn new(inner: T) -> Iter { - Iter { inner: inner } -} - -impl Iterator for Iter { +impl Iterator for IntoIter { type Item = u8; fn next(&mut self) -> Option { @@ -102,8 +117,9 @@ return None; } - let b = self.inner.bytes()[0]; + let b = self.inner.chunk()[0]; self.inner.advance(1); + Some(b) } @@ -113,4 +129,4 @@ } } -impl ExactSizeIterator for Iter { } +impl ExactSizeIterator for IntoIter {} diff -Nru rust-bytes-0.4.12/src/buf/limit.rs rust-bytes-1.1.0/src/buf/limit.rs --- rust-bytes-0.4.12/src/buf/limit.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/src/buf/limit.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,75 @@ +use crate::buf::UninitSlice; +use crate::BufMut; + +use core::cmp; + +/// A `BufMut` adapter which limits the amount of bytes that can be written +/// to an underlying buffer. +#[derive(Debug)] +pub struct Limit { + inner: T, + limit: usize, +} + +pub(super) fn new(inner: T, limit: usize) -> Limit { + Limit { inner, limit } +} + +impl Limit { + /// Consumes this `Limit`, returning the underlying value. + pub fn into_inner(self) -> T { + self.inner + } + + /// Gets a reference to the underlying `BufMut`. + /// + /// It is inadvisable to directly write to the underlying `BufMut`. + pub fn get_ref(&self) -> &T { + &self.inner + } + + /// Gets a mutable reference to the underlying `BufMut`. + /// + /// It is inadvisable to directly write to the underlying `BufMut`. + pub fn get_mut(&mut self) -> &mut T { + &mut self.inner + } + + /// Returns the maximum number of bytes that can be written + /// + /// # Note + /// + /// If the inner `BufMut` has fewer bytes than indicated by this method then + /// that is the actual number of available bytes. + pub fn limit(&self) -> usize { + self.limit + } + + /// Sets the maximum number of bytes that can be written. + /// + /// # Note + /// + /// If the inner `BufMut` has fewer bytes than `lim` then that is the actual + /// number of available bytes. + pub fn set_limit(&mut self, lim: usize) { + self.limit = lim + } +} + +unsafe impl BufMut for Limit { + fn remaining_mut(&self) -> usize { + cmp::min(self.inner.remaining_mut(), self.limit) + } + + fn chunk_mut(&mut self) -> &mut UninitSlice { + let bytes = self.inner.chunk_mut(); + let end = cmp::min(bytes.len(), self.limit); + &mut bytes[..end] + } + + unsafe fn advance_mut(&mut self, cnt: usize) { + assert!(cnt <= self.limit); + self.inner.advance_mut(cnt); + self.limit -= cnt; + } +} diff -Nru rust-bytes-0.4.12/src/buf/mod.rs rust-bytes-1.1.0/src/buf/mod.rs --- rust-bytes-0.4.12/src/buf/mod.rs 2019-03-06 19:57:32.000000000 +0000 +++ rust-bytes-1.1.0/src/buf/mod.rs 1973-11-29 21:33:09.000000000 +0000 @@ -16,23 +16,26 @@ //! [`Buf`]: trait.Buf.html //! [`BufMut`]: trait.BufMut.html -mod buf; +mod buf_impl; mod buf_mut; -mod from_buf; mod chain; -mod into_buf; mod iter; +mod limit; +#[cfg(feature = "std")] mod reader; mod take; +mod uninit_slice; mod vec_deque; +#[cfg(feature = "std")] mod writer; -pub use self::buf::Buf; +pub use self::buf_impl::Buf; pub use self::buf_mut::BufMut; -pub use self::from_buf::FromBuf; pub use self::chain::Chain; -pub use self::into_buf::IntoBuf; -pub use self::iter::Iter; -pub use self::reader::Reader; +pub use self::iter::IntoIter; +pub use self::limit::Limit; pub use self::take::Take; -pub use self::writer::Writer; +pub use self::uninit_slice::UninitSlice; + +#[cfg(feature = "std")] +pub use self::{reader::Reader, writer::Writer}; diff -Nru rust-bytes-0.4.12/src/buf/reader.rs rust-bytes-1.1.0/src/buf/reader.rs --- rust-bytes-0.4.12/src/buf/reader.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/src/buf/reader.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,4 +1,4 @@ -use {Buf}; +use crate::Buf; use std::{cmp, io}; @@ -13,7 +13,7 @@ } pub fn new(buf: B) -> Reader { - Reader { buf: buf } + Reader { buf } } impl Reader { @@ -25,11 +25,10 @@ /// /// ```rust /// use bytes::Buf; - /// use std::io::{self, Cursor}; /// - /// let mut buf = Cursor::new(b"hello world").reader(); + /// let buf = b"hello world".reader(); /// - /// assert_eq!(0, buf.get_ref().position()); + /// assert_eq!(b"hello world", buf.get_ref()); /// ``` pub fn get_ref(&self) -> &B { &self.buf @@ -38,21 +37,6 @@ /// Gets a mutable reference to the underlying `Buf`. /// /// It is inadvisable to directly read from the underlying `Buf`. - /// - /// # Examples - /// - /// ```rust - /// use bytes::Buf; - /// use std::io::{self, Cursor}; - /// - /// let mut buf = Cursor::new(b"hello world").reader(); - /// let mut dst = vec![]; - /// - /// buf.get_mut().set_position(2); - /// io::copy(&mut buf, &mut dst).unwrap(); - /// - /// assert_eq!(*dst, b"llo world"[..]); - /// ``` pub fn get_mut(&mut self) -> &mut B { &mut self.buf } @@ -63,9 +47,9 @@ /// /// ```rust /// use bytes::Buf; - /// use std::io::{self, Cursor}; + /// use std::io; /// - /// let mut buf = Cursor::new(b"hello world").reader(); + /// let mut buf = b"hello world".reader(); /// let mut dst = vec![]; /// /// io::copy(&mut buf, &mut dst).unwrap(); @@ -89,7 +73,7 @@ impl io::BufRead for Reader { fn fill_buf(&mut self) -> io::Result<&[u8]> { - Ok(self.buf.bytes()) + Ok(self.buf.chunk()) } fn consume(&mut self, amt: usize) { self.buf.advance(amt) diff -Nru rust-bytes-0.4.12/src/buf/take.rs rust-bytes-1.1.0/src/buf/take.rs --- rust-bytes-0.4.12/src/buf/take.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/src/buf/take.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,6 +1,6 @@ -use {Buf}; +use crate::{Buf, Bytes}; -use std::cmp; +use core::cmp; /// A `Buf` adapter which limits the bytes read from an underlying buffer. /// @@ -13,10 +13,7 @@ } pub fn new(inner: T, limit: usize) -> Take { - Take { - inner: inner, - limit: limit, - } + Take { inner, limit } } impl Take { @@ -26,9 +23,8 @@ /// /// ```rust /// use bytes::{Buf, BufMut}; - /// use std::io::Cursor; /// - /// let mut buf = Cursor::new(b"hello world").take(2); + /// let mut buf = b"hello world".take(2); /// let mut dst = vec![]; /// /// dst.put(&mut buf); @@ -51,12 +47,11 @@ /// # Examples /// /// ```rust - /// use bytes::{Buf, BufMut}; - /// use std::io::Cursor; + /// use bytes::Buf; /// - /// let mut buf = Cursor::new(b"hello world").take(2); + /// let buf = b"hello world".take(2); /// - /// assert_eq!(0, buf.get_ref().position()); + /// assert_eq!(11, buf.get_ref().remaining()); /// ``` pub fn get_ref(&self) -> &T { &self.inner @@ -70,12 +65,11 @@ /// /// ```rust /// use bytes::{Buf, BufMut}; - /// use std::io::Cursor; /// - /// let mut buf = Cursor::new(b"hello world").take(2); + /// let mut buf = b"hello world".take(2); /// let mut dst = vec![]; /// - /// buf.get_mut().set_position(2); + /// buf.get_mut().advance(2); /// /// dst.put(&mut buf); /// assert_eq!(*dst, b"ll"[..]); @@ -95,9 +89,8 @@ /// /// ```rust /// use bytes::Buf; - /// use std::io::Cursor; /// - /// let mut buf = Cursor::new(b"hello world").take(2); + /// let mut buf = b"hello world".take(2); /// /// assert_eq!(2, buf.limit()); /// assert_eq!(b'h', buf.get_u8()); @@ -118,9 +111,8 @@ /// /// ```rust /// use bytes::{Buf, BufMut}; - /// use std::io::Cursor; /// - /// let mut buf = Cursor::new(b"hello world").take(2); + /// let mut buf = b"hello world".take(2); /// let mut dst = vec![]; /// /// dst.put(&mut buf); @@ -142,8 +134,8 @@ cmp::min(self.inner.remaining(), self.limit) } - fn bytes(&self) -> &[u8] { - let bytes = self.inner.bytes(); + fn chunk(&self) -> &[u8] { + let bytes = self.inner.chunk(); &bytes[..cmp::min(bytes.len(), self.limit)] } @@ -152,4 +144,12 @@ self.inner.advance(cnt); self.limit -= cnt; } + + fn copy_to_bytes(&mut self, len: usize) -> Bytes { + assert!(len <= self.remaining(), "`len` greater than remaining"); + + let r = self.inner.copy_to_bytes(len); + self.limit -= len; + r + } } diff -Nru rust-bytes-0.4.12/src/buf/uninit_slice.rs rust-bytes-1.1.0/src/buf/uninit_slice.rs --- rust-bytes-0.4.12/src/buf/uninit_slice.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/src/buf/uninit_slice.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,183 @@ +use core::fmt; +use core::mem::MaybeUninit; +use core::ops::{ + Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, +}; + +/// Uninitialized byte slice. +/// +/// Returned by `BufMut::chunk_mut()`, the referenced byte slice may be +/// uninitialized. The wrapper provides safe access without introducing +/// undefined behavior. +/// +/// The safety invariants of this wrapper are: +/// +/// 1. Reading from an `UninitSlice` is undefined behavior. +/// 2. Writing uninitialized bytes to an `UninitSlice` is undefined behavior. +/// +/// The difference between `&mut UninitSlice` and `&mut [MaybeUninit]` is +/// that it is possible in safe code to write uninitialized bytes to an +/// `&mut [MaybeUninit]`, which this type prohibits. +#[repr(transparent)] +pub struct UninitSlice([MaybeUninit]); + +impl UninitSlice { + /// Create a `&mut UninitSlice` from a pointer and a length. + /// + /// # Safety + /// + /// The caller must ensure that `ptr` references a valid memory region owned + /// by the caller representing a byte slice for the duration of `'a`. + /// + /// # Examples + /// + /// ``` + /// use bytes::buf::UninitSlice; + /// + /// let bytes = b"hello world".to_vec(); + /// let ptr = bytes.as_ptr() as *mut _; + /// let len = bytes.len(); + /// + /// let slice = unsafe { UninitSlice::from_raw_parts_mut(ptr, len) }; + /// ``` + #[inline] + pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice { + let maybe_init: &mut [MaybeUninit] = + core::slice::from_raw_parts_mut(ptr as *mut _, len); + &mut *(maybe_init as *mut [MaybeUninit] as *mut UninitSlice) + } + + /// Write a single byte at the specified offset. + /// + /// # Panics + /// + /// The function panics if `index` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// use bytes::buf::UninitSlice; + /// + /// let mut data = [b'f', b'o', b'o']; + /// let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) }; + /// + /// slice.write_byte(0, b'b'); + /// + /// assert_eq!(b"boo", &data[..]); + /// ``` + #[inline] + pub fn write_byte(&mut self, index: usize, byte: u8) { + assert!(index < self.len()); + + unsafe { self[index..].as_mut_ptr().write(byte) } + } + + /// Copies bytes from `src` into `self`. + /// + /// The length of `src` must be the same as `self`. + /// + /// # Panics + /// + /// The function panics if `src` has a different length than `self`. + /// + /// # Examples + /// + /// ``` + /// use bytes::buf::UninitSlice; + /// + /// let mut data = [b'f', b'o', b'o']; + /// let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) }; + /// + /// slice.copy_from_slice(b"bar"); + /// + /// assert_eq!(b"bar", &data[..]); + /// ``` + #[inline] + pub fn copy_from_slice(&mut self, src: &[u8]) { + use core::ptr; + + assert_eq!(self.len(), src.len()); + + unsafe { + ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len()); + } + } + + /// Return a raw pointer to the slice's buffer. + /// + /// # Safety + /// + /// The caller **must not** read from the referenced memory and **must not** + /// write **uninitialized** bytes to the slice either. + /// + /// # Examples + /// + /// ``` + /// use bytes::BufMut; + /// + /// let mut data = [0, 1, 2]; + /// let mut slice = &mut data[..]; + /// let ptr = BufMut::chunk_mut(&mut slice).as_mut_ptr(); + /// ``` + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut u8 { + self.0.as_mut_ptr() as *mut _ + } + + /// Returns the number of bytes in the slice. + /// + /// # Examples + /// + /// ``` + /// use bytes::BufMut; + /// + /// let mut data = [0, 1, 2]; + /// let mut slice = &mut data[..]; + /// let len = BufMut::chunk_mut(&mut slice).len(); + /// + /// assert_eq!(len, 3); + /// ``` + #[inline] + pub fn len(&self) -> usize { + self.0.len() + } +} + +impl fmt::Debug for UninitSlice { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_struct("UninitSlice[...]").finish() + } +} + +macro_rules! impl_index { + ($($t:ty),*) => { + $( + impl Index<$t> for UninitSlice { + type Output = UninitSlice; + + #[inline] + fn index(&self, index: $t) -> &UninitSlice { + let maybe_uninit: &[MaybeUninit] = &self.0[index]; + unsafe { &*(maybe_uninit as *const [MaybeUninit] as *const UninitSlice) } + } + } + + impl IndexMut<$t> for UninitSlice { + #[inline] + fn index_mut(&mut self, index: $t) -> &mut UninitSlice { + let maybe_uninit: &mut [MaybeUninit] = &mut self.0[index]; + unsafe { &mut *(maybe_uninit as *mut [MaybeUninit] as *mut UninitSlice) } + } + } + )* + }; +} + +impl_index!( + Range, + RangeFrom, + RangeFull, + RangeInclusive, + RangeTo, + RangeToInclusive +); diff -Nru rust-bytes-0.4.12/src/buf/vec_deque.rs rust-bytes-1.1.0/src/buf/vec_deque.rs --- rust-bytes-0.4.12/src/buf/vec_deque.rs 2019-03-06 19:57:32.000000000 +0000 +++ rust-bytes-1.1.0/src/buf/vec_deque.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,4 +1,4 @@ -use std::collections::VecDeque; +use alloc::collections::VecDeque; use super::Buf; @@ -7,7 +7,7 @@ self.len() } - fn bytes(&self) -> &[u8] { + fn chunk(&self) -> &[u8] { let (s1, s2) = self.as_slices(); if s1.is_empty() { s2 @@ -20,20 +20,3 @@ self.drain(..cnt); } } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn hello_world() { - let mut buffer: VecDeque = 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::>()[..]); - } -} diff -Nru rust-bytes-0.4.12/src/buf/writer.rs rust-bytes-1.1.0/src/buf/writer.rs --- rust-bytes-0.4.12/src/buf/writer.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/src/buf/writer.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,4 +1,4 @@ -use BufMut; +use crate::BufMut; use std::{cmp, io}; @@ -13,7 +13,7 @@ } pub fn new(buf: B) -> Writer { - Writer { buf: buf } + Writer { buf } } impl Writer { @@ -26,7 +26,7 @@ /// ```rust /// use bytes::BufMut; /// - /// let mut buf = Vec::with_capacity(1024).writer(); + /// let buf = Vec::with_capacity(1024).writer(); /// /// assert_eq!(1024, buf.get_ref().capacity()); /// ``` @@ -59,10 +59,10 @@ /// /// ```rust /// use bytes::BufMut; - /// use std::io::{self, Cursor}; + /// use std::io; /// /// let mut buf = vec![].writer(); - /// let mut src = Cursor::new(b"hello world"); + /// let mut src = &b"hello world"[..]; /// /// io::copy(&mut src, &mut buf).unwrap(); /// diff -Nru rust-bytes-0.4.12/src/bytes_mut.rs rust-bytes-1.1.0/src/bytes_mut.rs --- rust-bytes-0.4.12/src/bytes_mut.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/src/bytes_mut.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,1598 @@ +use core::iter::{FromIterator, Iterator}; +use core::mem::{self, ManuallyDrop}; +use core::ops::{Deref, DerefMut}; +use core::ptr::{self, NonNull}; +use core::{cmp, fmt, hash, isize, slice, usize}; + +use alloc::{ + borrow::{Borrow, BorrowMut}, + boxed::Box, + string::String, + vec::Vec, +}; + +use crate::buf::{IntoIter, UninitSlice}; +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. +/// +/// `BytesMut` can be thought of as containing a `buf: Arc>`, 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 +/// +/// `BytesMut`'s `BufMut` implementation will implicitly grow its buffer as +/// necessary. However, explicitly reserving the required space up-front before +/// a series of inserts will be more efficient. +/// +/// # Examples +/// +/// ``` +/// use bytes::{BytesMut, BufMut}; +/// +/// let mut buf = BytesMut::with_capacity(64); +/// +/// buf.put_u8(b'h'); +/// buf.put_u8(b'e'); +/// buf.put(&b"llo"[..]); +/// +/// assert_eq!(&buf[..], b"hello"); +/// +/// // Freeze the buffer so that it can be shared +/// let a = buf.freeze(); +/// +/// // This does not allocate, instead `b` points to the same memory. +/// let b = a.clone(); +/// +/// assert_eq!(&a[..], b"hello"); +/// assert_eq!(&b[..], b"hello"); +/// ``` +pub struct BytesMut { + ptr: NonNull, + len: usize, + cap: usize, + data: *mut Shared, +} + +// Thread-safe reference-counted container for the shared storage. This mostly +// the same as `core::sync::Arc` but without the weak counter. The ref counting +// fns are based on the ones found in `std`. +// +// The main reason to use `Shared` instead of `core::sync::Arc` is that it ends +// up making the overall code simpler and easier to reason about. This is due to +// some of the logic around setting `Inner::arc` and other ways the `arc` field +// is used. Using `Arc` ended up requiring a number of funky transmutes and +// other shenanigans to make it work. +struct Shared { + vec: Vec, + original_capacity_repr: usize, + ref_count: AtomicUsize, +} + +// Buffer storage strategy flags. +const KIND_ARC: usize = 0b0; +const KIND_VEC: usize = 0b1; +const KIND_MASK: usize = 0b1; + +// The max original capacity value. Any `Bytes` allocated with a greater initial +// capacity will default to this. +const MAX_ORIGINAL_CAPACITY_WIDTH: usize = 17; +// The original capacity algorithm will not take effect unless the originally +// allocated capacity was at least 1kb in size. +const MIN_ORIGINAL_CAPACITY_WIDTH: usize = 10; +// The original capacity is stored in powers of 2 starting at 1kb to a max of +// 64kb. Representing it as such requires only 3 bits of storage. +const ORIGINAL_CAPACITY_MASK: usize = 0b11100; +const ORIGINAL_CAPACITY_OFFSET: usize = 2; + +// When the storage is in the `Vec` representation, the pointer can be advanced +// at most this value. This is due to the amount of storage available to track +// the offset is usize - number of KIND bits and number of ORIGINAL_CAPACITY +// bits. +const VEC_POS_OFFSET: usize = 5; +const MAX_VEC_POS: usize = usize::MAX >> VEC_POS_OFFSET; +const NOT_VEC_POS_MASK: usize = 0b11111; + +#[cfg(target_pointer_width = "64")] +const PTR_WIDTH: usize = 64; +#[cfg(target_pointer_width = "32")] +const PTR_WIDTH: usize = 32; + +/* + * + * ===== BytesMut ===== + * + */ + +impl BytesMut { + /// Creates a new `BytesMut` with the specified capacity. + /// + /// The returned `BytesMut` will be able to hold at least `capacity` bytes + /// without reallocating. + /// + /// It is important to note that this function does not specify the length + /// of the returned `BytesMut`, but only the capacity. + /// + /// # Examples + /// + /// ``` + /// use bytes::{BytesMut, BufMut}; + /// + /// let mut bytes = BytesMut::with_capacity(64); + /// + /// // `bytes` contains no data, even though there is capacity + /// assert_eq!(bytes.len(), 0); + /// + /// bytes.put(&b"hello world"[..]); + /// + /// assert_eq!(&bytes[..], b"hello world"); + /// ``` + #[inline] + pub fn with_capacity(capacity: usize) -> BytesMut { + BytesMut::from_vec(Vec::with_capacity(capacity)) + } + + /// Creates a new `BytesMut` with default capacity. + /// + /// Resulting object has length 0 and unspecified capacity. + /// This function does not allocate. + /// + /// # Examples + /// + /// ``` + /// use bytes::{BytesMut, BufMut}; + /// + /// let mut bytes = BytesMut::new(); + /// + /// assert_eq!(0, bytes.len()); + /// + /// bytes.reserve(2); + /// bytes.put_slice(b"xy"); + /// + /// assert_eq!(&b"xy"[..], &bytes[..]); + /// ``` + #[inline] + pub fn new() -> BytesMut { + BytesMut::with_capacity(0) + } + + /// Returns the number of bytes contained in this `BytesMut`. + /// + /// # Examples + /// + /// ``` + /// use bytes::BytesMut; + /// + /// let b = BytesMut::from(&b"hello"[..]); + /// assert_eq!(b.len(), 5); + /// ``` + #[inline] + pub fn len(&self) -> usize { + self.len + } + + /// Returns true if the `BytesMut` has a length of 0. + /// + /// # Examples + /// + /// ``` + /// use bytes::BytesMut; + /// + /// let b = BytesMut::with_capacity(64); + /// assert!(b.is_empty()); + /// ``` + #[inline] + pub fn is_empty(&self) -> bool { + self.len == 0 + } + + /// Returns the number of bytes the `BytesMut` can hold without reallocating. + /// + /// # Examples + /// + /// ``` + /// use bytes::BytesMut; + /// + /// let b = BytesMut::with_capacity(64); + /// assert_eq!(b.capacity(), 64); + /// ``` + #[inline] + pub fn capacity(&self) -> usize { + self.cap + } + + /// Converts `self` into an immutable `Bytes`. + /// + /// The conversion is zero cost and is used to indicate that the slice + /// referenced by the handle will no longer be mutated. Once the conversion + /// is done, the handle can be cloned and shared across threads. + /// + /// # Examples + /// + /// ``` + /// use bytes::{BytesMut, BufMut}; + /// use std::thread; + /// + /// let mut b = BytesMut::with_capacity(64); + /// b.put(&b"hello world"[..]); + /// let b1 = b.freeze(); + /// let b2 = b1.clone(); + /// + /// let th = thread::spawn(move || { + /// assert_eq!(&b1[..], b"hello world"); + /// }); + /// + /// assert_eq!(&b2[..], b"hello world"); + /// th.join().unwrap(); + /// ``` + #[inline] + pub fn freeze(mut self) -> Bytes { + if self.kind() == KIND_VEC { + // Just re-use `Bytes` internal Vec vtable + unsafe { + let (off, _) = self.get_vec_pos(); + let vec = rebuild_vec(self.ptr.as_ptr(), self.len, self.cap, off); + mem::forget(self); + let mut b: Bytes = vec.into(); + b.advance(off); + b + } + } else { + debug_assert_eq!(self.kind(), KIND_ARC); + + let ptr = self.ptr.as_ptr(); + let len = self.len; + let data = AtomicPtr::new(self.data as _); + mem::forget(self); + unsafe { Bytes::with_vtable(ptr, len, data, &SHARED_VTABLE) } + } + } + + /// Splits the bytes into two at the given index. + /// + /// Afterwards `self` contains elements `[0, at)`, and the returned + /// `BytesMut` contains elements `[at, capacity)`. + /// + /// This is an `O(1)` operation that just increases the reference count + /// and sets a few indices. + /// + /// # Examples + /// + /// ``` + /// use bytes::BytesMut; + /// + /// let mut a = BytesMut::from(&b"hello world"[..]); + /// let mut b = a.split_off(5); + /// + /// a[0] = b'j'; + /// b[0] = b'!'; + /// + /// assert_eq!(&a[..], b"jello"); + /// assert_eq!(&b[..], b"!world"); + /// ``` + /// + /// # Panics + /// + /// 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(), + "split_off out of bounds: {:?} <= {:?}", + at, + self.capacity(), + ); + unsafe { + let mut other = self.shallow_clone(); + other.set_start(at); + self.set_end(at); + other + } + } + + /// Removes the bytes from the current view, returning them in a new + /// `BytesMut` handle. + /// + /// Afterwards, `self` will be empty, but will retain any additional + /// capacity that it had before the operation. This is identical to + /// `self.split_to(self.len())`. + /// + /// This is an `O(1)` operation that just increases the reference count and + /// sets a few indices. + /// + /// # Examples + /// + /// ``` + /// use bytes::{BytesMut, BufMut}; + /// + /// let mut buf = BytesMut::with_capacity(1024); + /// buf.put(&b"hello world"[..]); + /// + /// let other = buf.split(); + /// + /// assert!(buf.is_empty()); + /// assert_eq!(1013, buf.capacity()); + /// + /// assert_eq!(other, b"hello world"[..]); + /// ``` + #[must_use = "consider BytesMut::advance(len()) if you don't need the other half"] + pub fn split(&mut self) -> BytesMut { + let len = self.len(); + self.split_to(len) + } + + /// Splits the buffer into two at the given index. + /// + /// Afterwards `self` contains elements `[at, len)`, and the returned `BytesMut` + /// contains elements `[0, at)`. + /// + /// This is an `O(1)` operation that just increases the reference count and + /// sets a few indices. + /// + /// # Examples + /// + /// ``` + /// use bytes::BytesMut; + /// + /// let mut a = BytesMut::from(&b"hello world"[..]); + /// let mut b = a.split_to(5); + /// + /// a[0] = b'!'; + /// b[0] = b'j'; + /// + /// assert_eq!(&a[..], b"!world"); + /// assert_eq!(&b[..], b"jello"); + /// ``` + /// + /// # Panics + /// + /// 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(), + "split_to out of bounds: {:?} <= {:?}", + at, + self.len(), + ); + + unsafe { + let mut other = self.shallow_clone(); + other.set_end(at); + self.set_start(at); + other + } + } + + /// Shortens the buffer, keeping the first `len` bytes and dropping the + /// rest. + /// + /// If `len` is greater than the buffer's current length, this has no + /// effect. + /// + /// Existing underlying capacity is preserved. + /// + /// The [`split_off`] method can emulate `truncate`, but this causes the + /// excess bytes to be returned instead of dropped. + /// + /// # Examples + /// + /// ``` + /// use bytes::BytesMut; + /// + /// let mut buf = BytesMut::from(&b"hello world"[..]); + /// buf.truncate(5); + /// assert_eq!(buf, b"hello"[..]); + /// ``` + /// + /// [`split_off`]: #method.split_off + pub fn truncate(&mut self, len: usize) { + if len <= self.len() { + unsafe { + self.set_len(len); + } + } + } + + /// Clears the buffer, removing all data. Existing capacity is preserved. + /// + /// # Examples + /// + /// ``` + /// use bytes::BytesMut; + /// + /// let mut buf = BytesMut::from(&b"hello world"[..]); + /// buf.clear(); + /// assert!(buf.is_empty()); + /// ``` + pub fn clear(&mut self) { + self.truncate(0); + } + + /// Resizes the buffer so that `len` is equal to `new_len`. + /// + /// If `new_len` is greater than `len`, the buffer is extended by the + /// difference with each additional byte set to `value`. If `new_len` is + /// less than `len`, the buffer is simply truncated. + /// + /// # Examples + /// + /// ``` + /// use bytes::BytesMut; + /// + /// let mut buf = BytesMut::new(); + /// + /// buf.resize(3, 0x1); + /// assert_eq!(&buf[..], &[0x1, 0x1, 0x1]); + /// + /// buf.resize(2, 0x2); + /// assert_eq!(&buf[..], &[0x1, 0x1]); + /// + /// buf.resize(4, 0x3); + /// assert_eq!(&buf[..], &[0x1, 0x1, 0x3, 0x3]); + /// ``` + pub fn resize(&mut self, new_len: usize, value: u8) { + let len = self.len(); + if new_len > len { + let additional = new_len - len; + self.reserve(additional); + unsafe { + let dst = self.chunk_mut().as_mut_ptr(); + ptr::write_bytes(dst, value, additional); + self.set_len(new_len); + } + } else { + self.truncate(new_len); + } + } + + /// Sets the length of the buffer. + /// + /// This will explicitly set the size of the buffer without actually + /// modifying the data, so it is up to the caller to ensure that the data + /// has been initialized. + /// + /// # Examples + /// + /// ``` + /// use bytes::BytesMut; + /// + /// let mut b = BytesMut::from(&b"hello world"[..]); + /// + /// unsafe { + /// b.set_len(5); + /// } + /// + /// assert_eq!(&b[..], b"hello"); + /// + /// unsafe { + /// b.set_len(11); + /// } + /// + /// assert_eq!(&b[..], b"hello world"); + /// ``` + #[inline] + pub unsafe fn set_len(&mut self, len: usize) { + debug_assert!(len <= self.cap, "set_len out of bounds"); + self.len = len; + } + + /// Reserves capacity for at least `additional` more bytes to be inserted + /// into the given `BytesMut`. + /// + /// More than `additional` bytes may be reserved in order to avoid frequent + /// reallocations. A call to `reserve` may result in an allocation. + /// + /// Before allocating new buffer space, the function will attempt to reclaim + /// space in the existing buffer. If the current handle references a small + /// view in the original buffer and all other handles have been dropped, + /// and the requested capacity is less than or equal to the existing + /// buffer's capacity, then the current view will be copied to the front of + /// the buffer and the handle will take ownership of the full buffer. + /// + /// # Examples + /// + /// In the following example, a new buffer is allocated. + /// + /// ``` + /// use bytes::BytesMut; + /// + /// let mut buf = BytesMut::from(&b"hello"[..]); + /// buf.reserve(64); + /// assert!(buf.capacity() >= 69); + /// ``` + /// + /// In the following example, the existing buffer is reclaimed. + /// + /// ``` + /// use bytes::{BytesMut, BufMut}; + /// + /// let mut buf = BytesMut::with_capacity(128); + /// buf.put(&[0; 64][..]); + /// + /// let ptr = buf.as_ptr(); + /// let other = buf.split(); + /// + /// assert!(buf.is_empty()); + /// assert_eq!(buf.capacity(), 64); + /// + /// drop(other); + /// buf.reserve(128); + /// + /// assert_eq!(buf.capacity(), 128); + /// assert_eq!(buf.as_ptr(), ptr); + /// ``` + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + #[inline] + pub fn reserve(&mut self, additional: usize) { + let len = self.len(); + let rem = self.capacity() - len; + + if additional <= rem { + // The handle can already store at least `additional` more bytes, so + // there is no further work needed to be done. + return; + } + + self.reserve_inner(additional); + } + + // In separate function to allow the short-circuits in `reserve` to + // be inline-able. Significant helps performance. + fn reserve_inner(&mut self, additional: usize) { + let len = self.len(); + let kind = self.kind(); + + if kind == KIND_VEC { + // If there's enough free space before the start of the buffer, then + // just copy the data backwards and reuse the already-allocated + // space. + // + // Otherwise, since backed by a vector, use `Vec::reserve` + unsafe { + let (off, prev) = self.get_vec_pos(); + + // 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 + // data back. + let base_ptr = self.ptr.as_ptr().offset(-(off as isize)); + ptr::copy(self.ptr.as_ptr(), base_ptr, self.len); + self.ptr = vptr(base_ptr); + self.set_vec_pos(0, prev); + + // Length stays constant, but since we moved backwards we + // can gain capacity back. + self.cap += off; + } else { + // No space - allocate more + let mut v = + ManuallyDrop::new(rebuild_vec(self.ptr.as_ptr(), self.len, self.cap, off)); + v.reserve(additional); + + // Update the info + self.ptr = vptr(v.as_mut_ptr().offset(off as isize)); + self.len = v.len() - off; + self.cap = v.capacity() - off; + } + + return; + } + } + + 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. + // + // Compute the new capacity + let mut new_cap = len.checked_add(additional).expect("overflow"); + + let original_capacity; + let original_capacity_repr; + + unsafe { + original_capacity_repr = (*shared).original_capacity_repr; + original_capacity = original_capacity_from_repr(original_capacity_repr); + + // First, try to reclaim the buffer. This is possible if the current + // handle is the only outstanding handle pointing to the buffer. + if (*shared).is_unique() { + // This is the only handle to the buffer. It can be reclaimed. + // However, before doing the work of copying data, check to make + // sure that the vector has enough capacity. + let v = &mut (*shared).vec; + + if v.capacity() >= new_cap { + // The capacity is sufficient, reclaim the buffer + let ptr = v.as_mut_ptr(); + + ptr::copy(self.ptr.as_ptr(), ptr, len); + + self.ptr = vptr(ptr); + self.cap = v.capacity(); + + return; + } + + // The vector capacity is not sufficient. The reserve request is + // asking for more than the initial buffer capacity. Allocate more + // than requested if `new_cap` is not much bigger than the current + // capacity. + // + // There are some situations, using `reserve_exact` that the + // buffer capacity could be below `original_capacity`, so do a + // check. + let double = v.capacity().checked_shl(1).unwrap_or(new_cap); + + new_cap = cmp::max(cmp::max(double, new_cap), original_capacity); + } else { + new_cap = cmp::max(new_cap, original_capacity); + } + } + + // Create a new vector to store the data + let mut v = ManuallyDrop::new(Vec::with_capacity(new_cap)); + + // Copy the bytes + v.extend_from_slice(self.as_ref()); + + // Release the shared handle. This must be done *after* the bytes are + // copied. + unsafe { release_shared(shared) }; + + // Update self + let data = (original_capacity_repr << ORIGINAL_CAPACITY_OFFSET) | KIND_VEC; + self.data = data as _; + self.ptr = vptr(v.as_mut_ptr()); + self.len = v.len(); + self.cap = v.capacity(); + } + + /// Appends given bytes to this `BytesMut`. + /// + /// If this `BytesMut` object does not have enough capacity, it is resized + /// first. + /// + /// # Examples + /// + /// ``` + /// use bytes::BytesMut; + /// + /// let mut buf = BytesMut::with_capacity(0); + /// buf.extend_from_slice(b"aaabbb"); + /// buf.extend_from_slice(b"cccddd"); + /// + /// assert_eq!(b"aaabbbcccddd", &buf[..]); + /// ``` + pub fn extend_from_slice(&mut self, extend: &[u8]) { + let cnt = extend.len(); + self.reserve(cnt); + + unsafe { + let dst = self.uninit_slice(); + // Reserved above + debug_assert!(dst.len() >= cnt); + + ptr::copy_nonoverlapping(extend.as_ptr(), dst.as_mut_ptr() as *mut u8, cnt); + } + + unsafe { + self.advance_mut(cnt); + } + } + + /// Absorbs a `BytesMut` that was previously split off. + /// + /// 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 + /// + /// ``` + /// use bytes::BytesMut; + /// + /// let mut buf = BytesMut::with_capacity(64); + /// buf.extend_from_slice(b"aaabbbcccddd"); + /// + /// let split = buf.split_off(6); + /// assert_eq!(b"aaabbb", &buf[..]); + /// assert_eq!(b"cccddd", &split[..]); + /// + /// buf.unsplit(split); + /// assert_eq!(b"aaabbbcccddd", &buf[..]); + /// ``` + pub fn unsplit(&mut self, other: BytesMut) { + if self.is_empty() { + *self = other; + return; + } + + if let Err(other) = self.try_unsplit(other) { + self.extend_from_slice(other.as_ref()); + } + } + + // private + + // For now, use a `Vec` to manage the memory for us, but we may want to + // change that in the future to some alternate allocator strategy. + // + // Thus, we don't expose an easy way to construct from a `Vec` since an + // internal change could make a simple pattern (`BytesMut::from(vec)`) + // suddenly a lot more expensive. + #[inline] + pub(crate) fn from_vec(mut vec: Vec) -> BytesMut { + let ptr = vptr(vec.as_mut_ptr()); + let len = vec.len(); + let cap = vec.capacity(); + mem::forget(vec); + + let original_capacity_repr = original_capacity_to_repr(cap); + let data = (original_capacity_repr << ORIGINAL_CAPACITY_OFFSET) | KIND_VEC; + + BytesMut { + ptr, + len, + cap, + data: data as *mut _, + } + } + + #[inline] + fn as_slice(&self) -> &[u8] { + 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 fn set_start(&mut self, start: usize) { + // Setting the start to 0 is a no-op, so return early if this is the + // case. + if start == 0 { + return; + } + + debug_assert!(start <= self.cap, "internal: set_start out of bounds"); + + let kind = self.kind(); + + if kind == KIND_VEC { + // Setting the start when in vec representation is a little more + // complicated. First, we have to track how far ahead the + // "start" of the byte buffer from the beginning of the vec. We + // also have to ensure that we don't exceed the maximum shift. + let (mut pos, prev) = self.get_vec_pos(); + pos += start; + + if pos <= MAX_VEC_POS { + self.set_vec_pos(pos, prev); + } else { + // The repr must be upgraded to ARC. This will never happen + // 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); + } + } + + // Updating the start of the view is setting `ptr` to point to the + // new start and updating the `len` field to reflect the new length + // of the view. + self.ptr = vptr(self.ptr.as_ptr().offset(start as isize)); + + if self.len >= start { + self.len -= start; + } else { + self.len = 0; + } + + self.cap -= start; + } + + unsafe fn set_end(&mut self, end: usize) { + debug_assert_eq!(self.kind(), KIND_ARC); + assert!(end <= self.cap, "set_end out of bounds"); + + self.cap = end; + self.len = cmp::min(self.len, end); + } + + fn try_unsplit(&mut self, other: BytesMut) -> Result<(), BytesMut> { + if other.capacity() == 0 { + return Ok(()); + } + + 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 + { + // Contiguous blocks, just combine directly + self.len += other.len; + self.cap += other.cap; + Ok(()) + } else { + Err(other) + } + } + + #[inline] + fn kind(&self) -> usize { + self.data as usize & KIND_MASK + } + + unsafe fn promote_to_shared(&mut self, ref_cnt: usize) { + debug_assert_eq!(self.kind(), KIND_VEC); + debug_assert!(ref_cnt == 1 || ref_cnt == 2); + + let original_capacity_repr = + (self.data as usize & ORIGINAL_CAPACITY_MASK) >> ORIGINAL_CAPACITY_OFFSET; + + // The vec offset cannot be concurrently mutated, so there + // should be no danger reading it. + let off = (self.data as usize) >> VEC_POS_OFFSET; + + // 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`. + // This means that these fields will not be concurrently + // updated and since the buffer hasn't been promoted to an + // `Arc`, those three fields still are the components of the + // vector. + let shared = Box::new(Shared { + vec: rebuild_vec(self.ptr.as_ptr(), self.len, self.cap, off), + original_capacity_repr, + ref_count: AtomicUsize::new(ref_cnt), + }); + + let shared = Box::into_raw(shared); + + // The pointer should be aligned, so this assert should + // always succeed. + debug_assert_eq!(shared as usize & KIND_MASK, KIND_ARC); + + self.data = shared as _; + } + + /// Makes an exact shallow clone of `self`. + /// + /// The kind of `self` doesn't matter, but this is unsafe + /// because the clone will have the same offsets. You must + /// be sure the returned value to the user doesn't allow + /// two views into the same range. + #[inline] + unsafe fn shallow_clone(&mut self) -> BytesMut { + if self.kind() == KIND_ARC { + increment_shared(self.data); + ptr::read(self) + } else { + self.promote_to_shared(/*ref_count = */ 2); + ptr::read(self) + } + } + + #[inline] + unsafe fn get_vec_pos(&mut self) -> (usize, usize) { + debug_assert_eq!(self.kind(), KIND_VEC); + + let prev = self.data as usize; + (prev >> VEC_POS_OFFSET, prev) + } + + #[inline] + unsafe fn set_vec_pos(&mut self, pos: usize, prev: usize) { + debug_assert_eq!(self.kind(), KIND_VEC); + debug_assert!(pos <= MAX_VEC_POS); + + self.data = ((pos << VEC_POS_OFFSET) | (prev & NOT_VEC_POS_MASK)) as *mut _; + } + + #[inline] + fn uninit_slice(&mut self) -> &mut UninitSlice { + unsafe { + let ptr = self.ptr.as_ptr().offset(self.len as isize); + let len = self.cap - self.len; + + UninitSlice::from_raw_parts_mut(ptr, len) + } + } +} + +impl Drop for BytesMut { + fn drop(&mut self) { + let kind = self.kind(); + + if kind == KIND_VEC { + unsafe { + let (off, _) = self.get_vec_pos(); + + // Vector storage, free the vector + let _ = rebuild_vec(self.ptr.as_ptr(), self.len, self.cap, off); + } + } else if kind == KIND_ARC { + unsafe { release_shared(self.data as _) }; + } + } +} + +impl Buf for BytesMut { + #[inline] + fn remaining(&self) -> usize { + self.len() + } + + #[inline] + fn chunk(&self) -> &[u8] { + self.as_slice() + } + + #[inline] + fn advance(&mut self, cnt: usize) { + assert!( + cnt <= self.remaining(), + "cannot advance past `remaining`: {:?} <= {:?}", + cnt, + self.remaining(), + ); + unsafe { + self.set_start(cnt); + } + } + + fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes { + self.split_to(len).freeze() + } +} + +unsafe impl BufMut for BytesMut { + #[inline] + fn remaining_mut(&self) -> usize { + usize::MAX - self.len() + } + + #[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 + ); + self.len = new_len; + } + + #[inline] + fn chunk_mut(&mut self) -> &mut UninitSlice { + if self.capacity() == self.len() { + self.reserve(64); + } + self.uninit_slice() + } + + // Specialize these methods so they can skip checking `remaining_mut` + // and `advance_mut`. + + fn put(&mut self, mut src: T) + where + Self: Sized, + { + while src.has_remaining() { + let s = src.chunk(); + let l = s.len(); + self.extend_from_slice(s); + src.advance(l); + } + } + + fn put_slice(&mut self, src: &[u8]) { + self.extend_from_slice(src); + } + + fn put_bytes(&mut self, val: u8, cnt: usize) { + self.reserve(cnt); + unsafe { + let dst = self.uninit_slice(); + // Reserved above + debug_assert!(dst.len() >= cnt); + + ptr::write_bytes(dst.as_mut_ptr(), val, cnt); + + self.advance_mut(cnt); + } + } +} + +impl AsRef<[u8]> for BytesMut { + #[inline] + fn as_ref(&self) -> &[u8] { + self.as_slice() + } +} + +impl Deref for BytesMut { + type Target = [u8]; + + #[inline] + fn deref(&self) -> &[u8] { + self.as_ref() + } +} + +impl AsMut<[u8]> for BytesMut { + #[inline] + fn as_mut(&mut self) -> &mut [u8] { + self.as_slice_mut() + } +} + +impl DerefMut for BytesMut { + #[inline] + fn deref_mut(&mut self) -> &mut [u8] { + self.as_mut() + } +} + +impl<'a> From<&'a [u8]> for BytesMut { + fn from(src: &'a [u8]) -> BytesMut { + BytesMut::from_vec(src.to_vec()) + } +} + +impl<'a> From<&'a str> for BytesMut { + fn from(src: &'a str) -> BytesMut { + BytesMut::from(src.as_bytes()) + } +} + +impl From 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() + } +} + +impl PartialOrd for BytesMut { + fn partial_cmp(&self, other: &BytesMut) -> Option { + self.as_slice().partial_cmp(other.as_slice()) + } +} + +impl Ord for BytesMut { + fn cmp(&self, other: &BytesMut) -> cmp::Ordering { + self.as_slice().cmp(other.as_slice()) + } +} + +impl Eq for BytesMut {} + +impl Default for BytesMut { + #[inline] + fn default() -> BytesMut { + BytesMut::new() + } +} + +impl hash::Hash for BytesMut { + fn hash(&self, state: &mut H) + where + H: hash::Hasher, + { + let s: &[u8] = self.as_ref(); + s.hash(state); + } +} + +impl Borrow<[u8]> for BytesMut { + fn borrow(&self) -> &[u8] { + self.as_ref() + } +} + +impl BorrowMut<[u8]> for BytesMut { + fn borrow_mut(&mut self) -> &mut [u8] { + self.as_mut() + } +} + +impl fmt::Write for BytesMut { + #[inline] + fn write_str(&mut self, s: &str) -> fmt::Result { + if self.remaining_mut() >= s.len() { + self.put_slice(s.as_bytes()); + Ok(()) + } else { + Err(fmt::Error) + } + } + + #[inline] + fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result { + fmt::write(self, args) + } +} + +impl Clone for BytesMut { + fn clone(&self) -> BytesMut { + BytesMut::from(&self[..]) + } +} + +impl IntoIterator for BytesMut { + type Item = u8; + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + IntoIter::new(self) + } +} + +impl<'a> IntoIterator for &'a BytesMut { + type Item = &'a u8; + type IntoIter = core::slice::Iter<'a, u8>; + + fn into_iter(self) -> Self::IntoIter { + self.as_ref().into_iter() + } +} + +impl Extend for BytesMut { + fn extend(&mut self, iter: T) + where + T: IntoIterator, + { + let iter = iter.into_iter(); + + let (lower, _) = iter.size_hint(); + self.reserve(lower); + + // TODO: optimize + // 1. If self.kind() == KIND_VEC, use Vec::extend + // 2. Make `reserve` inline-able + for b in iter { + self.reserve(1); + self.put_u8(b); + } + } +} + +impl<'a> Extend<&'a u8> for BytesMut { + fn extend(&mut self, iter: T) + where + T: IntoIterator, + { + self.extend(iter.into_iter().map(|b| *b)) + } +} + +impl FromIterator for BytesMut { + fn from_iter>(into_iter: T) -> Self { + BytesMut::from_vec(Vec::from_iter(into_iter)) + } +} + +impl<'a> FromIterator<&'a u8> for BytesMut { + fn from_iter>(into_iter: T) -> Self { + BytesMut::from_iter(into_iter.into_iter().map(|b| *b)) + } +} + +/* + * + * ===== Inner ===== + * + */ + +unsafe fn increment_shared(ptr: *mut Shared) { + let old_size = (*ptr).ref_count.fetch_add(1, Ordering::Relaxed); + + if old_size > isize::MAX as usize { + crate::abort(); + } +} + +unsafe fn release_shared(ptr: *mut Shared) { + // `Shared` storage... follow the drop steps from Arc. + if (*ptr).ref_count.fetch_sub(1, Ordering::Release) != 1 { + return; + } + + // This fence is needed to prevent reordering of use of the data and + // deletion of the data. Because it is marked `Release`, the decreasing + // of the reference count synchronizes with this `Acquire` fence. This + // means that use of the data happens before decreasing the reference + // count, which happens before this fence, which happens before the + // deletion of the data. + // + // As explained in the [Boost documentation][1], + // + // > It is important to enforce any possible access to the object in one + // > thread (through an existing reference) to *happen before* deleting + // > the object in a different thread. This is achieved by a "release" + // > operation after dropping a reference (any access to the object + // > through this reference must obviously happened before), and an + // > "acquire" operation before deleting the object. + // + // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) + atomic::fence(Ordering::Acquire); + + // Drop the data + Box::from_raw(ptr); +} + +impl Shared { + fn is_unique(&self) -> bool { + // The goal is to check if the current handle is the only handle + // that currently has access to the buffer. This is done by + // checking if the `ref_count` is currently 1. + // + // The `Acquire` ordering synchronizes with the `Release` as + // part of the `fetch_sub` in `release_shared`. The `fetch_sub` + // operation guarantees that any mutations done in other threads + // are ordered before the `ref_count` is decremented. As such, + // this `Acquire` will guarantee that those mutations are + // visible to the current thread. + self.ref_count.load(Ordering::Acquire) == 1 + } +} + +#[inline] +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, + ) +} + +fn original_capacity_from_repr(repr: usize) -> usize { + if repr == 0 { + return 0; + } + + 1 << (repr + (MIN_ORIGINAL_CAPACITY_WIDTH - 1)) +} + +/* +#[test] +fn test_original_capacity_to_repr() { + 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); + } + + // 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); + } + } +} + +#[test] +fn test_original_capacity_from_repr() { + assert_eq!(0, original_capacity_from_repr(0)); + + 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 BytesMut {} +unsafe impl Sync for BytesMut {} + +/* + * + * ===== PartialEq / PartialOrd ===== + * + */ + +impl PartialEq<[u8]> for BytesMut { + fn eq(&self, other: &[u8]) -> bool { + &**self == other + } +} + +impl PartialOrd<[u8]> for BytesMut { + fn partial_cmp(&self, other: &[u8]) -> Option { + (**self).partial_cmp(other) + } +} + +impl PartialEq for [u8] { + fn eq(&self, other: &BytesMut) -> bool { + *other == *self + } +} + +impl PartialOrd for [u8] { + fn partial_cmp(&self, other: &BytesMut) -> Option { + <[u8] as PartialOrd<[u8]>>::partial_cmp(self, other) + } +} + +impl PartialEq for BytesMut { + fn eq(&self, other: &str) -> bool { + &**self == other.as_bytes() + } +} + +impl PartialOrd for BytesMut { + fn partial_cmp(&self, other: &str) -> Option { + (**self).partial_cmp(other.as_bytes()) + } +} + +impl PartialEq for str { + fn eq(&self, other: &BytesMut) -> bool { + *other == *self + } +} + +impl PartialOrd for str { + fn partial_cmp(&self, other: &BytesMut) -> Option { + <[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other) + } +} + +impl PartialEq> for BytesMut { + fn eq(&self, other: &Vec) -> bool { + *self == &other[..] + } +} + +impl PartialOrd> for BytesMut { + fn partial_cmp(&self, other: &Vec) -> Option { + (**self).partial_cmp(&other[..]) + } +} + +impl PartialEq for Vec { + fn eq(&self, other: &BytesMut) -> bool { + *other == *self + } +} + +impl PartialOrd for Vec { + fn partial_cmp(&self, other: &BytesMut) -> Option { + other.partial_cmp(self) + } +} + +impl PartialEq for BytesMut { + fn eq(&self, other: &String) -> bool { + *self == &other[..] + } +} + +impl PartialOrd for BytesMut { + fn partial_cmp(&self, other: &String) -> Option { + (**self).partial_cmp(other.as_bytes()) + } +} + +impl PartialEq for String { + fn eq(&self, other: &BytesMut) -> bool { + *other == *self + } +} + +impl PartialOrd for String { + fn partial_cmp(&self, other: &BytesMut) -> Option { + <[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other) + } +} + +impl<'a, T: ?Sized> PartialEq<&'a T> for BytesMut +where + BytesMut: PartialEq, +{ + fn eq(&self, other: &&'a T) -> bool { + *self == **other + } +} + +impl<'a, T: ?Sized> PartialOrd<&'a T> for BytesMut +where + BytesMut: PartialOrd, +{ + fn partial_cmp(&self, other: &&'a T) -> Option { + self.partial_cmp(*other) + } +} + +impl PartialEq for &[u8] { + fn eq(&self, other: &BytesMut) -> bool { + *other == *self + } +} + +impl PartialOrd for &[u8] { + fn partial_cmp(&self, other: &BytesMut) -> Option { + <[u8] as PartialOrd<[u8]>>::partial_cmp(self, other) + } +} + +impl PartialEq for &str { + fn eq(&self, other: &BytesMut) -> bool { + *other == *self + } +} + +impl PartialOrd for &str { + fn partial_cmp(&self, other: &BytesMut) -> Option { + other.partial_cmp(self) + } +} + +impl PartialEq for Bytes { + fn eq(&self, other: &BytesMut) -> bool { + &other[..] == &self[..] + } +} + +impl PartialEq for BytesMut { + fn eq(&self, other: &Bytes) -> bool { + &other[..] == &self[..] + } +} + +#[inline] +fn vptr(ptr: *mut u8) -> NonNull { + if cfg!(debug_assertions) { + NonNull::new(ptr).expect("Vec pointer should be non-null") + } else { + unsafe { NonNull::new_unchecked(ptr) } + } +} + +unsafe fn rebuild_vec(ptr: *mut u8, mut len: usize, mut cap: usize, off: usize) -> Vec { + let ptr = ptr.offset(-(off as isize)); + len += off; + cap += off; + + Vec::from_raw_parts(ptr, len, cap) +} + +// ===== impl SharedVtable ===== + +static SHARED_VTABLE: Vtable = Vtable { + clone: shared_v_clone, + drop: shared_v_drop, +}; + +unsafe fn shared_v_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes { + let shared = data.load(Ordering::Relaxed) as *mut Shared; + increment_shared(shared); + + let data = AtomicPtr::new(shared as _); + Bytes::with_vtable(ptr, len, data, &SHARED_VTABLE) +} + +unsafe fn shared_v_drop(data: &mut AtomicPtr<()>, _ptr: *const u8, _len: usize) { + data.with_mut(|shared| { + release_shared(*shared as *mut Shared); + }); +} + +// compile-fails + +/// ```compile_fail +/// use bytes::BytesMut; +/// #[deny(unused_must_use)] +/// { +/// let mut b1 = BytesMut::from("hello world"); +/// b1.split_to(6); +/// } +/// ``` +fn _split_to_must_use() {} + +/// ```compile_fail +/// use bytes::BytesMut; +/// #[deny(unused_must_use)] +/// { +/// let mut b1 = BytesMut::from("hello world"); +/// b1.split_off(6); +/// } +/// ``` +fn _split_off_must_use() {} + +/// ```compile_fail +/// use bytes::BytesMut; +/// #[deny(unused_must_use)] +/// { +/// let mut b1 = BytesMut::from("hello world"); +/// b1.split(); +/// } +/// ``` +fn _split_must_use() {} + +// fuzz tests +#[cfg(all(test, loom))] +mod fuzz { + use loom::sync::Arc; + use loom::thread; + + use super::BytesMut; + use crate::Bytes; + + #[test] + fn bytes_mut_cloning_frozen() { + loom::model(|| { + let a = BytesMut::from(&b"abcdefgh"[..]).split().freeze(); + let addr = a.as_ptr() as usize; + + // test the Bytes::clone is Sync by putting it in an Arc + let a1 = Arc::new(a); + let a2 = a1.clone(); + + let t1 = thread::spawn(move || { + let b: Bytes = (*a1).clone(); + assert_eq!(b.as_ptr() as usize, addr); + }); + + let t2 = thread::spawn(move || { + let b: Bytes = (*a2).clone(); + assert_eq!(b.as_ptr() as usize, addr); + }); + + t1.join().unwrap(); + t2.join().unwrap(); + }); + } +} diff -Nru rust-bytes-0.4.12/src/bytes.rs rust-bytes-1.1.0/src/bytes.rs --- rust-bytes-0.4.12/src/bytes.rs 2019-03-06 19:57:32.000000000 +0000 +++ rust-bytes-1.1.0/src/bytes.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,70 +1,80 @@ -use {IntoBuf, Buf, BufMut}; -use buf::Iter; -use debug; - -use std::{cmp, fmt, mem, hash, ops, slice, ptr, usize}; -use std::borrow::{Borrow, BorrowMut}; -use std::io::Cursor; -use std::sync::atomic::{self, AtomicUsize, AtomicPtr}; -use std::sync::atomic::Ordering::{Relaxed, Acquire, Release, AcqRel}; -use std::iter::{FromIterator, Iterator}; +use core::iter::FromIterator; +use core::ops::{Deref, RangeBounds}; +use core::{cmp, fmt, hash, mem, ptr, slice, usize}; + +use alloc::{borrow::Borrow, boxed::Box, string::String, vec::Vec}; + +use crate::buf::IntoIter; +#[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. +/// A cheaply cloneable and sliceable chunk of contiguous memory. /// /// `Bytes` is an efficient container for storing and operating on contiguous /// slices of memory. It is intended for use primarily in networking code, but /// could have applications elsewhere as well. /// /// `Bytes` values facilitate zero-copy network programming by allowing multiple -/// `Bytes` objects to point to the same underlying memory. This is managed by -/// using a reference count to track when the memory is no longer needed and can -/// be freed. +/// `Bytes` objects to point to the same underlying memory. +/// +/// `Bytes` does not have a single implementation. It is an interface, whose +/// exact behavior is implemented through dynamic dispatch in several underlying +/// implementations of `Bytes`. +/// +/// All `Bytes` implementations must fulfill the following requirements: +/// - They are cheaply cloneable and thereby shareable between an unlimited amount +/// of components, for example by modifying a reference count. +/// - Instances can be sliced to refer to a subset of the the original buffer. /// /// ``` /// use bytes::Bytes; /// -/// let mut mem = Bytes::from(&b"Hello world"[..]); -/// let a = mem.slice(0, 5); +/// let mut mem = Bytes::from("Hello world"); +/// let a = mem.slice(0..5); /// -/// assert_eq!(&a[..], b"Hello"); +/// assert_eq!(a, "Hello"); /// /// let b = mem.split_to(6); /// -/// assert_eq!(&mem[..], b"world"); -/// assert_eq!(&b[..], b"Hello "); +/// assert_eq!(mem, "world"); +/// assert_eq!(b, "Hello "); /// ``` /// /// # Memory layout /// -/// The `Bytes` struct itself is fairly small, limited to a pointer to the -/// memory and 4 `usize` fields used to track information about which segment of -/// the underlying memory the `Bytes` handle has access to. -/// -/// The memory layout looks like this: -/// -/// ```text -/// +-------+ -/// | Bytes | -/// +-------+ -/// / \_____ -/// | \ -/// v v -/// +-----+------------------------------------+ -/// | Arc | | Data | | -/// +-----+------------------------------------+ -/// ``` +/// The `Bytes` struct itself is fairly small, limited to 4 `usize` fields used +/// to track information about which segment of the underlying memory the +/// `Bytes` handle has access to. /// -/// `Bytes` keeps both a pointer to the shared `Arc` containing the full memory +/// `Bytes` keeps both a pointer to the shared state containing the full memory /// slice and a pointer to the start of the region visible by the handle. /// `Bytes` also tracks the length of its view into the memory. /// /// # Sharing /// -/// The memory itself is reference counted, and multiple `Bytes` objects may -/// point to the same region. Each `Bytes` handle point to different sections within -/// the memory region, and `Bytes` handle may or may not have overlapping views +/// `Bytes` contains a vtable, which allows implementations of `Bytes` to define +/// how sharing/cloneing is implemented in detail. +/// When `Bytes::clone()` is called, `Bytes` will call the vtable function for +/// cloning the backing storage in order to share it behind between multiple +/// `Bytes` instances. +/// +/// For `Bytes` implementations which refer to constant memory (e.g. created +/// via `Bytes::from_static()`) the cloning implementation will be a no-op. +/// +/// For `Bytes` implementations which point to a reference counted shared storage +/// (e.g. an `Arc<[u8]>`), sharing will be implemented by increasing the +/// the reference count. +/// +/// Due to this mechanism, multiple `Bytes` instances may point to the same +/// shared memory region. +/// Each `Bytes` instance can point to different sections within that +/// memory region, and `Bytes` instances may or may not have overlapping views /// into the memory. /// +/// The following diagram visualizes a scenario where 2 `Bytes` instances make +/// use of an `Arc`-based backing storage, and provide access to different views: /// /// ```text /// @@ -81,343 +91,22 @@ /// | Arc | | | | | /// +-----+---------------------------------+-----+ /// ``` -/// -/// # Mutating -/// -/// While `Bytes` handles may potentially represent overlapping views of the -/// underlying memory slice and may not be mutated, `BytesMut` handles are -/// guaranteed to be the only handle able to view that slice of memory. As such, -/// `BytesMut` handles are able to mutate the underlying memory. Note that -/// holding a unique view to a region of memory does not mean that there are no -/// other `Bytes` and `BytesMut` handles with disjoint views of the underlying -/// memory. -/// -/// # Inline bytes -/// -/// As an optimization, when the slice referenced by a `Bytes` or `BytesMut` -/// handle is small enough [^1], `with_capacity` will avoid the allocation by -/// inlining the slice directly in the handle. In this case, a clone is no -/// longer "shallow" and the data will be copied. Converting from a `Vec` will -/// never use inlining. -/// -/// [^1]: Small enough: 31 bytes on 64 bit systems, 15 on 32 bit systems. -/// pub struct Bytes { - inner: Inner, -} - -/// 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` but with less copies and -/// allocations. -/// -/// For more detail, see [Bytes](struct.Bytes.html). -/// -/// # Growth -/// -/// One key difference from `Vec` is that most operations **do not -/// implicitly grow the buffer**. This means that calling `my_bytes.put("hello -/// world");` could panic if `my_bytes` does not have enough capacity. Before -/// writing to the buffer, ensure that there is enough remaining capacity by -/// calling `my_bytes.remaining_mut()`. In general, avoiding calls to `reserve` -/// is preferable. -/// -/// The only exception is `extend` which implicitly reserves required capacity. -/// -/// # Examples -/// -/// ``` -/// use bytes::{BytesMut, BufMut}; -/// -/// let mut buf = BytesMut::with_capacity(64); -/// -/// buf.put(b'h'); -/// buf.put(b'e'); -/// buf.put("llo"); -/// -/// assert_eq!(&buf[..], b"hello"); -/// -/// // Freeze the buffer so that it can be shared -/// let a = buf.freeze(); -/// -/// // This does not allocate, instead `b` points to the same memory. -/// let b = a.clone(); -/// -/// assert_eq!(&a[..], b"hello"); -/// assert_eq!(&b[..], b"hello"); -/// ``` -pub struct BytesMut { - inner: Inner, -} - -// Both `Bytes` and `BytesMut` are backed by `Inner` and functions are delegated -// to `Inner` functions. The `Bytes` and `BytesMut` shims ensure that functions -// that mutate the underlying buffer are only performed when the data range -// being mutated is only available via a single `BytesMut` handle. -// -// # Data storage modes -// -// The goal of `bytes` is to be as efficient as possible across a wide range of -// potential usage patterns. As such, `bytes` needs to be able to handle buffers -// that are never shared, shared on a single thread, and shared across many -// threads. `bytes` also needs to handle both tiny buffers as well as very large -// buffers. For example, [Cassandra](http://cassandra.apache.org) values have -// been known to be in the hundreds of megabyte, and HTTP header values can be a -// few characters in size. -// -// To achieve high performance in these various situations, `Bytes` and -// `BytesMut` use different strategies for storing the buffer depending on the -// usage pattern. -// -// ## Delayed `Arc` allocation -// -// When a `Bytes` or `BytesMut` is first created, there is only one outstanding -// handle referencing the buffer. Since sharing is not yet required, an `Arc`* is -// not used and the buffer is backed by a `Vec` directly. Using an -// `Arc>` requires two allocations, so if the buffer ends up never being -// shared, that allocation is avoided. -// -// When sharing does become necessary (`clone`, `split_to`, `split_off`), that -// is when the buffer is promoted to being shareable. The `Vec` is moved -// into an `Arc` and both the original handle and the new handle use the same -// buffer via the `Arc`. -// -// * `Arc` is being used to signify an atomically reference counted cell. We -// don't use the `Arc` implementation provided by `std` and instead use our own. -// This ends up simplifying a number of the `unsafe` code snippets. -// -// ## Inlining small buffers -// -// The `Bytes` / `BytesMut` structs require 4 pointer sized fields. On 64 bit -// systems, this ends up being 32 bytes, which is actually a lot of storage for -// cases where `Bytes` is being used to represent small byte strings, such as -// HTTP header names and values. -// -// To avoid any allocation at all in these cases, `Bytes` will use the struct -// itself for storing the buffer, reserving 1 byte for meta data. This means -// that, on 64 bit systems, 31 byte buffers require no allocation at all. -// -// The byte used for metadata stores a 2 bits flag used to indicate that the -// buffer is stored inline as well as 6 bits for tracking the buffer length (the -// return value of `Bytes::len`). -// -// ## Static buffers -// -// `Bytes` can also represent a static buffer, which is created with -// `Bytes::from_static`. No copying or allocations are required for tracking -// static buffers. The pointer to the `&'static [u8]`, the length, and a flag -// tracking that the `Bytes` instance represents a static buffer is stored in -// the `Bytes` struct. -// -// # Struct layout -// -// Both `Bytes` and `BytesMut` are wrappers around `Inner`, which provides the -// data fields as well as all of the function implementations. -// -// The `Inner` struct is carefully laid out in order to support the -// functionality described above as well as being as small as possible. Size is -// important as growing the size of the `Bytes` struct from 32 bytes to 40 bytes -// added as much as 15% overhead in benchmarks using `Bytes` in an HTTP header -// map structure. -// -// The `Inner` struct contains the following fields: -// -// * `ptr: *mut u8` -// * `len: usize` -// * `cap: usize` -// * `arc: AtomicPtr` -// -// ## `ptr: *mut u8` -// -// A pointer to start of the handle's buffer view. When backed by a `Vec`, -// this is always the `Vec`'s pointer. When backed by an `Arc>`, `ptr` -// may have been shifted to point somewhere inside the buffer. -// -// When in "inlined" mode, `ptr` is used as part of the inlined buffer. -// -// ## `len: usize` -// -// The length of the handle's buffer view. When backed by a `Vec`, this is -// always the `Vec`'s length. The slice represented by `ptr` and `len` should -// (ideally) always be initialized memory. -// -// When in "inlined" mode, `len` is used as part of the inlined buffer. -// -// ## `cap: usize` -// -// The capacity of the handle's buffer view. When backed by a `Vec`, this is -// always the `Vec`'s capacity. The slice represented by `ptr+len` and `cap-len` -// may or may not be initialized memory. -// -// When in "inlined" mode, `cap` is used as part of the inlined buffer. -// -// ## `arc: AtomicPtr` -// -// When `Inner` is in allocated mode (backed by Vec or Arc>), this -// will be the pointer to the `Arc` structure tracking the ref count for the -// underlying buffer. When the pointer is null, then the `Arc` has not been -// allocated yet and `self` is the only outstanding handle for the underlying -// buffer. -// -// The lower two bits of `arc` are used to track the storage mode of `Inner`. -// `0b01` indicates inline storage, `0b10` indicates static storage, and `0b11` -// indicates vector storage, not yet promoted to Arc. Since pointers to -// allocated structures are aligned, the lower two bits of a pointer will always -// be 0. This allows disambiguating between a pointer and the two flags. -// -// When in "inlined" mode, the least significant byte of `arc` is also used to -// store the length of the buffer view (vs. the capacity, which is a constant). -// -// 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 big or -// little endian. -// -// On little endian platforms, the `arc` field must be the first field in the -// struct. On big endian platforms, the `arc` field must be the last field in -// the struct. Since a deterministic struct layout is required, `Inner` is -// annotated with `#[repr(C)]`. -// -// # Thread safety -// -// `Bytes::clone()` returns a new `Bytes` handle with no copying. This is done -// by bumping the buffer ref count and returning a new struct pointing to the -// same buffer. However, the `Arc` structure is lazily allocated. This means -// that if `Bytes` is stored itself in an `Arc` (`Arc`), the `clone` -// function can be called concurrently from multiple threads. This is why an -// `AtomicPtr` is used for the `arc` field vs. a `*const`. -// -// Care is taken to ensure that the need for synchronization is minimized. Most -// operations do not require any synchronization. -// -#[cfg(target_endian = "little")] -#[repr(C)] -struct Inner { - // WARNING: Do not access the fields directly unless you know what you are - // doing. Instead, use the fns. See implementation comment above. - arc: AtomicPtr, - ptr: *mut u8, + ptr: *const u8, len: usize, - cap: usize, + // inlined "trait object" + data: AtomicPtr<()>, + vtable: &'static Vtable, } -#[cfg(target_endian = "big")] -#[repr(C)] -struct Inner { - // WARNING: Do not access the fields directly unless you know what you are - // doing. Instead, use the fns. See implementation comment above. - ptr: *mut u8, - len: usize, - cap: usize, - arc: AtomicPtr, +pub(crate) struct Vtable { + /// fn(data, ptr, len) + pub clone: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> Bytes, + /// fn(data, ptr, len) + pub drop: unsafe fn(&mut AtomicPtr<()>, *const u8, usize), } -// Thread-safe reference-counted container for the shared storage. This mostly -// the same as `std::sync::Arc` but without the weak counter. The ref counting -// fns are based on the ones found in `std`. -// -// The main reason to use `Shared` instead of `std::sync::Arc` is that it ends -// up making the overall code simpler and easier to reason about. This is due to -// some of the logic around setting `Inner::arc` and other ways the `arc` field -// is used. Using `Arc` ended up requiring a number of funky transmutes and -// other shenanigans to make it work. -struct Shared { - vec: Vec, - original_capacity_repr: usize, - ref_count: AtomicUsize, -} - -// Buffer storage strategy flags. -const KIND_ARC: usize = 0b00; -const KIND_INLINE: usize = 0b01; -const KIND_STATIC: usize = 0b10; -const KIND_VEC: usize = 0b11; -const KIND_MASK: usize = 0b11; - -// The max original capacity value. Any `Bytes` allocated with a greater initial -// capacity will default to this. -const MAX_ORIGINAL_CAPACITY_WIDTH: usize = 17; -// The original capacity algorithm will not take effect unless the originally -// allocated capacity was at least 1kb in size. -const MIN_ORIGINAL_CAPACITY_WIDTH: usize = 10; -// The original capacity is stored in powers of 2 starting at 1kb to a max of -// 64kb. Representing it as such requires only 3 bits of storage. -const ORIGINAL_CAPACITY_MASK: usize = 0b11100; -const ORIGINAL_CAPACITY_OFFSET: usize = 2; - -// When the storage is in the `Vec` representation, the pointer can be advanced -// at most this value. This is due to the amount of storage available to track -// the offset is usize - number of KIND bits and number of ORIGINAL_CAPACITY -// bits. -const VEC_POS_OFFSET: usize = 5; -const MAX_VEC_POS: usize = usize::MAX >> VEC_POS_OFFSET; -const NOT_VEC_POS_MASK: usize = 0b11111; - -// Bit op constants for extracting the inline length value from the `arc` field. -const INLINE_LEN_MASK: usize = 0b11111100; -const INLINE_LEN_OFFSET: usize = 2; - -// Byte offset from the start of `Inner` to where the inline buffer data -// starts. On little endian platforms, the first byte of the struct is the -// storage flag, so the data is shifted by a byte. On big endian systems, the -// data starts at the beginning of the struct. -#[cfg(target_endian = "little")] -const INLINE_DATA_OFFSET: isize = 1; -#[cfg(target_endian = "big")] -const INLINE_DATA_OFFSET: isize = 0; - -#[cfg(target_pointer_width = "64")] -const PTR_WIDTH: usize = 64; -#[cfg(target_pointer_width = "32")] -const PTR_WIDTH: usize = 32; - -// Inline buffer capacity. This is the size of `Inner` minus 1 byte for the -// metadata. -#[cfg(target_pointer_width = "64")] -const INLINE_CAP: usize = 4 * 8 - 1; -#[cfg(target_pointer_width = "32")] -const INLINE_CAP: usize = 4 * 4 - 1; - -/* - * - * ===== Bytes ===== - * - */ - impl Bytes { - /// Creates a new `Bytes` with the specified capacity. - /// - /// The returned `Bytes` will be able to hold at least `capacity` bytes - /// without reallocating. If `capacity` is under `4 * size_of::() - 1`, - /// then `BytesMut` will not allocate. - /// - /// It is important to note that this function does not specify the length - /// of the returned `Bytes`, but only the capacity. - /// - /// # Examples - /// - /// ``` - /// use bytes::Bytes; - /// - /// let mut bytes = Bytes::with_capacity(64); - /// - /// // `bytes` contains no data, even though there is capacity - /// assert_eq!(bytes.len(), 0); - /// - /// bytes.extend_from_slice(&b"hello world"[..]); - /// - /// assert_eq!(&bytes[..], b"hello world"); - /// ``` - #[inline] - pub fn with_capacity(capacity: usize) -> Bytes { - Bytes { - inner: Inner::with_capacity(capacity), - } - } - /// Creates a new empty `Bytes`. /// /// This will not allocate and the returned `Bytes` handle will be empty. @@ -431,8 +120,18 @@ /// 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::with_capacity(0) + const EMPTY: &[u8] = &[]; + Bytes::from_static(EMPTY) } /// Creates a new `Bytes` from a static slice. @@ -449,9 +148,23 @@ /// assert_eq!(&b[..], b"hello"); /// ``` #[inline] + #[cfg(not(all(loom, test)))] + pub const fn from_static(bytes: &'static [u8]) -> Bytes { + Bytes { + ptr: bytes.as_ptr(), + len: bytes.len(), + data: AtomicPtr::new(ptr::null_mut()), + vtable: &STATIC_VTABLE, + } + } + + #[cfg(all(loom, test))] pub fn from_static(bytes: &'static [u8]) -> Bytes { Bytes { - inner: Inner::from_static(bytes), + ptr: bytes.as_ptr(), + len: bytes.len(), + data: AtomicPtr::new(ptr::null_mut()), + vtable: &STATIC_VTABLE, } } @@ -467,7 +180,7 @@ /// ``` #[inline] pub fn len(&self) -> usize { - self.inner.len() + self.len } /// Returns true if the `Bytes` has a length of 0. @@ -482,10 +195,15 @@ /// ``` #[inline] pub fn is_empty(&self) -> bool { - self.inner.is_empty() + self.len == 0 + } + + /// Creates `Bytes` instance from slice, by copying it. + pub fn copy_from_slice(data: &[u8]) -> Self { + data.to_vec().into() } - /// Returns a slice of self for the index range `[begin..end)`. + /// Returns a slice of self for the provided range. /// /// This will increment the reference count for the underlying memory and /// return a new `Bytes` handle set to the slice. @@ -498,7 +216,7 @@ /// use bytes::Bytes; /// /// let a = Bytes::from(&b"hello world"[..]); - /// let b = a.slice(2, 5); + /// let b = a.slice(2..5); /// /// assert_eq!(&b[..], b"llo"); /// ``` @@ -507,73 +225,46 @@ /// /// Requires that `begin <= end` and `end <= self.len()`, otherwise slicing /// will panic. - pub fn slice(&self, begin: usize, end: usize) -> Bytes { - assert!(begin <= end); - assert!(end <= self.len()); + pub fn slice(&self, range: impl RangeBounds) -> Bytes { + use core::ops::Bound; - if end - begin <= INLINE_CAP { - return Bytes::from(&self[begin..end]); - } + let len = self.len(); - let mut ret = self.clone(); + let begin = match range.start_bound() { + Bound::Included(&n) => n, + Bound::Excluded(&n) => n + 1, + Bound::Unbounded => 0, + }; - unsafe { - ret.inner.set_end(end); - ret.inner.set_start(begin); + let end = match range.end_bound() { + Bound::Included(&n) => n.checked_add(1).expect("out of range"), + Bound::Excluded(&n) => n, + Bound::Unbounded => 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(); } - ret - } + let mut ret = self.clone(); - /// Returns a slice of self for the index range `[begin..self.len())`. - /// - /// This will increment the reference count for the underlying memory and - /// return a new `Bytes` handle set to the slice. - /// - /// This operation is `O(1)` and is equivalent to `self.slice(begin, - /// self.len())`. - /// - /// # Examples - /// - /// ``` - /// use bytes::Bytes; - /// - /// let a = Bytes::from(&b"hello world"[..]); - /// let b = a.slice_from(6); - /// - /// assert_eq!(&b[..], b"world"); - /// ``` - /// - /// # Panics - /// - /// Requires that `begin <= self.len()`, otherwise slicing will panic. - pub fn slice_from(&self, begin: usize) -> Bytes { - self.slice(begin, self.len()) - } + ret.len = end - begin; + ret.ptr = unsafe { ret.ptr.offset(begin as isize) }; - /// Returns a slice of self for the index range `[0..end)`. - /// - /// This will increment the reference count for the underlying memory and - /// return a new `Bytes` handle set to the slice. - /// - /// This operation is `O(1)` and is equivalent to `self.slice(0, end)`. - /// - /// # Examples - /// - /// ``` - /// use bytes::Bytes; - /// - /// let a = Bytes::from(&b"hello world"[..]); - /// let b = a.slice_to(5); - /// - /// assert_eq!(&b[..], b"hello"); - /// ``` - /// - /// # Panics - /// - /// Requires that `end <= self.len()`, otherwise slicing will panic. - pub fn slice_to(&self, end: usize) -> Bytes { - self.slice(0, end) + ret } /// Returns a slice of self that is equivalent to the given `subset`. @@ -602,18 +293,36 @@ /// 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(); 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); + assert!( + sub_p >= bytes_p, + "subset pointer ({:p}) is smaller than self pointer ({:p})", + sub_p as *const u8, + bytes_p as *const u8, + ); + assert!( + sub_p + sub_len <= bytes_p + bytes_len, + "subset is out of bounds: self = ({:p}, {}), subset = ({:p}, {})", + bytes_p as *const u8, + bytes_len, + sub_p as *const u8, + sub_len, + ); let sub_offset = sub_p - bytes_p; - self.slice(sub_offset, sub_offset + sub_len) + self.slice(sub_offset..(sub_offset + sub_len)) } /// Splits the bytes into two at the given index. @@ -639,8 +348,14 @@ /// # Panics /// /// 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(); @@ -650,9 +365,13 @@ return mem::replace(self, Bytes::new()); } - Bytes { - inner: self.inner.split_off(at), - } + let mut ret = self.clone(); + + self.len = at; + + unsafe { ret.inc_start(at) }; + + ret } /// Splits the bytes into two at the given index. @@ -678,8 +397,14 @@ /// # Panics /// /// 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()); @@ -689,15 +414,12 @@ return Bytes::new(); } - Bytes { - inner: self.inner.split_to(at), - } - } + let mut ret = self.clone(); + + unsafe { self.inc_start(at) }; - #[deprecated(since = "0.4.1", note = "use split_to instead")] - #[doc(hidden)] - pub fn drain_to(&mut self, at: usize) -> Bytes { - self.split_to(at) + ret.len = at; + ret } /// Shortens the buffer, keeping the first `len` bytes and dropping the @@ -720,24 +442,20 @@ /// ``` /// /// [`split_off`]: #method.split_off - pub fn truncate(&mut self, len: usize) { - self.inner.truncate(len); - } - - /// Shortens the buffer, dropping the first `cnt` bytes and keeping the - /// rest. - /// - /// This is the same function as `Buf::advance`, and in the next breaking - /// release of `bytes`, this implementation will be removed in favor of - /// having `Bytes` implement `Buf`. - /// - /// # Panics - /// - /// This function panics if `cnt` is greater than `self.len()` #[inline] - pub fn advance(&mut self, cnt: usize) { - assert!(cnt <= self.len(), "cannot advance past `remaining`"); - unsafe { self.inner.set_start(cnt); } + 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. @@ -751,2197 +469,676 @@ /// buf.clear(); /// assert!(buf.is_empty()); /// ``` + #[inline] pub fn clear(&mut self) { self.truncate(0); } - /// Attempts to convert into a `BytesMut` handle. - /// - /// This will only succeed if there are no other outstanding references to - /// the underlying chunk of memory. `Bytes` handles that contain inlined - /// bytes will always be convertable to `BytesMut`. - /// - /// # Examples - /// - /// ``` - /// use bytes::Bytes; - /// - /// let a = Bytes::from(&b"Mary had a little lamb, little lamb, little lamb..."[..]); - /// - /// // Create a shallow clone - /// let b = a.clone(); - /// - /// // This will fail because `b` shares a reference with `a` - /// let a = a.try_mut().unwrap_err(); - /// - /// drop(b); - /// - /// // This will succeed - /// let mut a = a.try_mut().unwrap(); - /// - /// a[0] = b'b'; - /// - /// assert_eq!(&a[..4], b"bary"); - /// ``` - pub fn try_mut(mut self) -> Result { - if self.inner.is_mut_safe() { - Ok(BytesMut { inner: self.inner }) - } else { - Err(self) + #[inline] + pub(crate) unsafe fn with_vtable( + ptr: *const u8, + len: usize, + data: AtomicPtr<()>, + vtable: &'static Vtable, + ) -> Bytes { + Bytes { + ptr, + len, + data, + vtable, } } - /// Appends given bytes to this object. - /// - /// If this `Bytes` object has not enough capacity, it is resized first. - /// If it is shared (`refcount > 1`), it is copied first. - /// - /// This operation can be less effective than the similar operation on - /// `BytesMut`, especially on small additions. - /// - /// # Examples - /// - /// ``` - /// use bytes::Bytes; - /// - /// let mut buf = Bytes::from("aabb"); - /// buf.extend_from_slice(b"ccdd"); - /// buf.extend_from_slice(b"eeff"); - /// - /// assert_eq!(b"aabbccddeeff", &buf[..]); - /// ``` - pub fn extend_from_slice(&mut self, extend: &[u8]) { - if extend.is_empty() { - return; - } - - let new_cap = self.len().checked_add(extend.len()).expect("capacity overflow"); - - let result = match mem::replace(self, Bytes::new()).try_mut() { - Ok(mut bytes_mut) => { - bytes_mut.extend_from_slice(extend); - bytes_mut - }, - Err(bytes) => { - let mut bytes_mut = BytesMut::with_capacity(new_cap); - bytes_mut.put_slice(&bytes); - bytes_mut.put_slice(extend); - bytes_mut - } - }; + // private - mem::replace(self, result.freeze()); + #[inline] + fn as_slice(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.ptr, self.len) } } -} -impl IntoBuf for Bytes { - type Buf = Cursor; - - fn into_buf(self) -> Self::Buf { - Cursor::new(self) + #[inline] + unsafe fn inc_start(&mut self, by: usize) { + // should already be asserted, but debug assert for tests + debug_assert!(self.len >= by, "internal: inc_start out of bounds"); + self.len -= by; + self.ptr = self.ptr.offset(by as isize); } } -impl<'a> IntoBuf for &'a Bytes { - type Buf = Cursor; +// Vtable must enforce this behavior +unsafe impl Send for Bytes {} +unsafe impl Sync for Bytes {} - fn into_buf(self) -> Self::Buf { - Cursor::new(self) +impl Drop for Bytes { + #[inline] + fn drop(&mut self) { + unsafe { (self.vtable.drop)(&mut self.data, self.ptr, self.len) } } } impl Clone for Bytes { + #[inline] fn clone(&self) -> Bytes { - Bytes { - inner: unsafe { self.inner.shallow_clone(false) }, - } + unsafe { (self.vtable.clone)(&self.data, self.ptr, self.len) } } } -impl AsRef<[u8]> for Bytes { +impl Buf for Bytes { #[inline] - fn as_ref(&self) -> &[u8] { - self.inner.as_ref() + fn remaining(&self) -> usize { + self.len() } -} -impl ops::Deref for Bytes { - type Target = [u8]; + #[inline] + fn chunk(&self) -> &[u8] { + self.as_slice() + } #[inline] - fn deref(&self) -> &[u8] { - self.inner.as_ref() + fn advance(&mut self, cnt: usize) { + assert!( + cnt <= self.len(), + "cannot advance past `remaining`: {:?} <= {:?}", + cnt, + self.len(), + ); + + unsafe { + self.inc_start(cnt); + } } -} -impl From for Bytes { - fn from(src: BytesMut) -> Bytes { - src.freeze() + fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes { + if len == self.remaining() { + core::mem::replace(self, Bytes::new()) + } else { + let ret = self.slice(..len); + self.advance(len); + ret + } } } -impl From> for Bytes { - fn from(src: Vec) -> Bytes { - BytesMut::from(src).freeze() +impl Deref for Bytes { + type Target = [u8]; + + #[inline] + fn deref(&self) -> &[u8] { + self.as_slice() } } -impl From for Bytes { - fn from(src: String) -> Bytes { - BytesMut::from(src).freeze() +impl AsRef<[u8]> for Bytes { + #[inline] + fn as_ref(&self) -> &[u8] { + self.as_slice() } } -impl<'a> From<&'a [u8]> for Bytes { - fn from(src: &'a [u8]) -> Bytes { - BytesMut::from(src).freeze() +impl hash::Hash for Bytes { + fn hash(&self, state: &mut H) + where + H: hash::Hasher, + { + self.as_slice().hash(state); } } -impl<'a> From<&'a str> for Bytes { - fn from(src: &'a str) -> Bytes { - BytesMut::from(src).freeze() +impl Borrow<[u8]> for Bytes { + fn borrow(&self) -> &[u8] { + self.as_slice() } } -impl FromIterator for BytesMut { - fn from_iter>(into_iter: T) -> Self { - let iter = into_iter.into_iter(); - let (min, maybe_max) = iter.size_hint(); +impl IntoIterator for Bytes { + type Item = u8; + type IntoIter = IntoIter; - let mut out = BytesMut::with_capacity(maybe_max.unwrap_or(min)); + fn into_iter(self) -> Self::IntoIter { + IntoIter::new(self) + } +} - for i in iter { - out.reserve(1); - out.put(i); - } +impl<'a> IntoIterator for &'a Bytes { + type Item = &'a u8; + type IntoIter = core::slice::Iter<'a, u8>; - out + fn into_iter(self) -> Self::IntoIter { + self.as_slice().into_iter() } } impl FromIterator for Bytes { fn from_iter>(into_iter: T) -> Self { - BytesMut::from_iter(into_iter).freeze() - } -} - -impl<'a> FromIterator<&'a u8> for BytesMut { - fn from_iter>(into_iter: T) -> Self { - BytesMut::from_iter(into_iter.into_iter().map(|b| *b)) + Vec::from_iter(into_iter).into() } } -impl<'a> FromIterator<&'a u8> for Bytes { - fn from_iter>(into_iter: T) -> Self { - BytesMut::from_iter(into_iter).freeze() - } -} +// impl Eq impl PartialEq for Bytes { fn eq(&self, other: &Bytes) -> bool { - self.inner.as_ref() == other.inner.as_ref() + self.as_slice() == other.as_slice() } } impl PartialOrd for Bytes { fn partial_cmp(&self, other: &Bytes) -> Option { - self.inner.as_ref().partial_cmp(other.inner.as_ref()) + self.as_slice().partial_cmp(other.as_slice()) } } impl Ord for Bytes { fn cmp(&self, other: &Bytes) -> cmp::Ordering { - self.inner.as_ref().cmp(other.inner.as_ref()) + self.as_slice().cmp(other.as_slice()) } } -impl Eq for Bytes { -} +impl Eq for Bytes {} -impl Default for Bytes { - #[inline] - fn default() -> Bytes { - Bytes::new() +impl PartialEq<[u8]> for Bytes { + fn eq(&self, other: &[u8]) -> bool { + self.as_slice() == other } } -impl fmt::Debug for Bytes { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&debug::BsDebug(&self.inner.as_ref()), fmt) +impl PartialOrd<[u8]> for Bytes { + fn partial_cmp(&self, other: &[u8]) -> Option { + self.as_slice().partial_cmp(other) } } -impl hash::Hash for Bytes { - fn hash(&self, state: &mut H) where H: hash::Hasher { - let s: &[u8] = self.as_ref(); - s.hash(state); +impl PartialEq for [u8] { + fn eq(&self, other: &Bytes) -> bool { + *other == *self } } -impl Borrow<[u8]> for Bytes { - fn borrow(&self) -> &[u8] { - self.as_ref() +impl PartialOrd for [u8] { + fn partial_cmp(&self, other: &Bytes) -> Option { + <[u8] as PartialOrd<[u8]>>::partial_cmp(self, other) } } -impl IntoIterator for Bytes { - type Item = u8; - type IntoIter = Iter>; - - fn into_iter(self) -> Self::IntoIter { - self.into_buf().iter() +impl PartialEq for Bytes { + fn eq(&self, other: &str) -> bool { + self.as_slice() == other.as_bytes() } } -impl<'a> IntoIterator for &'a Bytes { - type Item = u8; - type IntoIter = Iter>; - - fn into_iter(self) -> Self::IntoIter { - self.into_buf().iter() +impl PartialOrd for Bytes { + fn partial_cmp(&self, other: &str) -> Option { + self.as_slice().partial_cmp(other.as_bytes()) } } -impl Extend for Bytes { - fn extend(&mut self, iter: T) where T: IntoIterator { - let iter = iter.into_iter(); - - let (lower, upper) = iter.size_hint(); - - // Avoid possible conversion into mut if there's nothing to add - if let Some(0) = upper { - return; - } - - let mut bytes_mut = match mem::replace(self, Bytes::new()).try_mut() { - Ok(bytes_mut) => bytes_mut, - Err(bytes) => { - let mut bytes_mut = BytesMut::with_capacity(bytes.len() + lower); - bytes_mut.put_slice(&bytes); - bytes_mut - } - }; - - bytes_mut.extend(iter); - - mem::replace(self, bytes_mut.freeze()); +impl PartialEq for str { + fn eq(&self, other: &Bytes) -> bool { + *other == *self } } -impl<'a> Extend<&'a u8> for Bytes { - fn extend(&mut self, iter: T) where T: IntoIterator { - self.extend(iter.into_iter().map(|b| *b)) - } -} - -/* - * - * ===== BytesMut ===== - * - */ - -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::() - 1`, - /// then `BytesMut` will not allocate. - /// - /// It is important to note that this function does not specify the length - /// of the returned `BytesMut`, but only the capacity. - /// - /// # Examples - /// - /// ``` - /// use bytes::{BytesMut, BufMut}; - /// - /// let mut bytes = BytesMut::with_capacity(64); - /// - /// // `bytes` contains no data, even though there is capacity - /// assert_eq!(bytes.len(), 0); - /// - /// bytes.put(&b"hello world"[..]); - /// - /// assert_eq!(&bytes[..], b"hello world"); - /// ``` - #[inline] - pub fn with_capacity(capacity: usize) -> BytesMut { - BytesMut { - inner: Inner::with_capacity(capacity), - } - } - - /// Creates a new `BytesMut` with default capacity. - /// - /// Resulting object has length 0 and unspecified capacity. - /// This function does not allocate. - /// - /// # Examples - /// - /// ``` - /// use bytes::{BytesMut, BufMut}; - /// - /// let mut bytes = BytesMut::new(); - /// - /// assert_eq!(0, bytes.len()); - /// - /// bytes.reserve(2); - /// bytes.put_slice(b"xy"); - /// - /// assert_eq!(&b"xy"[..], &bytes[..]); - /// ``` - #[inline] - pub fn new() -> BytesMut { - BytesMut::with_capacity(0) - } - - /// Returns the number of bytes contained in this `BytesMut`. - /// - /// # Examples - /// - /// ``` - /// use bytes::BytesMut; - /// - /// let b = BytesMut::from(&b"hello"[..]); - /// assert_eq!(b.len(), 5); - /// ``` - #[inline] - pub fn len(&self) -> usize { - self.inner.len() - } - - /// Returns true if the `BytesMut` has a length of 0. - /// - /// # Examples - /// - /// ``` - /// use bytes::BytesMut; - /// - /// let b = BytesMut::with_capacity(64); - /// assert!(b.is_empty()); - /// ``` - #[inline] - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// Returns the number of bytes the `BytesMut` can hold without reallocating. - /// - /// # Examples - /// - /// ``` - /// use bytes::BytesMut; - /// - /// let b = BytesMut::with_capacity(64); - /// assert_eq!(b.capacity(), 64); - /// ``` - #[inline] - pub fn capacity(&self) -> usize { - self.inner.capacity() - } - - /// Converts `self` into an immutable `Bytes`. - /// - /// The conversion is zero cost and is used to indicate that the slice - /// referenced by the handle will no longer be mutated. Once the conversion - /// is done, the handle can be cloned and shared across threads. - /// - /// # Examples - /// - /// ``` - /// use bytes::{BytesMut, BufMut}; - /// use std::thread; - /// - /// let mut b = BytesMut::with_capacity(64); - /// b.put("hello world"); - /// let b1 = b.freeze(); - /// let b2 = b1.clone(); - /// - /// let th = thread::spawn(move || { - /// assert_eq!(&b1[..], b"hello world"); - /// }); - /// - /// assert_eq!(&b2[..], b"hello world"); - /// th.join().unwrap(); - /// ``` - #[inline] - pub fn freeze(self) -> Bytes { - Bytes { inner: self.inner } - } - - /// Splits the bytes into two at the given index. - /// - /// Afterwards `self` contains elements `[0, at)`, and the returned - /// `BytesMut` contains elements `[at, capacity)`. - /// - /// This is an `O(1)` operation that just increases the reference count - /// and sets a few indices. - /// - /// # Examples - /// - /// ``` - /// use bytes::BytesMut; - /// - /// let mut a = BytesMut::from(&b"hello world"[..]); - /// let mut b = a.split_off(5); - /// - /// a[0] = b'j'; - /// b[0] = b'!'; - /// - /// assert_eq!(&a[..], b"jello"); - /// assert_eq!(&b[..], b"!world"); - /// ``` - /// - /// # Panics - /// - /// Panics if `at > capacity`. - pub fn split_off(&mut self, at: usize) -> BytesMut { - BytesMut { - inner: self.inner.split_off(at), - } - } - - /// Removes the bytes from the current view, returning them in a new - /// `BytesMut` handle. - /// - /// Afterwards, `self` will be empty, but will retain any additional - /// capacity that it had before the operation. This is identical to - /// `self.split_to(self.len())`. - /// - /// This is an `O(1)` operation that just increases the reference count and - /// sets a few indices. - /// - /// # Examples - /// - /// ``` - /// use bytes::{BytesMut, BufMut}; - /// - /// let mut buf = BytesMut::with_capacity(1024); - /// buf.put(&b"hello world"[..]); - /// - /// let other = buf.take(); - /// - /// assert!(buf.is_empty()); - /// assert_eq!(1013, buf.capacity()); - /// - /// assert_eq!(other, b"hello world"[..]); - /// ``` - pub fn take(&mut self) -> BytesMut { - let len = self.len(); - self.split_to(len) - } - - #[deprecated(since = "0.4.1", note = "use take instead")] - #[doc(hidden)] - pub fn drain(&mut self) -> BytesMut { - self.take() - } - - /// Splits the buffer into two at the given index. - /// - /// Afterwards `self` contains elements `[at, len)`, and the returned `BytesMut` - /// contains elements `[0, at)`. - /// - /// This is an `O(1)` operation that just increases the reference count and - /// sets a few indices. - /// - /// # Examples - /// - /// ``` - /// use bytes::BytesMut; - /// - /// let mut a = BytesMut::from(&b"hello world"[..]); - /// let mut b = a.split_to(5); - /// - /// a[0] = b'!'; - /// b[0] = b'j'; - /// - /// assert_eq!(&a[..], b"!world"); - /// assert_eq!(&b[..], b"jello"); - /// ``` - /// - /// # Panics - /// - /// Panics if `at > len`. - pub fn split_to(&mut self, at: usize) -> BytesMut { - BytesMut { - inner: self.inner.split_to(at), - } - } - - #[deprecated(since = "0.4.1", note = "use split_to instead")] - #[doc(hidden)] - pub fn drain_to(&mut self, at: usize) -> BytesMut { - self.split_to(at) - } - - /// Shortens the buffer, keeping the first `len` bytes and dropping the - /// rest. - /// - /// If `len` is greater than the buffer's current length, this has no - /// effect. - /// - /// The [`split_off`] method can emulate `truncate`, but this causes the - /// excess bytes to be returned instead of dropped. - /// - /// # Examples - /// - /// ``` - /// use bytes::BytesMut; - /// - /// let mut buf = BytesMut::from(&b"hello world"[..]); - /// buf.truncate(5); - /// assert_eq!(buf, b"hello"[..]); - /// ``` - /// - /// [`split_off`]: #method.split_off - pub fn truncate(&mut self, len: usize) { - self.inner.truncate(len); - } - - /// Shortens the buffer, dropping the first `cnt` bytes and keeping the - /// rest. - /// - /// This is the same function as `Buf::advance`, and in the next breaking - /// release of `bytes`, this implementation will be removed in favor of - /// having `BytesMut` implement `Buf`. - /// - /// # Panics - /// - /// This function panics if `cnt` is greater than `self.len()` - #[inline] - pub fn advance(&mut self, cnt: usize) { - assert!(cnt <= self.len(), "cannot advance past `remaining`"); - unsafe { self.inner.set_start(cnt); } - } - - /// Clears the buffer, removing all data. - /// - /// # Examples - /// - /// ``` - /// use bytes::BytesMut; - /// - /// let mut buf = BytesMut::from(&b"hello world"[..]); - /// buf.clear(); - /// assert!(buf.is_empty()); - /// ``` - pub fn clear(&mut self) { - self.truncate(0); - } - - /// Resizes the buffer so that `len` is equal to `new_len`. - /// - /// If `new_len` is greater than `len`, the buffer is extended by the - /// difference with each additional byte set to `value`. If `new_len` is - /// less than `len`, the buffer is simply truncated. - /// - /// # Examples - /// - /// ``` - /// use bytes::BytesMut; - /// - /// let mut buf = BytesMut::new(); - /// - /// buf.resize(3, 0x1); - /// assert_eq!(&buf[..], &[0x1, 0x1, 0x1]); - /// - /// buf.resize(2, 0x2); - /// assert_eq!(&buf[..], &[0x1, 0x1]); - /// - /// buf.resize(4, 0x3); - /// assert_eq!(&buf[..], &[0x1, 0x1, 0x3, 0x3]); - /// ``` - pub fn resize(&mut self, new_len: usize, value: u8) { - self.inner.resize(new_len, value); - } - - /// Sets the length of the buffer. - /// - /// This will explicitly set the size of the buffer without actually - /// modifying the data, so it is up to the caller to ensure that the data - /// has been initialized. - /// - /// # Examples - /// - /// ``` - /// use bytes::BytesMut; - /// - /// let mut b = BytesMut::from(&b"hello world"[..]); - /// - /// unsafe { - /// b.set_len(5); - /// } - /// - /// assert_eq!(&b[..], b"hello"); - /// - /// unsafe { - /// b.set_len(11); - /// } - /// - /// assert_eq!(&b[..], b"hello world"); - /// ``` - /// - /// # Panics - /// - /// This method will panic if `len` is out of bounds for the underlying - /// slice or if it comes after the `end` of the configured window. - pub unsafe fn set_len(&mut self, len: usize) { - self.inner.set_len(len) - } - - /// Reserves capacity for at least `additional` more bytes to be inserted - /// into the given `BytesMut`. - /// - /// More than `additional` bytes may be reserved in order to avoid frequent - /// reallocations. A call to `reserve` may result in an allocation. - /// - /// Before allocating new buffer space, the function will attempt to reclaim - /// space in the existing buffer. If the current handle references a small - /// view in the original buffer and all other handles have been dropped, - /// and the requested capacity is less than or equal to the existing - /// buffer's capacity, then the current view will be copied to the front of - /// the buffer and the handle will take ownership of the full buffer. - /// - /// # Examples - /// - /// In the following example, a new buffer is allocated. - /// - /// ``` - /// use bytes::BytesMut; - /// - /// let mut buf = BytesMut::from(&b"hello"[..]); - /// buf.reserve(64); - /// assert!(buf.capacity() >= 69); - /// ``` - /// - /// In the following example, the existing buffer is reclaimed. - /// - /// ``` - /// use bytes::{BytesMut, BufMut}; - /// - /// let mut buf = BytesMut::with_capacity(128); - /// buf.put(&[0; 64][..]); - /// - /// let ptr = buf.as_ptr(); - /// let other = buf.take(); - /// - /// assert!(buf.is_empty()); - /// assert_eq!(buf.capacity(), 64); - /// - /// drop(other); - /// buf.reserve(128); - /// - /// assert_eq!(buf.capacity(), 128); - /// assert_eq!(buf.as_ptr(), ptr); - /// ``` - /// - /// # Panics - /// - /// Panics if the new capacity overflows `usize`. - pub fn reserve(&mut self, additional: usize) { - self.inner.reserve(additional) - } - - /// Appends given bytes to this object. - /// - /// If this `BytesMut` object has not enough capacity, it is resized first. - /// So unlike `put_slice` operation, `extend_from_slice` does not panic. - /// - /// # Examples - /// - /// ``` - /// use bytes::BytesMut; - /// - /// let mut buf = BytesMut::with_capacity(0); - /// buf.extend_from_slice(b"aaabbb"); - /// buf.extend_from_slice(b"cccddd"); - /// - /// assert_eq!(b"aaabbbcccddd", &buf[..]); - /// ``` - pub fn extend_from_slice(&mut self, extend: &[u8]) { - self.reserve(extend.len()); - self.put_slice(extend); - } - - /// Combine splitted BytesMut objects back as contiguous. - /// - /// If `BytesMut` objects were not contiguous originally, they will be extended. - /// - /// # Examples - /// - /// ``` - /// use bytes::BytesMut; - /// - /// let mut buf = BytesMut::with_capacity(64); - /// buf.extend_from_slice(b"aaabbbcccddd"); - /// - /// let splitted = buf.split_off(6); - /// assert_eq!(b"aaabbb", &buf[..]); - /// assert_eq!(b"cccddd", &splitted[..]); - /// - /// buf.unsplit(splitted); - /// assert_eq!(b"aaabbbcccddd", &buf[..]); - /// ``` - pub fn unsplit(&mut self, other: BytesMut) { - let ptr; - - if other.is_empty() { - return; - } - - if self.is_empty() { - *self = other; - return; - } - - unsafe { - ptr = self.inner.ptr.offset(self.inner.len as isize); - } - if ptr == other.inner.ptr && - self.inner.kind() == KIND_ARC && - other.inner.kind() == KIND_ARC - { - debug_assert_eq!(self.inner.arc.load(Acquire), - other.inner.arc.load(Acquire)); - // Contiguous blocks, just combine directly - self.inner.len += other.inner.len; - self.inner.cap += other.inner.cap; - } - else { - self.extend_from_slice(&other); - } - } -} - -impl BufMut for BytesMut { - #[inline] - fn remaining_mut(&self) -> usize { - self.capacity() - self.len() - } - - #[inline] - unsafe fn advance_mut(&mut self, cnt: usize) { - let new_len = self.len() + cnt; - - // This call will panic if `cnt` is too big - self.inner.set_len(new_len); - } - - #[inline] - unsafe fn bytes_mut(&mut self) -> &mut [u8] { - let len = self.len(); - - // This will never panic as `len` can never become invalid - &mut self.inner.as_raw()[len..] - } - - #[inline] - fn put_slice(&mut self, src: &[u8]) { - assert!(self.remaining_mut() >= src.len()); - - let len = src.len(); - - unsafe { - self.bytes_mut()[..len].copy_from_slice(src); - self.advance_mut(len); - } - } - - #[inline] - fn put_u8(&mut self, n: u8) { - self.inner.put_u8(n); - } - - #[inline] - fn put_i8(&mut self, n: i8) { - self.put_u8(n as u8); - } -} - -impl IntoBuf for BytesMut { - type Buf = Cursor; - - fn into_buf(self) -> Self::Buf { - Cursor::new(self) - } -} - -impl<'a> IntoBuf for &'a BytesMut { - type Buf = Cursor<&'a BytesMut>; - - fn into_buf(self) -> Self::Buf { - Cursor::new(self) - } -} - -impl AsRef<[u8]> for BytesMut { - #[inline] - fn as_ref(&self) -> &[u8] { - self.inner.as_ref() - } -} - -impl ops::Deref for BytesMut { - type Target = [u8]; - - #[inline] - fn deref(&self) -> &[u8] { - self.as_ref() - } -} - -impl AsMut<[u8]> for BytesMut { - fn as_mut(&mut self) -> &mut [u8] { - self.inner.as_mut() - } -} - -impl ops::DerefMut for BytesMut { - #[inline] - fn deref_mut(&mut self) -> &mut [u8] { - self.inner.as_mut() - } -} - -impl From> for BytesMut { - fn from(src: Vec) -> BytesMut { - BytesMut { - inner: Inner::from_vec(src), - } - } -} - -impl From for BytesMut { - fn from(src: String) -> BytesMut { - BytesMut::from(src.into_bytes()) - } -} - -impl<'a> From<&'a [u8]> for BytesMut { - fn from(src: &'a [u8]) -> BytesMut { - let len = src.len(); - - if len == 0 { - BytesMut::new() - } else if len <= INLINE_CAP { - unsafe { - let mut inner: Inner = mem::uninitialized(); - - // Set inline mask - inner.arc = AtomicPtr::new(KIND_INLINE as *mut Shared); - inner.set_inline_len(len); - inner.as_raw()[0..len].copy_from_slice(src); - - BytesMut { - inner: inner, - } - } - } else { - BytesMut::from(src.to_vec()) - } - } -} - -impl<'a> From<&'a str> for BytesMut { - fn from(src: &'a str) -> BytesMut { - BytesMut::from(src.as_bytes()) - } -} - -impl From for BytesMut { - fn from(src: Bytes) -> BytesMut { - src.try_mut() - .unwrap_or_else(|src| BytesMut::from(&src[..])) - } -} - -impl PartialEq for BytesMut { - fn eq(&self, other: &BytesMut) -> bool { - self.inner.as_ref() == other.inner.as_ref() - } -} - -impl PartialOrd for BytesMut { - fn partial_cmp(&self, other: &BytesMut) -> Option { - self.inner.as_ref().partial_cmp(other.inner.as_ref()) - } -} - -impl Ord for BytesMut { - fn cmp(&self, other: &BytesMut) -> cmp::Ordering { - self.inner.as_ref().cmp(other.inner.as_ref()) - } -} - -impl Eq for BytesMut { -} - -impl Default for BytesMut { - #[inline] - fn default() -> BytesMut { - BytesMut::new() - } -} - -impl fmt::Debug for BytesMut { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&debug::BsDebug(&self.inner.as_ref()), fmt) - } -} - -impl hash::Hash for BytesMut { - fn hash(&self, state: &mut H) where H: hash::Hasher { - let s: &[u8] = self.as_ref(); - s.hash(state); - } -} - -impl Borrow<[u8]> for BytesMut { - fn borrow(&self) -> &[u8] { - self.as_ref() - } -} - -impl BorrowMut<[u8]> for BytesMut { - fn borrow_mut(&mut self) -> &mut [u8] { - self.as_mut() - } -} - -impl fmt::Write for BytesMut { - #[inline] - fn write_str(&mut self, s: &str) -> fmt::Result { - if self.remaining_mut() >= s.len() { - self.put_slice(s.as_bytes()); - Ok(()) - } else { - Err(fmt::Error) - } - } - - #[inline] - fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result { - fmt::write(self, args) - } -} - -impl Clone for BytesMut { - fn clone(&self) -> BytesMut { - BytesMut::from(&self[..]) - } -} - -impl IntoIterator for BytesMut { - type Item = u8; - type IntoIter = Iter>; - - fn into_iter(self) -> Self::IntoIter { - self.into_buf().iter() - } -} - -impl<'a> IntoIterator for &'a BytesMut { - type Item = u8; - type IntoIter = Iter>; - - fn into_iter(self) -> Self::IntoIter { - self.into_buf().iter() - } -} - -impl Extend for BytesMut { - fn extend(&mut self, iter: T) where T: IntoIterator { - let iter = iter.into_iter(); - - let (lower, _) = iter.size_hint(); - self.reserve(lower); - - for b in iter { - unsafe { - self.bytes_mut()[0] = b; - self.advance_mut(1); - } - } - } -} - -impl<'a> Extend<&'a u8> for BytesMut { - fn extend(&mut self, iter: T) where T: IntoIterator { - self.extend(iter.into_iter().map(|b| *b)) - } -} - -/* - * - * ===== Inner ===== - * - */ - -impl Inner { - #[inline] - fn from_static(bytes: &'static [u8]) -> Inner { - let ptr = bytes.as_ptr() as *mut u8; - - Inner { - // `arc` won't ever store a pointer. Instead, use it to - // track the fact that the `Bytes` handle is backed by a - // static buffer. - arc: AtomicPtr::new(KIND_STATIC as *mut Shared), - ptr: ptr, - len: bytes.len(), - cap: bytes.len(), - } - } - - #[inline] - fn from_vec(mut src: Vec) -> Inner { - let len = src.len(); - let cap = src.capacity(); - let ptr = src.as_mut_ptr(); - - mem::forget(src); - - let original_capacity_repr = original_capacity_to_repr(cap); - let arc = (original_capacity_repr << ORIGINAL_CAPACITY_OFFSET) | KIND_VEC; - - Inner { - arc: AtomicPtr::new(arc as *mut Shared), - ptr: ptr, - len: len, - cap: cap, - } - } - - #[inline] - fn with_capacity(capacity: usize) -> Inner { - if capacity <= INLINE_CAP { - unsafe { - // Using uninitialized memory is ~30% faster - let mut inner: Inner = mem::uninitialized(); - inner.arc = AtomicPtr::new(KIND_INLINE as *mut Shared); - inner - } - } else { - Inner::from_vec(Vec::with_capacity(capacity)) - } - } - - /// Return a slice for the handle's view into the shared buffer - #[inline] - fn as_ref(&self) -> &[u8] { - unsafe { - if self.is_inline() { - slice::from_raw_parts(self.inline_ptr(), self.inline_len()) - } else { - slice::from_raw_parts(self.ptr, self.len) - } - } - } - - /// Return a mutable slice for the handle's view into the shared buffer - #[inline] - fn as_mut(&mut self) -> &mut [u8] { - debug_assert!(!self.is_static()); - - unsafe { - if self.is_inline() { - slice::from_raw_parts_mut(self.inline_ptr(), self.inline_len()) - } else { - slice::from_raw_parts_mut(self.ptr, self.len) - } - } - } - - /// Return a mutable slice for the handle's view into the shared buffer - /// including potentially uninitialized bytes. - #[inline] - unsafe fn as_raw(&mut self) -> &mut [u8] { - debug_assert!(!self.is_static()); - - if self.is_inline() { - slice::from_raw_parts_mut(self.inline_ptr(), INLINE_CAP) - } else { - slice::from_raw_parts_mut(self.ptr, self.cap) - } - } - - /// Insert a byte into the next slot and advance the len by 1. - #[inline] - fn put_u8(&mut self, n: u8) { - if self.is_inline() { - let len = self.inline_len(); - assert!(len < INLINE_CAP); - unsafe { - *self.inline_ptr().offset(len as isize) = n; - } - self.set_inline_len(len + 1); - } else { - assert!(self.len < self.cap); - unsafe { - *self.ptr.offset(self.len as isize) = n; - } - self.len += 1; - } - } - - #[inline] - fn len(&self) -> usize { - if self.is_inline() { - self.inline_len() - } else { - self.len - } - } - - /// Pointer to the start of the inline buffer - #[inline] - unsafe fn inline_ptr(&self) -> *mut u8 { - (self as *const Inner as *mut Inner as *mut u8) - .offset(INLINE_DATA_OFFSET) - } - - #[inline] - fn inline_len(&self) -> usize { - let p: &usize = unsafe { mem::transmute(&self.arc) }; - (p & INLINE_LEN_MASK) >> INLINE_LEN_OFFSET - } - - /// Set the length of the inline buffer. This is done by writing to the - /// least significant byte of the `arc` field. - #[inline] - fn set_inline_len(&mut self, len: usize) { - debug_assert!(len <= INLINE_CAP); - let p = self.arc.get_mut(); - *p = ((*p as usize & !INLINE_LEN_MASK) | (len << INLINE_LEN_OFFSET)) as _; - } - - /// slice. - #[inline] - unsafe fn set_len(&mut self, len: usize) { - if self.is_inline() { - assert!(len <= INLINE_CAP); - self.set_inline_len(len); - } else { - assert!(len <= self.cap); - self.len = len; - } - } - - #[inline] - fn is_empty(&self) -> bool { - self.len() == 0 - } - - #[inline] - fn capacity(&self) -> usize { - if self.is_inline() { - INLINE_CAP - } else { - self.cap - } - } - - fn split_off(&mut self, at: usize) -> Inner { - let mut other = unsafe { self.shallow_clone(true) }; - - unsafe { - other.set_start(at); - self.set_end(at); - } - - return other - } - - fn split_to(&mut self, at: usize) -> Inner { - let mut other = unsafe { self.shallow_clone(true) }; - - unsafe { - other.set_end(at); - self.set_start(at); - } - - return other - } - - fn truncate(&mut self, len: usize) { - if len <= self.len() { - unsafe { self.set_len(len); } - } - } - - fn resize(&mut self, new_len: usize, value: u8) { - let len = self.len(); - if new_len > len { - let additional = new_len - len; - self.reserve(additional); - unsafe { - let dst = self.as_raw()[len..].as_mut_ptr(); - ptr::write_bytes(dst, value, additional); - self.set_len(new_len); - } - } else { - self.truncate(new_len); - } - } - - unsafe fn set_start(&mut self, start: usize) { - // Setting the start to 0 is a no-op, so return early if this is the - // case. - if start == 0 { - return; - } - - let kind = self.kind(); - - // Always check `inline` first, because if the handle is using inline - // data storage, all of the `Inner` struct fields will be gibberish. - if kind == KIND_INLINE { - assert!(start <= INLINE_CAP); - - let len = self.inline_len(); - - if len <= start { - self.set_inline_len(0); - } else { - // `set_start` is essentially shifting data off the front of the - // view. Inlined buffers only track the length of the slice. - // So, to update the start, the data at the new starting point - // is copied to the beginning of the buffer. - let new_len = len - start; - - let dst = self.inline_ptr(); - let src = (dst as *const u8).offset(start as isize); - - ptr::copy(src, dst, new_len); - - self.set_inline_len(new_len); - } - } else { - assert!(start <= self.cap); - - if kind == KIND_VEC { - // Setting the start when in vec representation is a little more - // complicated. First, we have to track how far ahead the - // "start" of the byte buffer from the beginning of the vec. We - // also have to ensure that we don't exceed the maximum shift. - let (mut pos, prev) = self.uncoordinated_get_vec_pos(); - pos += start; - - if pos <= MAX_VEC_POS { - self.uncoordinated_set_vec_pos(pos, prev); - } else { - // The repr must be upgraded to ARC. This will never happen - // 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. - let _ = self.shallow_clone(true); - } - } - - // Updating the start of the view is setting `ptr` to point to the - // new start and updating the `len` field to reflect the new length - // of the view. - self.ptr = self.ptr.offset(start as isize); - - if self.len >= start { - self.len -= start; - } else { - self.len = 0; - } - - self.cap -= start; - } - } - - unsafe fn set_end(&mut self, end: usize) { - debug_assert!(self.is_shared()); - - // Always check `inline` first, because if the handle is using inline - // data storage, all of the `Inner` struct fields will be gibberish. - if self.is_inline() { - assert!(end <= INLINE_CAP); - let new_len = cmp::min(self.inline_len(), end); - self.set_inline_len(new_len); - } else { - assert!(end <= self.cap); - - self.cap = end; - self.len = cmp::min(self.len, end); - } - } - - /// Checks if it is safe to mutate the memory - fn is_mut_safe(&mut self) -> bool { - let kind = self.kind(); - - // Always check `inline` first, because if the handle is using inline - // data storage, all of the `Inner` struct fields will be gibberish. - if kind == KIND_INLINE { - // Inlined buffers can always be mutated as the data is never shared - // across handles. - true - } else if kind == KIND_VEC { - true - } else if kind == KIND_STATIC { - false - } else { - // Otherwise, the underlying buffer is potentially shared with other - // handles, so the ref_count needs to be checked. - unsafe { (**self.arc.get_mut()).is_unique() } - } - } - - /// Increments the ref count. This should only be done if it is known that - /// it can be done safely. As such, this fn is not public, instead other - /// fns will use this one while maintaining the guarantees. - /// Parameter `mut_self` should only be set to `true` if caller holds - /// `&mut self` reference. - /// - /// "Safely" is defined as not exposing two `BytesMut` values that point to - /// the same byte window. - /// - /// This function is thread safe. - unsafe fn shallow_clone(&self, mut_self: bool) -> Inner { - // Always check `inline` first, because if the handle is using inline - // data storage, all of the `Inner` struct fields will be gibberish. - // - // Additionally, if kind is STATIC, then Arc is *never* changed, making - // it safe and faster to check for it now before an atomic acquire. - - if self.is_inline_or_static() { - // In this case, a shallow_clone still involves copying the data. - let mut inner: Inner = mem::uninitialized(); - ptr::copy_nonoverlapping( - self, - &mut inner, - 1, - ); - inner - } else { - self.shallow_clone_sync(mut_self) - } - } - - - #[cold] - unsafe fn shallow_clone_sync(&self, mut_self: bool) -> Inner { - // The function requires `&self`, this means that `shallow_clone` - // could be called concurrently. - // - // The first step is to load the value of `arc`. This will determine - // how to proceed. The `Acquire` ordering synchronizes with the - // `compare_and_swap` that comes later in this function. The goal is - // to ensure that if `arc` is currently set to point to a `Shared`, - // that the current thread acquires the associated memory. - let arc = self.arc.load(Acquire); - let kind = arc as usize & KIND_MASK; - - if kind == KIND_ARC { - self.shallow_clone_arc(arc) - } else { - assert!(kind == KIND_VEC); - self.shallow_clone_vec(arc as usize, mut_self) - } - } - - unsafe fn shallow_clone_arc(&self, arc: *mut Shared) -> Inner { - debug_assert!(arc as usize & KIND_MASK == KIND_ARC); - - let old_size = (*arc).ref_count.fetch_add(1, Relaxed); - - if old_size == usize::MAX { - abort(); - } - - Inner { - arc: AtomicPtr::new(arc), - .. *self - } - } - - #[cold] - unsafe fn shallow_clone_vec(&self, arc: usize, mut_self: bool) -> Inner { - // If the buffer is still tracked in a `Vec`. It is time to - // promote the vec to an `Arc`. This could potentially be called - // concurrently, so some care must be taken. - - debug_assert!(arc & KIND_MASK == KIND_VEC); - - let original_capacity_repr = - (arc as usize & ORIGINAL_CAPACITY_MASK) >> ORIGINAL_CAPACITY_OFFSET; - - // The vec offset cannot be concurrently mutated, so there - // should be no danger reading it. - let off = (arc as usize) >> VEC_POS_OFFSET; - - // 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`. - // This means that these fields will not be concurrently - // updated and since the buffer hasn't been promoted to an - // `Arc`, those three fields still are the components of the - // vector. - let shared = Box::new(Shared { - vec: rebuild_vec(self.ptr, self.len, self.cap, off), - original_capacity_repr: original_capacity_repr, - // Initialize refcount to 2. One for this reference, and one - // for the new clone that will be returned from - // `shallow_clone`. - ref_count: AtomicUsize::new(2), - }); - - let shared = Box::into_raw(shared); - - // The pointer should be aligned, so this assert should - // always succeed. - debug_assert!(0 == (shared as usize & 0b11)); - - // If there are no references to self in other threads, - // expensive atomic operations can be avoided. - if mut_self { - self.arc.store(shared, Relaxed); - return Inner { - arc: AtomicPtr::new(shared), - .. *self - }; - } - - // Try compare & swapping the pointer into the `arc` field. - // `Release` is used synchronize with other threads that - // will load the `arc` field. - // - // If the `compare_and_swap` fails, then the thread lost the - // race to promote the buffer to shared. The `Acquire` - // ordering will synchronize with the `compare_and_swap` - // that happened in the other thread and the `Shared` - // pointed to by `actual` will be visible. - let actual = self.arc.compare_and_swap(arc as *mut Shared, shared, AcqRel); - - if actual as usize == arc { - // The upgrade was successful, the new handle can be - // returned. - return Inner { - arc: AtomicPtr::new(shared), - .. *self - }; - } - - // The upgrade failed, a concurrent clone happened. Release - // the allocation that was made in this thread, it will not - // be needed. - let shared = Box::from_raw(shared); - mem::forget(*shared); - - // Buffer already promoted to shared storage, so increment ref - // count. - self.shallow_clone_arc(actual) - } - - #[inline] - fn reserve(&mut self, additional: usize) { - let len = self.len(); - let rem = self.capacity() - len; - - if additional <= rem { - // The handle can already store at least `additional` more bytes, so - // there is no further work needed to be done. - return; - } - - let kind = self.kind(); - - // Always check `inline` first, because if the handle is using inline - // data storage, all of the `Inner` struct fields will be gibberish. - if kind == KIND_INLINE { - let new_cap = len + additional; - - // Promote to a vector - let mut v = Vec::with_capacity(new_cap); - v.extend_from_slice(self.as_ref()); - - self.ptr = v.as_mut_ptr(); - self.len = v.len(); - self.cap = v.capacity(); - - // Since the minimum capacity is `INLINE_CAP`, don't bother encoding - // the original capacity as INLINE_CAP - self.arc = AtomicPtr::new(KIND_VEC as *mut Shared); - - mem::forget(v); - return; - } - - if kind == KIND_VEC { - // If there's enough free space before the start of the buffer, then - // just copy the data backwards and reuse the already-allocated - // space. - // - // Otherwise, since backed by a vector, use `Vec::reserve` - unsafe { - let (off, prev) = self.uncoordinated_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) { - // There's space - reuse it - // - // Just move the pointer back to the start after copying - // data back. - let base_ptr = self.ptr.offset(-(off as isize)); - ptr::copy(self.ptr, base_ptr, self.len); - self.ptr = base_ptr; - self.uncoordinated_set_vec_pos(0, prev); - - // Length stays constant, but since we moved backwards we - // can gain capacity back. - self.cap += off; - } else { - // No space - allocate more - let mut v = rebuild_vec(self.ptr, self.len, self.cap, off); - v.reserve(additional); - - // Update the info - self.ptr = v.as_mut_ptr().offset(off as isize); - self.len = v.len() - off; - self.cap = v.capacity() - off; - - // Drop the vec reference - mem::forget(v); - } - return; - } - } - - let arc = *self.arc.get_mut(); - - debug_assert!(kind == KIND_ARC); - - // Reserving involves abandoning the currently shared buffer and - // allocating a new vector with the requested capacity. - // - // Compute the new capacity - let mut new_cap = len + additional; - let original_capacity; - let original_capacity_repr; - - unsafe { - original_capacity_repr = (*arc).original_capacity_repr; - original_capacity = original_capacity_from_repr(original_capacity_repr); - - // First, try to reclaim the buffer. This is possible if the current - // handle is the only outstanding handle pointing to the buffer. - if (*arc).is_unique() { - // This is the only handle to the buffer. It can be reclaimed. - // However, before doing the work of copying data, check to make - // sure that the vector has enough capacity. - let v = &mut (*arc).vec; - - if v.capacity() >= new_cap { - // The capacity is sufficient, reclaim the buffer - let ptr = v.as_mut_ptr(); - - ptr::copy(self.ptr, ptr, len); - - self.ptr = ptr; - self.cap = v.capacity(); - - return; - } - - // The vector capacity is not sufficient. The reserve request is - // asking for more than the initial buffer capacity. Allocate more - // than requested if `new_cap` is not much bigger than the current - // capacity. - // - // There are some situations, using `reserve_exact` that the - // buffer capacity could be below `original_capacity`, so do a - // check. - new_cap = cmp::max( - cmp::max(v.capacity() << 1, new_cap), - original_capacity); - } else { - new_cap = cmp::max(new_cap, original_capacity); - } - } - - // Create a new vector to store the data - let mut v = Vec::with_capacity(new_cap); - - // Copy the bytes - v.extend_from_slice(self.as_ref()); - - // Release the shared handle. This must be done *after* the bytes are - // copied. - release_shared(arc); - - // Update self - self.ptr = v.as_mut_ptr(); - self.len = v.len(); - self.cap = v.capacity(); - - let arc = (original_capacity_repr << ORIGINAL_CAPACITY_OFFSET) | KIND_VEC; - - self.arc = AtomicPtr::new(arc as *mut Shared); - - // Forget the vector handle - mem::forget(v); - } - - /// Returns true if the buffer is stored inline - #[inline] - fn is_inline(&self) -> bool { - self.kind() == KIND_INLINE - } - - #[inline] - fn is_inline_or_static(&self) -> bool { - // The value returned by `kind` isn't itself safe, but the value could - // inform what operations to take, and unsafely do something without - // synchronization. - // - // KIND_INLINE and KIND_STATIC will *never* change, so branches on that - // information is safe. - let kind = self.kind(); - kind == KIND_INLINE || kind == KIND_STATIC - } - - /// Used for `debug_assert` statements. &mut is used to guarantee that it is - /// safe to check VEC_KIND - #[inline] - fn is_shared(&mut self) -> bool { - match self.kind() { - KIND_VEC => false, - _ => true, - } - } - - /// Used for `debug_assert` statements - #[inline] - fn is_static(&mut self) -> bool { - match self.kind() { - KIND_STATIC => true, - _ => false, - } - } - - #[inline] - fn kind(&self) -> usize { - // This function is going to probably raise some eyebrows. The function - // returns true if the buffer is stored inline. This is done by checking - // the least significant bit in the `arc` field. - // - // Now, you may notice that `arc` is an `AtomicPtr` and this is - // accessing it as a normal field without performing an atomic load... - // - // Again, the function only cares about the least significant bit, and - // this bit is set when `Inner` is created and never changed after that. - // All platforms have atomic "word" operations and won't randomly flip - // 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% - // slowdown using a `Relaxed` atomic load on x86. - - #[cfg(target_endian = "little")] - #[inline] - fn imp(arc: &AtomicPtr) -> usize { - unsafe { - let p: *const u8 = mem::transmute(arc); - (*p as usize) & KIND_MASK - } - } - - #[cfg(target_endian = "big")] - #[inline] - fn imp(arc: &AtomicPtr) -> usize { - unsafe { - let p: *const usize = mem::transmute(arc); - *p & KIND_MASK - } - } - - imp(&self.arc) - } - - #[inline] - fn uncoordinated_get_vec_pos(&mut self) -> (usize, usize) { - // Similar to above, this is a pretty crazed function. This should only - // be called when in the KIND_VEC mode. This + the &mut self argument - // guarantees that there is no possibility of concurrent calls to this - // function. - let prev = unsafe { - let p: &AtomicPtr = &self.arc; - let p: *const usize = mem::transmute(p); - *p - }; - - (prev >> VEC_POS_OFFSET, prev) - } - - #[inline] - fn uncoordinated_set_vec_pos(&mut self, pos: usize, prev: usize) { - // Once more... crazy - debug_assert!(pos <= MAX_VEC_POS); - - unsafe { - let p: &mut AtomicPtr = &mut self.arc; - let p: &mut usize = mem::transmute(p); - *p = (pos << VEC_POS_OFFSET) | (prev & NOT_VEC_POS_MASK); - } - } -} - -fn rebuild_vec(ptr: *mut u8, mut len: usize, mut cap: usize, off: usize) -> Vec { - unsafe { - let ptr = ptr.offset(-(off as isize)); - len += off; - cap += off; - - Vec::from_raw_parts(ptr, len, cap) - } -} - -impl Drop for Inner { - fn drop(&mut self) { - let kind = self.kind(); - - if kind == KIND_VEC { - let (off, _) = self.uncoordinated_get_vec_pos(); - - // Vector storage, free the vector - let _ = rebuild_vec(self.ptr, self.len, self.cap, off); - } else if kind == KIND_ARC { - release_shared(*self.arc.get_mut()); - } - } -} - -fn release_shared(ptr: *mut Shared) { - // `Shared` storage... follow the drop steps from Arc. - unsafe { - if (*ptr).ref_count.fetch_sub(1, Release) != 1 { - return; - } - - // This fence is needed to prevent reordering of use of the data and - // deletion of the data. Because it is marked `Release`, the decreasing - // of the reference count synchronizes with this `Acquire` fence. This - // means that use of the data happens before decreasing the reference - // count, which happens before this fence, which happens before the - // deletion of the data. - // - // As explained in the [Boost documentation][1], - // - // > It is important to enforce any possible access to the object in one - // > thread (through an existing reference) to *happen before* deleting - // > the object in a different thread. This is achieved by a "release" - // > operation after dropping a reference (any access to the object - // > through this reference must obviously happened before), and an - // > "acquire" operation before deleting the object. - // - // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) - atomic::fence(Acquire); - - // Drop the data - Box::from_raw(ptr); - } -} - -impl Shared { - fn is_unique(&self) -> bool { - // The goal is to check if the current handle is the only handle - // that currently has access to the buffer. This is done by - // checking if the `ref_count` is currently 1. - // - // The `Acquire` ordering synchronizes with the `Release` as - // part of the `fetch_sub` in `release_shared`. The `fetch_sub` - // operation guarantees that any mutations done in other threads - // are ordered before the `ref_count` is decremented. As such, - // this `Acquire` will guarantee that those mutations are - // visible to the current thread. - self.ref_count.load(Acquire) == 1 - } -} - -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) -} - -fn original_capacity_from_repr(repr: usize) -> usize { - if repr == 0 { - return 0; - } - - 1 << (repr + (MIN_ORIGINAL_CAPACITY_WIDTH - 1)) -} - -#[test] -fn test_original_capacity_to_repr() { - 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); - } - - // 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); - } - } -} - -#[test] -fn test_original_capacity_from_repr() { - assert_eq!(0, original_capacity_from_repr(0)); - - 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 {} -unsafe impl Sync for Inner {} - -/* - * - * ===== PartialEq / PartialOrd ===== - * - */ - -impl PartialEq<[u8]> for BytesMut { - fn eq(&self, other: &[u8]) -> bool { - &**self == other - } -} - -impl PartialOrd<[u8]> for BytesMut { - fn partial_cmp(&self, other: &[u8]) -> Option { - (**self).partial_cmp(other) - } -} - -impl PartialEq for [u8] { - fn eq(&self, other: &BytesMut) -> bool { - *other == *self - } -} - -impl PartialOrd for [u8] { - fn partial_cmp(&self, other: &BytesMut) -> Option { - other.partial_cmp(self) +impl PartialOrd for str { + fn partial_cmp(&self, other: &Bytes) -> Option { + <[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other) } } -impl PartialEq for BytesMut { - fn eq(&self, other: &str) -> bool { - &**self == other.as_bytes() +impl PartialEq> for Bytes { + fn eq(&self, other: &Vec) -> bool { + *self == &other[..] } } -impl PartialOrd for BytesMut { - fn partial_cmp(&self, other: &str) -> Option { - (**self).partial_cmp(other.as_bytes()) +impl PartialOrd> for Bytes { + fn partial_cmp(&self, other: &Vec) -> Option { + self.as_slice().partial_cmp(&other[..]) } } -impl PartialEq for str { - fn eq(&self, other: &BytesMut) -> bool { +impl PartialEq for Vec { + fn eq(&self, other: &Bytes) -> bool { *other == *self } } -impl PartialOrd for str { - fn partial_cmp(&self, other: &BytesMut) -> Option { - other.partial_cmp(self) +impl PartialOrd for Vec { + fn partial_cmp(&self, other: &Bytes) -> Option { + <[u8] as PartialOrd<[u8]>>::partial_cmp(self, other) } } -impl PartialEq> for BytesMut { - fn eq(&self, other: &Vec) -> bool { +impl PartialEq for Bytes { + fn eq(&self, other: &String) -> bool { *self == &other[..] } } -impl PartialOrd> for BytesMut { - fn partial_cmp(&self, other: &Vec) -> Option { - (**self).partial_cmp(&other[..]) +impl PartialOrd for Bytes { + fn partial_cmp(&self, other: &String) -> Option { + self.as_slice().partial_cmp(other.as_bytes()) } } -impl PartialEq for Vec { - fn eq(&self, other: &BytesMut) -> bool { +impl PartialEq for String { + fn eq(&self, other: &Bytes) -> bool { *other == *self } } -impl PartialOrd for Vec { - fn partial_cmp(&self, other: &BytesMut) -> Option { - other.partial_cmp(self) +impl PartialOrd for String { + fn partial_cmp(&self, other: &Bytes) -> Option { + <[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other) } } -impl PartialEq for BytesMut { - fn eq(&self, other: &String) -> bool { - *self == &other[..] +impl PartialEq for &[u8] { + fn eq(&self, other: &Bytes) -> bool { + *other == *self } } -impl PartialOrd for BytesMut { - fn partial_cmp(&self, other: &String) -> Option { - (**self).partial_cmp(other.as_bytes()) +impl PartialOrd for &[u8] { + fn partial_cmp(&self, other: &Bytes) -> Option { + <[u8] as PartialOrd<[u8]>>::partial_cmp(self, other) } } -impl PartialEq for String { - fn eq(&self, other: &BytesMut) -> bool { +impl PartialEq for &str { + fn eq(&self, other: &Bytes) -> bool { *other == *self } } -impl PartialOrd for String { - fn partial_cmp(&self, other: &BytesMut) -> Option { - other.partial_cmp(self) +impl PartialOrd for &str { + fn partial_cmp(&self, other: &Bytes) -> Option { + <[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other) } } -impl<'a, T: ?Sized> PartialEq<&'a T> for BytesMut - where BytesMut: PartialEq +impl<'a, T: ?Sized> PartialEq<&'a T> for Bytes +where + Bytes: PartialEq, { fn eq(&self, other: &&'a T) -> bool { *self == **other } } -impl<'a, T: ?Sized> PartialOrd<&'a T> for BytesMut - where BytesMut: PartialOrd +impl<'a, T: ?Sized> PartialOrd<&'a T> for Bytes +where + Bytes: PartialOrd, { fn partial_cmp(&self, other: &&'a T) -> Option { - self.partial_cmp(*other) + self.partial_cmp(&**other) } } -impl<'a> PartialEq for &'a [u8] { - fn eq(&self, other: &BytesMut) -> bool { - *other == *self - } -} +// impl From -impl<'a> PartialOrd for &'a [u8] { - fn partial_cmp(&self, other: &BytesMut) -> Option { - other.partial_cmp(self) +impl Default for Bytes { + #[inline] + fn default() -> Bytes { + Bytes::new() } } -impl<'a> PartialEq for &'a str { - fn eq(&self, other: &BytesMut) -> bool { - *other == *self +impl From<&'static [u8]> for Bytes { + fn from(slice: &'static [u8]) -> Bytes { + Bytes::from_static(slice) } } -impl<'a> PartialOrd for &'a str { - fn partial_cmp(&self, other: &BytesMut) -> Option { - other.partial_cmp(self) +impl From<&'static str> for Bytes { + fn from(slice: &'static str) -> Bytes { + Bytes::from_static(slice.as_bytes()) } } -impl PartialEq<[u8]> for Bytes { - fn eq(&self, other: &[u8]) -> bool { - self.inner.as_ref() == other +impl From> for Bytes { + fn from(vec: Vec) -> Bytes { + let slice = vec.into_boxed_slice(); + slice.into() } } -impl PartialOrd<[u8]> for Bytes { - fn partial_cmp(&self, other: &[u8]) -> Option { - self.inner.as_ref().partial_cmp(other) - } -} +impl From> for Bytes { + fn from(slice: Box<[u8]>) -> Bytes { + // Box<[u8]> doesn't contain a heap allocation for empty slices, + // so the pointer isn't aligned enough for the KIND_VEC stashing to + // work. + if slice.is_empty() { + return Bytes::new(); + } -impl PartialEq for [u8] { - fn eq(&self, other: &Bytes) -> bool { - *other == *self - } -} + let len = slice.len(); + let ptr = Box::into_raw(slice) as *mut u8; -impl PartialOrd for [u8] { - fn partial_cmp(&self, other: &Bytes) -> Option { - other.partial_cmp(self) + if ptr as usize & 0x1 == 0 { + let data = ptr as usize | KIND_VEC; + Bytes { + ptr, + len, + data: AtomicPtr::new(data as *mut _), + vtable: &PROMOTABLE_EVEN_VTABLE, + } + } else { + Bytes { + ptr, + len, + data: AtomicPtr::new(ptr as *mut _), + vtable: &PROMOTABLE_ODD_VTABLE, + } + } } } -impl PartialEq for Bytes { - fn eq(&self, other: &str) -> bool { - self.inner.as_ref() == other.as_bytes() +impl From for Bytes { + fn from(s: String) -> Bytes { + Bytes::from(s.into_bytes()) } } -impl PartialOrd for Bytes { - fn partial_cmp(&self, other: &str) -> Option { - self.inner.as_ref().partial_cmp(other.as_bytes()) - } -} +// ===== impl Vtable ===== -impl PartialEq for str { - fn eq(&self, other: &Bytes) -> bool { - *other == *self +impl fmt::Debug for Vtable { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Vtable") + .field("clone", &(self.clone as *const ())) + .field("drop", &(self.drop as *const ())) + .finish() } } -impl PartialOrd for str { - fn partial_cmp(&self, other: &Bytes) -> Option { - other.partial_cmp(self) - } -} +// ===== impl StaticVtable ===== -impl PartialEq> for Bytes { - fn eq(&self, other: &Vec) -> bool { - *self == &other[..] - } -} +const STATIC_VTABLE: Vtable = Vtable { + clone: static_clone, + drop: static_drop, +}; -impl PartialOrd> for Bytes { - fn partial_cmp(&self, other: &Vec) -> Option { - self.inner.as_ref().partial_cmp(&other[..]) - } +unsafe fn static_clone(_: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes { + let slice = slice::from_raw_parts(ptr, len); + Bytes::from_static(slice) } -impl PartialEq for Vec { - fn eq(&self, other: &Bytes) -> bool { - *other == *self - } +unsafe fn static_drop(_: &mut AtomicPtr<()>, _: *const u8, _: usize) { + // nothing to drop for &'static [u8] } -impl PartialOrd for Vec { - fn partial_cmp(&self, other: &Bytes) -> Option { - other.partial_cmp(self) - } -} +// ===== impl PromotableVtable ===== -impl PartialEq for Bytes { - fn eq(&self, other: &String) -> bool { - *self == &other[..] +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) } } -impl PartialOrd for Bytes { - fn partial_cmp(&self, other: &String) -> Option { - self.inner.as_ref().partial_cmp(other.as_bytes()) - } +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)); + } + }); } -impl PartialEq for String { - fn eq(&self, other: &Bytes) -> bool { - *other == *self +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) } } -impl PartialOrd for String { - fn partial_cmp(&self, other: &Bytes) -> Option { - other.partial_cmp(self) - } +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)); + } + }); } -impl<'a> PartialEq for &'a [u8] { - fn eq(&self, other: &Bytes) -> bool { - *other == *self - } +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<'a> PartialOrd for &'a [u8] { - fn partial_cmp(&self, other: &Bytes) -> Option { - other.partial_cmp(self) - } +// ===== impl SharedVtable ===== + +struct Shared { + // holds vec for drop, but otherwise doesnt access it + _vec: Vec, + ref_cnt: AtomicUsize, } -impl<'a> PartialEq for &'a str { - fn eq(&self, other: &Bytes) -> bool { - *other == *self - } +// 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::() % 2] = []; // Assert that the alignment of `Shared` is divisible by 2. + +static SHARED_VTABLE: Vtable = Vtable { + clone: shared_clone, + drop: shared_drop, +}; + +const KIND_ARC: usize = 0b0; +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::Relaxed); + shallow_clone_arc(shared as _, ptr, len) } -impl<'a> PartialOrd for &'a str { - fn partial_cmp(&self, other: &Bytes) -> Option { - other.partial_cmp(self) - } +unsafe fn shared_drop(data: &mut AtomicPtr<()>, _ptr: *const u8, _len: usize) { + data.with_mut(|shared| { + release_shared(*shared as *mut Shared); + }); } -impl<'a, T: ?Sized> PartialEq<&'a T> for Bytes - where Bytes: PartialEq -{ - fn eq(&self, other: &&'a T) -> bool { - *self == **other +unsafe fn shallow_clone_arc(shared: *mut Shared, ptr: *const u8, len: usize) -> Bytes { + let old_size = (*shared).ref_cnt.fetch_add(1, Ordering::Relaxed); + + if old_size > usize::MAX >> 1 { + crate::abort(); } -} -impl<'a, T: ?Sized> PartialOrd<&'a T> for Bytes - where Bytes: PartialOrd -{ - fn partial_cmp(&self, other: &&'a T) -> Option { - self.partial_cmp(&**other) + Bytes { + ptr, + len, + data: AtomicPtr::new(shared as _), + vtable: &SHARED_VTABLE, } } -impl PartialEq for Bytes -{ - fn eq(&self, other: &BytesMut) -> bool { - &other[..] == &self[..] +#[cold] +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`. It is time to + // promote the vec to an `Arc`. This could potentially be called + // concurrently, so some care must be taken. + + // 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`. + // This means that these fields will not be concurrently + // 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_boxed_slice(buf, offset, len).into_vec(); + let shared = Box::new(Shared { + _vec: vec, + // Initialize refcount to 2. One for this reference, and one + // for the new clone that will be returned from + // `shallow_clone`. + ref_cnt: AtomicUsize::new(2), + }); + + let shared = Box::into_raw(shared); + + // The pointer should be aligned, so this assert should + // always succeed. + debug_assert!( + 0 == (shared as usize & KIND_MASK), + "internal: Box should have an aligned pointer", + ); + + // Try compare & swapping the pointer into the `arc` field. + // `Release` is used synchronize with other threads that + // will load the `arc` field. + // + // If the `compare_exchange` fails, then the thread lost the + // race to promote the buffer to shared. The `Acquire` + // ordering will synchronize with the `compare_exchange` + // that happened in the other thread and the `Shared` + // pointed to by `actual` will be visible. + match atom.compare_exchange(ptr as _, shared as _, Ordering::AcqRel, Ordering::Acquire) { + Ok(actual) => { + debug_assert!(actual as usize == ptr as usize); + // The upgrade was successful, the new handle can be + // returned. + Bytes { + ptr: offset, + len, + data: AtomicPtr::new(shared as _), + vtable: &SHARED_VTABLE, + } + } + Err(actual) => { + // The upgrade failed, a concurrent clone happened. Release + // the allocation that was made in this thread, it will not + // be needed. + let shared = Box::from_raw(shared); + mem::forget(*shared); + + // Buffer already promoted to shared storage, so increment ref + // count. + shallow_clone_arc(actual as _, offset, len) + } } } -impl PartialEq for BytesMut -{ - fn eq(&self, other: &Bytes) -> bool { - &other[..] == &self[..] +unsafe fn release_shared(ptr: *mut Shared) { + // `Shared` storage... follow the drop steps from Arc. + if (*ptr).ref_cnt.fetch_sub(1, Ordering::Release) != 1 { + return; } -} -// While there is `std::process:abort`, it's only available in Rust 1.17, and -// our minimum supported version is currently 1.15. So, this acts as an abort -// by triggering a double panic, which always aborts in Rust. -struct Abort; + // This fence is needed to prevent reordering of use of the data and + // deletion of the data. Because it is marked `Release`, the decreasing + // of the reference count synchronizes with this `Acquire` fence. This + // means that use of the data happens before decreasing the reference + // count, which happens before this fence, which happens before the + // deletion of the data. + // + // As explained in the [Boost documentation][1], + // + // > It is important to enforce any possible access to the object in one + // > thread (through an existing reference) to *happen before* deleting + // > the object in a different thread. This is achieved by a "release" + // > operation after dropping a reference (any access to the object + // > through this reference must obviously happened before), and an + // > "acquire" operation before deleting the object. + // + // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) + atomic::fence(Ordering::Acquire); -impl Drop for Abort { - fn drop(&mut self) { - panic!(); - } + // Drop the data + Box::from_raw(ptr); } -#[inline(never)] -#[cold] -fn abort() { - let _a = Abort; - panic!(); +// compile-fails + +/// ```compile_fail +/// use bytes::Bytes; +/// #[deny(unused_must_use)] +/// { +/// let mut b1 = Bytes::from("hello world"); +/// b1.split_to(6); +/// } +/// ``` +fn _split_to_must_use() {} + +/// ```compile_fail +/// use bytes::Bytes; +/// #[deny(unused_must_use)] +/// { +/// let mut b1 = Bytes::from("hello world"); +/// b1.split_off(6); +/// } +/// ``` +fn _split_off_must_use() {} + +// fuzz tests +#[cfg(all(test, loom))] +mod fuzz { + use loom::sync::Arc; + use loom::thread; + + use super::Bytes; + #[test] + fn bytes_cloning_vec() { + loom::model(|| { + let a = Bytes::from(b"abcdefgh".to_vec()); + let addr = a.as_ptr() as usize; + + // test the Bytes::clone is Sync by putting it in an Arc + let a1 = Arc::new(a); + let a2 = a1.clone(); + + let t1 = thread::spawn(move || { + let b: Bytes = (*a1).clone(); + assert_eq!(b.as_ptr() as usize, addr); + }); + + let t2 = thread::spawn(move || { + let b: Bytes = (*a2).clone(); + assert_eq!(b.as_ptr() as usize, addr); + }); + + t1.join().unwrap(); + t2.join().unwrap(); + }); + } } diff -Nru rust-bytes-0.4.12/src/debug.rs rust-bytes-1.1.0/src/debug.rs --- rust-bytes-0.4.12/src/debug.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/src/debug.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -use std::fmt; - -/// Alternative implementation of `fmt::Debug` for byte slice. -/// -/// Standard `Debug` implementation for `[u8]` is comma separated -/// list of numbers. Since large amount of byte strings are in fact -/// ASCII strings or contain a lot of ASCII strings (e. g. HTTP), -/// it is convenient to print strings as ASCII when possible. -/// -/// This struct wraps `&[u8]` just to override `fmt::Debug`. -/// -/// `BsDebug` is not a part of public API of bytes crate. -pub struct BsDebug<'a>(pub &'a [u8]); - -impl<'a> fmt::Debug for BsDebug<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - try!(write!(fmt, "b\"")); - for &c in self.0 { - // https://doc.rust-lang.org/reference.html#byte-escapes - if c == b'\n' { - try!(write!(fmt, "\\n")); - } else if c == b'\r' { - try!(write!(fmt, "\\r")); - } else if c == b'\t' { - try!(write!(fmt, "\\t")); - } else if c == b'\\' || c == b'"' { - try!(write!(fmt, "\\{}", c as char)); - } else if c == b'\0' { - try!(write!(fmt, "\\0")); - // ASCII printable - } else if c >= 0x20 && c < 0x7f { - try!(write!(fmt, "{}", c as char)); - } else { - try!(write!(fmt, "\\x{:02x}", c)); - } - } - try!(write!(fmt, "\"")); - Ok(()) - } -} diff -Nru rust-bytes-0.4.12/src/either.rs rust-bytes-1.1.0/src/either.rs --- rust-bytes-0.4.12/src/either.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/src/either.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,89 +0,0 @@ -extern crate either; - -use {Buf, BufMut}; - -use self::either::Either; -use self::either::Either::*; -use iovec::IoVec; - -impl Buf for Either -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 BufMut for Either -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), - } - } -} diff -Nru rust-bytes-0.4.12/src/fmt/debug.rs rust-bytes-1.1.0/src/fmt/debug.rs --- rust-bytes-0.4.12/src/fmt/debug.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/src/fmt/debug.rs 1973-11-29 21:33:09.000000000 +0000 @@ -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) + } +} diff -Nru rust-bytes-0.4.12/src/fmt/hex.rs rust-bytes-1.1.0/src/fmt/hex.rs --- rust-bytes-0.4.12/src/fmt/hex.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/src/fmt/hex.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,37 @@ +use core::fmt::{Formatter, LowerHex, Result, UpperHex}; + +use super::BytesRef; +use crate::{Bytes, BytesMut}; + +impl LowerHex for BytesRef<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + for &b in self.0 { + write!(f, "{:02x}", b)?; + } + Ok(()) + } +} + +impl UpperHex for BytesRef<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + for &b in self.0 { + write!(f, "{:02X}", b)?; + } + Ok(()) + } +} + +macro_rules! hex_impl { + ($tr:ident, $ty:ty) => { + impl $tr for $ty { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + $tr::fmt(&BytesRef(self.as_ref()), f) + } + } + }; +} + +hex_impl!(LowerHex, Bytes); +hex_impl!(LowerHex, BytesMut); +hex_impl!(UpperHex, Bytes); +hex_impl!(UpperHex, BytesMut); diff -Nru rust-bytes-0.4.12/src/fmt/mod.rs rust-bytes-1.1.0/src/fmt/mod.rs --- rust-bytes-0.4.12/src/fmt/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/src/fmt/mod.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,5 @@ +mod debug; +mod hex; + +/// `BytesRef` is not a part of public API of bytes crate. +struct BytesRef<'a>(&'a [u8]); diff -Nru rust-bytes-0.4.12/src/lib.rs rust-bytes-1.1.0/src/lib.rs --- rust-bytes-0.4.12/src/lib.rs 2019-03-06 20:42:31.000000000 +0000 +++ rust-bytes-1.1.0/src/lib.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,3 +1,10 @@ +#![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)) +))] +#![no_std] + //! Provides abstractions for working with bytes. //! //! The `bytes` crate provides an efficient byte buffer structure @@ -9,7 +16,7 @@ //! //! # `Bytes` //! -//! `Bytes` is an efficient container for storing and operating on continguous +//! `Bytes` is an efficient container for storing and operating on contiguous //! slices of memory. It is intended for use primarily in networking code, but //! could have applications elsewhere as well. //! @@ -23,18 +30,18 @@ //! example: //! //! ```rust -//! use bytes::{BytesMut, BufMut, BigEndian}; +//! use bytes::{BytesMut, BufMut}; //! //! let mut buf = BytesMut::with_capacity(1024); //! buf.put(&b"hello world"[..]); -//! buf.put_u16::(1234); +//! buf.put_u16(1234); //! -//! let a = buf.take(); +//! let a = buf.split(); //! assert_eq!(a, b"hello world\x04\xD2"[..]); //! //! buf.put(&b"goodbye world"[..]); //! -//! let b = buf.take(); +//! let b = buf.split(); //! assert_eq!(b, b"goodbye world"[..]); //! //! assert_eq!(buf.capacity(), 998); @@ -68,38 +75,42 @@ //! perform a syscall, which has the potential of failing. Operations on `Buf` //! and `BufMut` are infallible. -#![deny(warnings, missing_docs, missing_debug_implementations)] -#![doc(html_root_url = "https://docs.rs/bytes/0.4.12")] +extern crate alloc; -extern crate byteorder; -extern crate iovec; +#[cfg(feature = "std")] +extern crate std; pub mod buf; -pub use buf::{ - Buf, - BufMut, - IntoBuf, -}; -#[deprecated(since = "0.4.1", note = "moved to `buf` module")] -#[doc(hidden)] -pub use buf::{ - Reader, - Writer, - Take, -}; +pub use crate::buf::{Buf, BufMut}; mod bytes; -mod debug; -pub use bytes::{Bytes, BytesMut}; - -#[deprecated] -pub use byteorder::{ByteOrder, BigEndian, LittleEndian}; +mod bytes_mut; +mod fmt; +mod loom; +pub use crate::bytes::Bytes; +pub use crate::bytes_mut::BytesMut; // Optional Serde support #[cfg(feature = "serde")] -#[doc(hidden)] -pub mod serde; +mod serde; -// Optional `Either` support -#[cfg(feature = "either")] -mod either; +#[inline(never)] +#[cold] +fn abort() -> ! { + #[cfg(feature = "std")] + { + std::process::abort(); + } + + #[cfg(not(feature = "std"))] + { + struct Abort; + impl Drop for Abort { + fn drop(&mut self) { + panic!(); + } + } + let _a = Abort; + panic!("abort"); + } +} diff -Nru rust-bytes-0.4.12/src/loom.rs rust-bytes-1.1.0/src/loom.rs --- rust-bytes-0.4.12/src/loom.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/src/loom.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,30 @@ +#[cfg(not(all(test, loom)))] +pub(crate) mod sync { + pub(crate) mod atomic { + pub(crate) use core::sync::atomic::{fence, AtomicPtr, AtomicUsize, Ordering}; + + pub(crate) trait AtomicMut { + fn with_mut(&mut self, f: F) -> R + where + F: FnOnce(&mut *mut T) -> R; + } + + impl AtomicMut for AtomicPtr { + fn with_mut(&mut self, f: F) -> R + where + F: FnOnce(&mut *mut T) -> R, + { + f(self.get_mut()) + } + } + } +} + +#[cfg(all(test, loom))] +pub(crate) mod sync { + pub(crate) mod atomic { + pub(crate) use loom::sync::atomic::{fence, AtomicPtr, AtomicUsize, Ordering}; + + pub(crate) trait AtomicMut {} + } +} diff -Nru rust-bytes-0.4.12/src/serde.rs rust-bytes-1.1.0/src/serde.rs --- rust-bytes-0.4.12/src/serde.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/src/serde.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,15 +1,16 @@ -extern crate serde; - -use std::{cmp, fmt}; -use self::serde::{Serialize, Serializer, Deserialize, Deserializer, de}; use super::{Bytes, BytesMut}; +use alloc::string::String; +use alloc::vec::Vec; +use core::{cmp, fmt}; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; macro_rules! serde_impl { - ($ty:ident, $visitor_ty:ident) => ( + ($ty:ident, $visitor_ty:ident, $from_slice:ident, $from_vec:ident) => { impl Serialize for $ty { #[inline] fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { serializer.serialize_bytes(&self) } @@ -20,63 +21,69 @@ impl<'de> de::Visitor<'de> for $visitor_ty { type Value = $ty; - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("byte array") } #[inline] fn visit_seq(self, mut seq: V) -> Result - 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::with_capacity(len); + let mut values: Vec = Vec::with_capacity(len); - while let Some(value) = try!(seq.next_element()) { + while let Some(value) = seq.next_element()? { values.push(value); } - Ok(values.into()) + Ok($ty::$from_vec(values)) } #[inline] fn visit_bytes(self, v: &[u8]) -> Result - where E: de::Error + where + E: de::Error, { - Ok($ty::from(v)) + Ok($ty::$from_slice(v)) } #[inline] fn visit_byte_buf(self, v: Vec) -> Result - where E: de::Error + where + E: de::Error, { - Ok($ty::from(v)) + Ok($ty::$from_vec(v)) } #[inline] fn visit_str(self, v: &str) -> Result - where E: de::Error + where + E: de::Error, { - Ok($ty::from(v)) + Ok($ty::$from_slice(v.as_bytes())) } #[inline] fn visit_string(self, v: String) -> Result - where E: de::Error + where + E: de::Error, { - Ok($ty::from(v)) + Ok($ty::$from_vec(v.into_bytes())) } } impl<'de> Deserialize<'de> for $ty { #[inline] fn deserialize(deserializer: D) -> Result<$ty, D::Error> - where D: Deserializer<'de> + where + D: Deserializer<'de>, { deserializer.deserialize_byte_buf($visitor_ty) } } - ); + }; } -serde_impl!(Bytes, BytesVisitor); -serde_impl!(BytesMut, BytesMutVisitor); +serde_impl!(Bytes, BytesVisitor, copy_from_slice, from); +serde_impl!(BytesMut, BytesMutVisitor, from, from_vec); diff -Nru rust-bytes-0.4.12/tests/test_buf_mut.rs rust-bytes-1.1.0/tests/test_buf_mut.rs --- rust-bytes-0.4.12/tests/test_buf_mut.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/tests/test_buf_mut.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,27 +1,23 @@ -extern crate bytes; -extern crate byteorder; -extern crate iovec; +#![warn(rust_2018_idioms)] +use bytes::buf::UninitSlice; use bytes::{BufMut, BytesMut}; -use iovec::IoVec; -use std::usize; -use std::fmt::Write; +use core::fmt::Write; +use core::usize; #[test] fn test_vec_as_mut_buf() { let mut buf = Vec::with_capacity(64); - assert_eq!(buf.remaining_mut(), usize::MAX); + assert_eq!(buf.remaining_mut(), isize::MAX as usize); - unsafe { - assert!(buf.bytes_mut().len() >= 64); - } + assert!(buf.chunk_mut().len() >= 64); buf.put(&b"zomg"[..]); assert_eq!(&buf, b"zomg"); - assert_eq!(buf.remaining_mut(), usize::MAX - 4); + assert_eq!(buf.remaining_mut(), isize::MAX as usize - 4); assert_eq!(buf.capacity(), 64); for _ in 0..16 { @@ -32,16 +28,24 @@ } #[test] +fn test_vec_put_bytes() { + let mut buf = Vec::new(); + buf.push(17); + buf.put_bytes(19, 2); + assert_eq!([17, 19, 19], &buf[..]); +} + +#[test] fn test_put_u8() { let mut buf = Vec::with_capacity(8); - buf.put::(33); + buf.put_u8(33); assert_eq!(b"\x21", &buf[..]); } #[test] fn test_put_u16() { let mut buf = Vec::with_capacity(8); - buf.put_u16_be(8532); + buf.put_u16(8532); assert_eq!(b"\x21\x54", &buf[..]); buf.clear(); @@ -50,13 +54,40 @@ } #[test] +fn test_put_int() { + let mut buf = Vec::with_capacity(8); + buf.put_int(0x1020304050607080, 3); + assert_eq!(b"\x60\x70\x80", &buf[..]); +} + +#[test] +#[should_panic] +fn test_put_int_nbytes_overflow() { + let mut buf = Vec::with_capacity(8); + buf.put_int(0x1020304050607080, 9); +} + +#[test] +fn test_put_int_le() { + let mut buf = Vec::with_capacity(8); + buf.put_int_le(0x1020304050607080, 3); + assert_eq!(b"\x80\x70\x60", &buf[..]); +} + +#[test] +#[should_panic] +fn test_put_int_le_nbytes_overflow() { + let mut buf = Vec::with_capacity(8); + buf.put_int_le(0x1020304050607080, 9); +} + +#[test] +#[should_panic(expected = "cannot advance")] fn test_vec_advance_mut() { - // 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()); } } @@ -66,18 +97,82 @@ buf.write_str("this is a test").unwrap(); let buf2 = buf.clone(); - buf.write_str(" of our emergecy broadcast system").unwrap(); + buf.write_str(" of our emergency broadcast system").unwrap(); assert!(buf != buf2); } #[test] -fn test_bufs_vec_mut() { - use std::mem; +fn test_mut_slice() { + let mut v = vec![0, 0, 0, 0]; + let mut s = &mut v[..]; + s.put_u32(42); + + assert_eq!(s.len(), 0); + assert_eq!(&v, &[0, 0, 0, 42]); +} + +#[test] +fn test_slice_put_bytes() { + let mut v = [0, 0, 0, 0]; + let mut s = &mut v[..]; + s.put_u8(17); + s.put_bytes(19, 2); + assert_eq!(1, s.remaining_mut()); + assert_eq!(&[17, 19, 19, 0], &v[..]); +} - let mut buf = BytesMut::from(&b"hello world"[..]); +#[test] +fn test_deref_bufmut_forwards() { + struct Special; - unsafe { - let mut dst: [&mut IoVec; 2] = mem::zeroed(); - assert_eq!(1, buf.bytes_vec_mut(&mut dst[..])); + unsafe impl BufMut for Special { + fn remaining_mut(&self) -> usize { + unreachable!("remaining_mut"); + } + + fn chunk_mut(&mut self) -> &mut UninitSlice { + unreachable!("chunk_mut"); + } + + unsafe fn advance_mut(&mut self, _: usize) { + unreachable!("advance"); + } + + fn put_u8(&mut self, _: u8) { + // specialized! + } } + + // these should all use the specialized method + Special.put_u8(b'x'); + (&mut Special as &mut dyn BufMut).put_u8(b'x'); + (Box::new(Special) as Box).put_u8(b'x'); + Box::new(Special).put_u8(b'x'); +} + +#[test] +#[should_panic] +fn write_byte_panics_if_out_of_bounds() { + let mut data = [b'b', b'a', b'r']; + + let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) }; + slice.write_byte(4, b'f'); +} + +#[test] +#[should_panic] +fn copy_from_slice_panics_if_different_length_1() { + let mut data = [b'b', b'a', b'r']; + + let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) }; + slice.copy_from_slice(b"a"); +} + +#[test] +#[should_panic] +fn copy_from_slice_panics_if_different_length_2() { + let mut data = [b'b', b'a', b'r']; + + let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) }; + slice.copy_from_slice(b"abcd"); } diff -Nru rust-bytes-0.4.12/tests/test_buf.rs rust-bytes-1.1.0/tests/test_buf.rs --- rust-bytes-0.4.12/tests/test_buf.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/tests/test_buf.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,58 +1,120 @@ -extern crate bytes; -extern crate byteorder; -extern crate iovec; +#![warn(rust_2018_idioms)] use bytes::Buf; -use iovec::IoVec; -use std::io::Cursor; +#[cfg(feature = "std")] +use std::io::IoSlice; #[test] fn test_fresh_cursor_vec() { - let mut buf = Cursor::new(b"hello".to_vec()); + let mut buf = &b"hello"[..]; assert_eq!(buf.remaining(), 5); - assert_eq!(buf.bytes(), b"hello"); + assert_eq!(buf.chunk(), b"hello"); buf.advance(2); assert_eq!(buf.remaining(), 3); - assert_eq!(buf.bytes(), b"llo"); + assert_eq!(buf.chunk(), b"llo"); buf.advance(3); assert_eq!(buf.remaining(), 0); - assert_eq!(buf.bytes(), b""); + assert_eq!(buf.chunk(), b""); } #[test] fn test_get_u8() { - let mut buf = Cursor::new(b"\x21zomg"); + let mut buf = &b"\x21zomg"[..]; assert_eq!(0x21, buf.get_u8()); } #[test] fn test_get_u16() { - let buf = b"\x21\x54zomg"; - assert_eq!(0x2154, Cursor::new(buf).get_u16_be()); - assert_eq!(0x5421, Cursor::new(buf).get_u16_le()); + let mut buf = &b"\x21\x54zomg"[..]; + assert_eq!(0x2154, buf.get_u16()); + let mut buf = &b"\x21\x54zomg"[..]; + assert_eq!(0x5421, buf.get_u16_le()); } #[test] #[should_panic] fn test_get_u16_buffer_underflow() { - let mut buf = Cursor::new(b"\x21"); - buf.get_u16_be(); + let mut buf = &b"\x21"[..]; + buf.get_u16(); } +#[cfg(feature = "std")] #[test] fn test_bufs_vec() { - let buf = Cursor::new(b"hello world"); + let buf = &b"hello world"[..]; - let b1: &[u8] = &mut [0]; - let b2: &[u8] = &mut [0]; + let b1: &[u8] = &mut []; + let b2: &[u8] = &mut []; - let mut dst: [&IoVec; 2] = - [b1.into(), b2.into()]; + let mut dst = [IoSlice::new(b1), IoSlice::new(b2)]; - assert_eq!(1, buf.bytes_vec(&mut dst[..])); + assert_eq!(1, buf.chunks_vectored(&mut dst[..])); +} + +#[test] +fn test_vec_deque() { + use std::collections::VecDeque; + + let mut buffer: VecDeque = VecDeque::new(); + buffer.extend(b"hello world"); + assert_eq!(11, buffer.remaining()); + assert_eq!(b"hello world", buffer.chunk()); + buffer.advance(6); + assert_eq!(b"world", buffer.chunk()); + buffer.extend(b" piece"); + let mut out = [0; 11]; + buffer.copy_to_slice(&mut out); + assert_eq!(b"world piece", &out[..]); +} + +#[test] +fn test_deref_buf_forwards() { + struct Special; + + impl Buf for Special { + fn remaining(&self) -> usize { + unreachable!("remaining"); + } + + fn chunk(&self) -> &[u8] { + unreachable!("chunk"); + } + + fn advance(&mut self, _: usize) { + unreachable!("advance"); + } + + fn get_u8(&mut self) -> u8 { + // specialized! + b'x' + } + } + + // these should all use the specialized method + assert_eq!(Special.get_u8(), b'x'); + assert_eq!((&mut Special as &mut dyn Buf).get_u8(), b'x'); + assert_eq!((Box::new(Special) as Box).get_u8(), b'x'); + assert_eq!(Box::new(Special).get_u8(), b'x'); +} + +#[test] +fn copy_to_bytes_less() { + let mut buf = &b"hello world"[..]; + + let bytes = buf.copy_to_bytes(5); + assert_eq!(bytes, &b"hello"[..]); + assert_eq!(buf, &b" world"[..]) +} + +#[test] +#[should_panic] +fn copy_to_bytes_overflow() { + let mut buf = &b"hello world"[..]; + + let _bytes = buf.copy_to_bytes(12); } diff -Nru rust-bytes-0.4.12/tests/test_bytes_odd_alloc.rs rust-bytes-1.1.0/tests/test_bytes_odd_alloc.rs --- rust-bytes-0.4.12/tests/test_bytes_odd_alloc.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/tests/test_bytes_odd_alloc.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,69 @@ +//! Test using `Bytes` with an allocator that hands out "odd" pointers for +//! vectors (pointers where the LSB is set). + +#![cfg(not(miri))] // Miri does not support custom allocators (also, Miri is "odd" by default with 50% chance) + +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(); +} diff -Nru rust-bytes-0.4.12/tests/test_bytes.rs rust-bytes-1.1.0/tests/test_bytes.rs --- rust-bytes-0.4.12/tests/test_bytes.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/tests/test_bytes.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,15 +1,12 @@ -extern crate bytes; +#![warn(rust_2018_idioms)] -use bytes::{Bytes, BytesMut, BufMut, IntoBuf}; +use bytes::{Buf, BufMut, Bytes, BytesMut}; + +use std::usize; const LONG: &'static [u8] = b"mary had a little lamb, little lamb, little lamb"; const SHORT: &'static [u8] = b"hello world"; -fn inline_cap() -> usize { - use std::mem; - 4 * mem::size_of::() - 1 -} - fn is_sync() {} fn is_send() {} @@ -22,6 +19,34 @@ } #[test] +fn test_layout() { + use std::mem; + + assert_eq!( + mem::size_of::(), + mem::size_of::() * 4, + "Bytes size should be 4 words", + ); + assert_eq!( + mem::size_of::(), + mem::size_of::() * 4, + "BytesMut should be 4 words", + ); + + assert_eq!( + mem::size_of::(), + mem::size_of::>(), + "Bytes should be same size as Option", + ); + + assert_eq!( + mem::size_of::(), + mem::size_of::>(), + "BytesMut should be same size as Option", + ); +} + +#[test] fn from_slice() { let a = Bytes::from(&b"abcdefgh"[..]); assert_eq!(a, b"abcdefgh"[..]); @@ -61,16 +86,14 @@ 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_err(); - assert!(c.is_empty()); + write!(c, "{}", s).unwrap(); + assert_eq!(c, s[..].as_bytes()); } #[test] @@ -98,22 +121,22 @@ fn slice() { let a = Bytes::from(&b"hello world"[..]); - let b = a.slice(3, 5); + let b = a.slice(3..5); assert_eq!(b, b"lo"[..]); - let b = a.slice(0, 0); + let b = a.slice(0..0); assert_eq!(b, b""[..]); - let b = a.slice(3, 3); + let b = a.slice(3..3); assert_eq!(b, b""[..]); - let b = a.slice(a.len(), a.len()); + let b = a.slice(a.len()..a.len()); assert_eq!(b, b""[..]); - let b = a.slice_to(5); + let b = a.slice(..5); assert_eq!(b, b"hello"[..]); - let b = a.slice_from(3); + let b = a.slice(3..); assert_eq!(b, b"lo world"[..]); } @@ -121,14 +144,14 @@ #[should_panic] fn slice_oob_1() { let a = Bytes::from(&b"hello world"[..]); - a.slice(5, inline_cap() + 1); + a.slice(5..44); } #[test] #[should_panic] fn slice_oob_2() { let a = Bytes::from(&b"hello world"[..]); - a.slice(inline_cap() + 1, inline_cap() + 5); + a.slice(44..49); } #[test] @@ -150,7 +173,7 @@ #[should_panic] fn split_off_oob() { let mut hello = Bytes::from(&b"helloworld"[..]); - hello.split_off(inline_cap() + 1); + let _ = hello.split_off(44); } #[test] @@ -175,8 +198,8 @@ let off = bytes.split_off(i); assert_eq!(i, bytes.len()); let mut sum = Vec::new(); - sum.extend(&bytes); - sum.extend(&off); + sum.extend(bytes.iter()); + sum.extend(off.iter()); assert_eq!(&s[..], &sum[..]); } { @@ -193,8 +216,8 @@ let off = bytes.split_to(i); assert_eq!(i, off.len()); let mut sum = Vec::new(); - sum.extend(&off); - sum.extend(&bytes); + sum.extend(off.iter()); + sum.extend(bytes.iter()); assert_eq!(&s[..], &sum[..]); } { @@ -211,21 +234,21 @@ #[test] fn split_to_1() { - // Inline - let mut a = Bytes::from(SHORT); + // Static + let mut a = Bytes::from_static(SHORT); let b = a.split_to(4); assert_eq!(SHORT[4..], a); assert_eq!(SHORT[..4], b); // Allocated - let mut a = Bytes::from(LONG); + let mut a = Bytes::copy_from_slice(LONG); let b = a.split_to(4); assert_eq!(LONG[4..], a); assert_eq!(LONG[..4], b); - let mut a = Bytes::from(LONG); + let mut a = Bytes::copy_from_slice(LONG); let b = a.split_to(30); assert_eq!(LONG[30..], a); @@ -247,26 +270,21 @@ #[should_panic] fn split_to_oob() { let mut hello = Bytes::from(&b"helloworld"[..]); - hello.split_to(inline_cap() + 1); + let _ = hello.split_to(33); } #[test] #[should_panic] fn split_to_oob_mut() { let mut hello = BytesMut::from(&b"helloworld"[..]); - hello.split_to(inline_cap() + 1); + let _ = hello.split_to(33); } #[test] +#[should_panic] fn split_to_uninitialized() { let mut bytes = BytesMut::with_capacity(1024); - let other = bytes.split_to(128); - - assert_eq!(bytes.len(), 0); - assert_eq!(bytes.capacity(), 896); - - assert_eq!(other.len(), 0); - assert_eq!(other.capacity(), 128); + let _other = bytes.split_to(128); } #[test] @@ -279,16 +297,114 @@ use std::panic; - make_bytes().split_to(4); - make_bytes().split_off(4); + let _ = make_bytes().split_to(4); + let _ = make_bytes().split_off(4); assert!(panic::catch_unwind(move || { - make_bytes().split_to(5); - }).is_err()); + let _ = make_bytes().split_to(5); + }) + .is_err()); assert!(panic::catch_unwind(move || { - make_bytes().split_off(5); - }).is_err()); + let _ = make_bytes().split_off(5); + }) + .is_err()); +} + +#[test] +fn truncate() { + let s = &b"helloworld"[..]; + let mut hello = Bytes::from(s); + hello.truncate(15); + assert_eq!(hello, s); + hello.truncate(10); + assert_eq!(hello, s); + hello.truncate(5); + assert_eq!(hello, "hello"); +} + +#[test] +fn freeze_clone_shared() { + let s = &b"abcdefgh"[..]; + let b = BytesMut::from(s).split().freeze(); + assert_eq!(b, s); + let c = b.clone(); + assert_eq!(c, s); +} + +#[test] +fn freeze_clone_unique() { + let s = &b"abcdefgh"[..]; + let b = BytesMut::from(s).freeze(); + assert_eq!(b, s); + let c = b.clone(); + assert_eq!(c, s); +} + +#[test] +fn 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] @@ -299,37 +415,12 @@ bytes.as_mut_ptr(); // Iterator - let v: Vec = bytes.iter().map(|b| *b).collect(); + let v: Vec = bytes.as_ref().iter().cloned().collect(); assert_eq!(&v[..], bytes); } #[test] -fn mut_into_buf() { - let mut v = vec![0, 0, 0, 0]; - let s = &mut v[..]; - s.into_buf().put_u32_le(42); -} - -#[test] fn reserve_convert() { - // Inline -> Vec - let mut bytes = BytesMut::with_capacity(8); - bytes.put("hello"); - bytes.reserve(40); - assert_eq!(bytes.capacity(), 45); - assert_eq!(bytes, "hello"); - - // Inline -> Inline - let mut bytes = BytesMut::with_capacity(inline_cap()); - bytes.put("abcdefghijkl"); - - let a = bytes.split_to(10); - bytes.reserve(inline_cap() - 3); - assert_eq!(inline_cap(), bytes.capacity()); - - assert_eq!(bytes, "kl"); - assert_eq!(a, "abcdefghij"); - // Vec -> Vec let mut bytes = BytesMut::from(LONG); bytes.reserve(64); @@ -348,8 +439,8 @@ #[test] fn reserve_growth() { let mut bytes = BytesMut::with_capacity(64); - bytes.put("hello world"); - let _ = bytes.take(); + bytes.put("hello world".as_bytes()); + let _ = bytes.split(); bytes.reserve(65); assert_eq!(bytes.capacity(), 128); @@ -360,50 +451,50 @@ let mut bytes = BytesMut::with_capacity(1024); for i in 0..1020 { - bytes.put(i as u8); + bytes.put_u8(i as u8); } - let _other = bytes.take(); + let _other = bytes.split(); bytes.reserve(16); assert_eq!(bytes.capacity(), 1024); } #[test] +#[cfg_attr(miri, ignore)] // Miri is too slow fn reserve_max_original_capacity_value() { const SIZE: usize = 128 * 1024; let mut bytes = BytesMut::with_capacity(SIZE); for _ in 0..SIZE { - bytes.put(0u8); + bytes.put_u8(0u8); } - let _other = bytes.take(); + let _other = bytes.split(); bytes.reserve(16); assert_eq!(bytes.capacity(), 64 * 1024); } -// Without either looking at the internals of the BytesMut or doing weird stuff -// with the memory allocator, there's no good way to automatically verify from -// within the program that this actually recycles memory. Instead, just exercise -// the code path to ensure that the results are correct. #[test] fn reserve_vec_recycling() { - let mut bytes = BytesMut::from(Vec::with_capacity(16)); + let mut bytes = BytesMut::with_capacity(16); assert_eq!(bytes.capacity(), 16); - bytes.put("0123456789012345"); + let addr = bytes.as_ptr() as usize; + bytes.put("0123456789012345".as_bytes()); + assert_eq!(bytes.as_ptr() as usize, addr); bytes.advance(10); assert_eq!(bytes.capacity(), 6); bytes.reserve(8); assert_eq!(bytes.capacity(), 16); + assert_eq!(bytes.as_ptr() as usize, addr); } #[test] fn reserve_in_arc_unique_does_not_overallocate() { let mut bytes = BytesMut::with_capacity(1000); - bytes.take(); + let _ = bytes.split(); // now bytes is Arc and refcount == 1 @@ -415,7 +506,7 @@ #[test] fn reserve_in_arc_unique_doubles() { let mut bytes = BytesMut::with_capacity(1000); - bytes.take(); + let _ = bytes.split(); // now bytes is Arc and refcount == 1 @@ -427,7 +518,7 @@ #[test] fn reserve_in_arc_nonunique_does_not_overallocate() { let mut bytes = BytesMut::with_capacity(1000); - let _copy = bytes.take(); + let _copy = bytes.split(); // now bytes is Arc and refcount == 2 @@ -437,15 +528,6 @@ } #[test] -fn inline_storage() { - let mut bytes = BytesMut::with_capacity(inline_cap()); - let zero = [0u8; 64]; - - bytes.put(&zero[0..inline_cap()]); - assert_eq!(*bytes, zero[0..inline_cap()]); -} - -#[test] fn extend_mut() { let mut bytes = BytesMut::with_capacity(0); bytes.extend(LONG); @@ -453,13 +535,6 @@ } #[test] -fn extend_shr() { - let mut bytes = Bytes::new(); - bytes.extend(LONG); - assert_eq!(*bytes, LONG[..]); -} - -#[test] fn extend_from_slice_mut() { for &i in &[3, 34] { let mut bytes = BytesMut::new(); @@ -470,13 +545,13 @@ } #[test] -fn extend_from_slice_shr() { - for &i in &[3, 34] { - let mut bytes = Bytes::new(); - bytes.extend_from_slice(&LONG[..i]); - bytes.extend_from_slice(&LONG[i..]); - assert_eq!(LONG[..], *bytes); - } +fn extend_mut_without_size_hint() { + let mut bytes = BytesMut::with_capacity(0); + let mut long_iter = LONG.iter(); + + // Use iter::from_fn since it doesn't know a size_hint + bytes.extend(std::iter::from_fn(|| long_iter.next())); + assert_eq!(*bytes, LONG[..]); } #[test] @@ -489,22 +564,28 @@ } #[test] -fn advance_inline() { - let mut a = Bytes::from(&b"hello world"[..]); +fn advance_static() { + let mut a = Bytes::from_static(b"hello world"); a.advance(6); assert_eq!(a, &b"world"[..]); } #[test] -fn advance_static() { - let mut a = Bytes::from_static(b"hello world"); +fn advance_vec() { + let mut a = Bytes::from(b"hello world boooo yah world zomg wat wat".to_vec()); + a.advance(16); + assert_eq!(a, b"o yah world zomg wat wat"[..]); + + a.advance(4); + assert_eq!(a, b"h world zomg wat wat"[..]); + a.advance(6); - assert_eq!(a, &b"world"[..]); + assert_eq!(a, b"d zomg wat wat"[..]); } #[test] -fn advance_vec() { - let mut a = BytesMut::from(b"hello world boooo yah world zomg wat wat".to_vec()); +fn advance_bytes_mut() { + let mut a = BytesMut::from("hello world boooo yah world zomg wat wat"); a.advance(16); assert_eq!(a, b"o yah world zomg wat wat"[..]); @@ -522,25 +603,25 @@ #[test] #[should_panic] fn advance_past_len() { - let mut a = BytesMut::from(b"hello world".to_vec()); + let mut a = BytesMut::from("hello world"); a.advance(20); } #[test] // Only run these tests on little endian systems. CI uses qemu for testing -// little endian... and qemu doesn't really support threading all that well. -#[cfg(target_endian = "little")] +// big endian... and qemu doesn't really support threading all that well. +#[cfg(any(miri, target_endian = "little"))] fn stress() { // Tests promoting a buffer from a vec -> shared in a concurrent situation use std::sync::{Arc, Barrier}; use std::thread; const THREADS: usize = 8; - const ITERS: usize = 1_000; + const ITERS: usize = if cfg!(miri) { 100 } else { 1_000 }; for i in 0..ITERS { let data = [i as u8; 256]; - let buf = Arc::new(Bytes::from(&data[..])); + let buf = Arc::new(Bytes::copy_from_slice(&data[..])); let barrier = Arc::new(Barrier::new(THREADS)); let mut joins = Vec::with_capacity(THREADS); @@ -575,10 +656,10 @@ assert!(bytesmut != bytes2); } +/* #[test] -fn unsplit_basic() { - let mut buf = BytesMut::with_capacity(64); - buf.extend_from_slice(b"aaabbbcccddd"); +fn bytes_unsplit_basic() { + let buf = Bytes::from(&b"aaabbbcccddd"[..]); let splitted = buf.split_off(6); assert_eq!(b"aaabbb", &buf[..]); @@ -589,23 +670,22 @@ } #[test] -fn unsplit_empty_other() { - let mut buf = BytesMut::with_capacity(64); - buf.extend_from_slice(b"aaabbbcccddd"); +fn bytes_unsplit_empty_other() { + let buf = Bytes::from(&b"aaabbbcccddd"[..]); // empty other - let other = BytesMut::new(); + let other = Bytes::new(); buf.unsplit(other); assert_eq!(b"aaabbbcccddd", &buf[..]); } #[test] -fn unsplit_empty_self() { +fn bytes_unsplit_empty_self() { // empty self - let mut buf = BytesMut::new(); + let mut buf = Bytes::new(); - let mut other = BytesMut::with_capacity(64); + let mut other = Bytes::with_capacity(64); other.extend_from_slice(b"aaabbbcccddd"); buf.unsplit(other); @@ -613,11 +693,13 @@ } #[test] -fn unsplit_inline_arc() { - let mut buf = BytesMut::with_capacity(8); //inline - buf.extend_from_slice(b"aaaabbbb"); +fn bytes_unsplit_arc_different() { + let mut buf = Bytes::with_capacity(64); + buf.extend_from_slice(b"aaaabbbbeeee"); - let mut buf2 = BytesMut::with_capacity(64); + buf.split_off(8); //arc + + let mut buf2 = Bytes::with_capacity(64); buf2.extend_from_slice(b"ccccddddeeee"); buf2.split_off(8); //arc @@ -627,52 +709,124 @@ } #[test] -fn unsplit_arc_inline() { - let mut buf = BytesMut::with_capacity(64); - buf.extend_from_slice(b"aaaabbbbeeee"); +fn bytes_unsplit_arc_non_contiguous() { + let mut buf = Bytes::with_capacity(64); + buf.extend_from_slice(b"aaaabbbbeeeeccccdddd"); - buf.split_off(8); //arc + let mut buf2 = buf.split_off(8); //arc - let mut buf2 = BytesMut::with_capacity(8); //inline - buf2.extend_from_slice(b"ccccdddd"); + let buf3 = buf2.split_off(4); //arc + buf.unsplit(buf3); + assert_eq!(b"aaaabbbbccccdddd", &buf[..]); +} + +#[test] +fn bytes_unsplit_two_split_offs() { + let mut buf = Bytes::with_capacity(64); + buf.extend_from_slice(b"aaaabbbbccccdddd"); + + let mut buf2 = buf.split_off(8); //arc + let buf3 = buf2.split_off(4); //arc + + buf2.unsplit(buf3); buf.unsplit(buf2); assert_eq!(b"aaaabbbbccccdddd", &buf[..]); +} +#[test] +fn bytes_unsplit_overlapping_references() { + let mut buf = Bytes::with_capacity(64); + buf.extend_from_slice(b"abcdefghijklmnopqrstuvwxyz"); + let mut buf0010 = buf.slice(0..10); + let buf1020 = buf.slice(10..20); + let buf0515 = buf.slice(5..15); + buf0010.unsplit(buf1020); + assert_eq!(b"abcdefghijklmnopqrst", &buf0010[..]); + assert_eq!(b"fghijklmno", &buf0515[..]); } +*/ #[test] -fn unsplit_both_inline() { - let mut buf = BytesMut::with_capacity(16); //inline - buf.extend_from_slice(b"aaaabbbbccccdddd"); +fn bytes_mut_unsplit_basic() { + let mut buf = BytesMut::with_capacity(64); + buf.extend_from_slice(b"aaabbbcccddd"); - let splitted = buf.split_off(8); // both inline - assert_eq!(b"aaaabbbb", &buf[..]); - assert_eq!(b"ccccdddd", &splitted[..]); + let splitted = buf.split_off(6); + assert_eq!(b"aaabbb", &buf[..]); + assert_eq!(b"cccddd", &splitted[..]); buf.unsplit(splitted); - assert_eq!(b"aaaabbbbccccdddd", &buf[..]); + assert_eq!(b"aaabbbcccddd", &buf[..]); +} + +#[test] +fn bytes_mut_unsplit_empty_other() { + let mut buf = BytesMut::with_capacity(64); + buf.extend_from_slice(b"aaabbbcccddd"); + + // empty other + let other = BytesMut::new(); + + buf.unsplit(other); + assert_eq!(b"aaabbbcccddd", &buf[..]); +} + +#[test] +fn bytes_mut_unsplit_empty_self() { + // empty self + let mut buf = BytesMut::new(); + + let mut other = BytesMut::with_capacity(64); + other.extend_from_slice(b"aaabbbcccddd"); + + buf.unsplit(other); + assert_eq!(b"aaabbbcccddd", &buf[..]); +} + +#[test] +fn bytes_mut_unsplit_other_keeps_capacity() { + let mut buf = BytesMut::with_capacity(64); + buf.extend_from_slice(b"aabb"); + + // non empty other created "from" buf + let mut other = buf.split_off(buf.len()); + other.extend_from_slice(b"ccddee"); + buf.unsplit(other); + + assert_eq!(buf.capacity(), 64); } +#[test] +fn bytes_mut_unsplit_empty_other_keeps_capacity() { + let mut buf = BytesMut::with_capacity(64); + buf.extend_from_slice(b"aabbccddee"); + + // empty other created "from" buf + let other = buf.split_off(buf.len()); + buf.unsplit(other); + + assert_eq!(buf.capacity(), 64); +} #[test] -fn unsplit_arc_different() { +fn bytes_mut_unsplit_arc_different() { let mut buf = BytesMut::with_capacity(64); buf.extend_from_slice(b"aaaabbbbeeee"); - buf.split_off(8); //arc + let _ = buf.split_off(8); //arc let mut buf2 = BytesMut::with_capacity(64); buf2.extend_from_slice(b"ccccddddeeee"); - buf2.split_off(8); //arc + let _ = buf2.split_off(8); //arc buf.unsplit(buf2); assert_eq!(b"aaaabbbbccccdddd", &buf[..]); } #[test] -fn unsplit_arc_non_contiguous() { +fn bytes_mut_unsplit_arc_non_contiguous() { let mut buf = BytesMut::with_capacity(64); buf.extend_from_slice(b"aaaabbbbeeeeccccdddd"); @@ -685,7 +839,7 @@ } #[test] -fn unsplit_two_split_offs() { +fn bytes_mut_unsplit_two_split_offs() { let mut buf = BytesMut::with_capacity(64); buf.extend_from_slice(b"aaaabbbbccccdddd"); @@ -735,7 +889,6 @@ test_slice_ref(&bytes, 9, 9, b""); } - #[test] fn slice_ref_empty() { let bytes = Bytes::from(&b""[..]); @@ -746,6 +899,16 @@ } #[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() { let bytes = Bytes::from(&b"012345678"[..]); @@ -755,19 +918,87 @@ } #[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] +fn empty_slice_ref_not_an_empty_subset() { + let bytes = Bytes::new(); + let slice = &b"some other slice"[0..0]; + + assert_eq!(Bytes::new(), bytes.slice_ref(slice)); +} + +#[test] +fn bytes_buf_mut_advance() { + let mut bytes = BytesMut::with_capacity(1024); + + unsafe { + let ptr = bytes.chunk_mut().as_mut_ptr(); + assert_eq!(1024, bytes.chunk_mut().len()); + + bytes.advance_mut(10); + + let next = bytes.chunk_mut().as_mut_ptr(); + assert_eq!(1024 - 10, bytes.chunk_mut().len()); + assert_eq!(ptr.offset(10), next); + + // advance to the end + bytes.advance_mut(1024 - 10); + + // The buffer size is doubled + assert_eq!(1024, bytes.chunk_mut().len()); + } +} + +#[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 empty_slice_ref_catches_not_an_empty_subset() { - let bytes = Bytes::from(&b""[..]); - let slice = &b""[0..0]; +fn bytes_reserve_overflow() { + let mut bytes = BytesMut::with_capacity(1024); + bytes.put_slice(b"hello world"); - bytes.slice_ref(slice); + bytes.reserve(usize::MAX); +} + +#[test] +fn bytes_with_capacity_but_empty() { + // See https://github.com/tokio-rs/bytes/issues/340 + let vec = Vec::with_capacity(1); + let _ = Bytes::from(vec); +} + +#[test] +fn bytes_put_bytes() { + let mut bytes = BytesMut::new(); + bytes.put_u8(17); + bytes.put_bytes(19, 2); + assert_eq!([17, 19, 19], bytes.as_ref()); +} + +#[test] +fn box_slice_empty() { + // See https://github.com/tokio-rs/bytes/issues/340 + let empty: Box<[u8]> = Default::default(); + let b = Bytes::from(empty); + assert!(b.is_empty()); } diff -Nru rust-bytes-0.4.12/tests/test_bytes_vec_alloc.rs rust-bytes-1.1.0/tests/test_bytes_vec_alloc.rs --- rust-bytes-0.4.12/tests/test_bytes_vec_alloc.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-bytes-1.1.0/tests/test_bytes_vec_alloc.rs 1973-11-29 21:33:09.000000000 +0000 @@ -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::(); + +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); +} diff -Nru rust-bytes-0.4.12/tests/test_chain.rs rust-bytes-1.1.0/tests/test_chain.rs --- rust-bytes-0.4.12/tests/test_chain.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/tests/test_chain.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,36 +1,31 @@ -extern crate bytes; -extern crate iovec; +#![warn(rust_2018_idioms)] -use bytes::{Buf, BufMut, Bytes, BytesMut}; -use bytes::buf::Chain; -use iovec::IoVec; -use std::io::Cursor; +use bytes::{Buf, BufMut, Bytes}; +#[cfg(feature = "std")] +use std::io::IoSlice; #[test] fn collect_two_bufs() { - let a = Cursor::new(Bytes::from(&b"hello"[..])); - let b = Cursor::new(Bytes::from(&b"world"[..])); + let a = Bytes::from(&b"hello"[..]); + let b = Bytes::from(&b"world"[..]); - let res: Vec = a.chain(b).collect(); + let res = a.chain(b).copy_to_bytes(10); assert_eq!(res, &b"helloworld"[..]); } #[test] fn writing_chained() { - let mut a = BytesMut::with_capacity(64); - let mut b = BytesMut::with_capacity(64); + let mut a = [0u8; 64]; + let mut b = [0u8; 64]; { - let mut buf = Chain::new(&mut a, &mut b); + let mut buf = (&mut a[..]).chain_mut(&mut b[..]); - for i in 0..128 { - buf.put(i as u8); + for i in 0u8..128 { + buf.put_u8(i); } } - assert_eq!(64, a.len()); - assert_eq!(64, b.len()); - for i in 0..64 { let expect = i as u8; assert_eq!(expect, a[i]); @@ -40,83 +35,121 @@ #[test] fn iterating_two_bufs() { - let a = Cursor::new(Bytes::from(&b"hello"[..])); - let b = Cursor::new(Bytes::from(&b"world"[..])); + let a = Bytes::from(&b"hello"[..]); + let b = Bytes::from(&b"world"[..]); - let res: Vec = a.chain(b).iter().collect(); + let res: Vec = a.chain(b).into_iter().collect(); assert_eq!(res, &b"helloworld"[..]); } +#[cfg(feature = "std")] #[test] fn vectored_read() { - let a = Cursor::new(Bytes::from(&b"hello"[..])); - let b = Cursor::new(Bytes::from(&b"world"[..])); + let a = Bytes::from(&b"hello"[..]); + let b = Bytes::from(&b"world"[..]); let mut buf = a.chain(b); { - let b1: &[u8] = &mut [0]; - let b2: &[u8] = &mut [0]; - let b3: &[u8] = &mut [0]; - let b4: &[u8] = &mut [0]; - let mut iovecs: [&IoVec; 4] = - [b1.into(), b2.into(), b3.into(), b4.into()]; + let b1: &[u8] = &mut []; + let b2: &[u8] = &mut []; + let b3: &[u8] = &mut []; + let b4: &[u8] = &mut []; + let mut iovecs = [ + IoSlice::new(b1), + IoSlice::new(b2), + IoSlice::new(b3), + IoSlice::new(b4), + ]; - assert_eq!(2, buf.bytes_vec(&mut iovecs)); + assert_eq!(2, buf.chunks_vectored(&mut iovecs)); assert_eq!(iovecs[0][..], b"hello"[..]); assert_eq!(iovecs[1][..], b"world"[..]); - assert_eq!(iovecs[2][..], b"\0"[..]); - assert_eq!(iovecs[3][..], b"\0"[..]); + assert_eq!(iovecs[2][..], b""[..]); + assert_eq!(iovecs[3][..], b""[..]); } buf.advance(2); { - let b1: &[u8] = &mut [0]; - let b2: &[u8] = &mut [0]; - let b3: &[u8] = &mut [0]; - let b4: &[u8] = &mut [0]; - let mut iovecs: [&IoVec; 4] = - [b1.into(), b2.into(), b3.into(), b4.into()]; + let b1: &[u8] = &mut []; + let b2: &[u8] = &mut []; + let b3: &[u8] = &mut []; + let b4: &[u8] = &mut []; + let mut iovecs = [ + IoSlice::new(b1), + IoSlice::new(b2), + IoSlice::new(b3), + IoSlice::new(b4), + ]; - assert_eq!(2, buf.bytes_vec(&mut iovecs)); + assert_eq!(2, buf.chunks_vectored(&mut iovecs)); assert_eq!(iovecs[0][..], b"llo"[..]); assert_eq!(iovecs[1][..], b"world"[..]); - assert_eq!(iovecs[2][..], b"\0"[..]); - assert_eq!(iovecs[3][..], b"\0"[..]); + assert_eq!(iovecs[2][..], b""[..]); + assert_eq!(iovecs[3][..], b""[..]); } buf.advance(3); { - let b1: &[u8] = &mut [0]; - let b2: &[u8] = &mut [0]; - let b3: &[u8] = &mut [0]; - let b4: &[u8] = &mut [0]; - let mut iovecs: [&IoVec; 4] = - [b1.into(), b2.into(), b3.into(), b4.into()]; + let b1: &[u8] = &mut []; + let b2: &[u8] = &mut []; + let b3: &[u8] = &mut []; + let b4: &[u8] = &mut []; + let mut iovecs = [ + IoSlice::new(b1), + IoSlice::new(b2), + IoSlice::new(b3), + IoSlice::new(b4), + ]; - assert_eq!(1, buf.bytes_vec(&mut iovecs)); + assert_eq!(1, buf.chunks_vectored(&mut iovecs)); assert_eq!(iovecs[0][..], b"world"[..]); - assert_eq!(iovecs[1][..], b"\0"[..]); - assert_eq!(iovecs[2][..], b"\0"[..]); - assert_eq!(iovecs[3][..], b"\0"[..]); + assert_eq!(iovecs[1][..], b""[..]); + assert_eq!(iovecs[2][..], b""[..]); + assert_eq!(iovecs[3][..], b""[..]); } buf.advance(3); { - let b1: &[u8] = &mut [0]; - let b2: &[u8] = &mut [0]; - let b3: &[u8] = &mut [0]; - let b4: &[u8] = &mut [0]; - let mut iovecs: [&IoVec; 4] = - [b1.into(), b2.into(), b3.into(), b4.into()]; + let b1: &[u8] = &mut []; + let b2: &[u8] = &mut []; + let b3: &[u8] = &mut []; + let b4: &[u8] = &mut []; + let mut iovecs = [ + IoSlice::new(b1), + IoSlice::new(b2), + IoSlice::new(b3), + IoSlice::new(b4), + ]; - assert_eq!(1, buf.bytes_vec(&mut iovecs)); + assert_eq!(1, buf.chunks_vectored(&mut iovecs)); assert_eq!(iovecs[0][..], b"ld"[..]); - assert_eq!(iovecs[1][..], b"\0"[..]); - assert_eq!(iovecs[2][..], b"\0"[..]); - assert_eq!(iovecs[3][..], b"\0"[..]); + assert_eq!(iovecs[1][..], b""[..]); + assert_eq!(iovecs[2][..], b""[..]); + assert_eq!(iovecs[3][..], b""[..]); } } + +#[test] +fn chain_get_bytes() { + let mut ab = Bytes::copy_from_slice(b"ab"); + let mut cd = Bytes::copy_from_slice(b"cd"); + let ab_ptr = ab.as_ptr(); + let cd_ptr = cd.as_ptr(); + let mut chain = (&mut ab).chain(&mut cd); + let a = chain.copy_to_bytes(1); + let bc = chain.copy_to_bytes(2); + let d = chain.copy_to_bytes(1); + + assert_eq!(Bytes::copy_from_slice(b"a"), a); + assert_eq!(Bytes::copy_from_slice(b"bc"), bc); + assert_eq!(Bytes::copy_from_slice(b"d"), d); + + // assert `get_bytes` did not allocate + assert_eq!(ab_ptr, a.as_ptr()); + // assert `get_bytes` did not allocate + assert_eq!(cd_ptr.wrapping_offset(1), d.as_ptr()); +} diff -Nru rust-bytes-0.4.12/tests/test_debug.rs rust-bytes-1.1.0/tests/test_debug.rs --- rust-bytes-0.4.12/tests/test_debug.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/tests/test_debug.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,4 +1,4 @@ -extern crate bytes; +#![warn(rust_2018_idioms)] use bytes::Bytes; diff -Nru rust-bytes-0.4.12/tests/test_from_buf.rs rust-bytes-1.1.0/tests/test_from_buf.rs --- rust-bytes-0.4.12/tests/test_from_buf.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/tests/test_from_buf.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -extern crate bytes; - -use bytes::{Buf, Bytes, BytesMut}; -use std::io::Cursor; - -const LONG: &'static [u8] = b"mary had a little lamb, little lamb, little lamb"; -const SHORT: &'static [u8] = b"hello world"; - -#[test] -fn collect_to_vec() { - let buf: Vec = Cursor::new(SHORT).collect(); - assert_eq!(buf, SHORT); - - let buf: Vec = Cursor::new(LONG).collect(); - assert_eq!(buf, LONG); -} - -#[test] -fn collect_to_bytes() { - let buf: Bytes = Cursor::new(SHORT).collect(); - assert_eq!(buf, SHORT); - - let buf: Bytes = Cursor::new(LONG).collect(); - assert_eq!(buf, LONG); -} - -#[test] -fn collect_to_bytes_mut() { - let buf: BytesMut = Cursor::new(SHORT).collect(); - assert_eq!(buf, SHORT); - - let buf: BytesMut = Cursor::new(LONG).collect(); - assert_eq!(buf, LONG); -} diff -Nru rust-bytes-0.4.12/tests/test_iter.rs rust-bytes-1.1.0/tests/test_iter.rs --- rust-bytes-0.4.12/tests/test_iter.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/tests/test_iter.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,20 +1,19 @@ -extern crate bytes; +#![warn(rust_2018_idioms)] -use bytes::{Buf, IntoBuf, Bytes}; +use bytes::Bytes; #[test] fn iter_len() { - let buf = Bytes::from(&b"hello world"[..]).into_buf(); + let buf = Bytes::from_static(b"hello world"); let iter = buf.iter(); assert_eq!(iter.size_hint(), (11, Some(11))); assert_eq!(iter.len(), 11); } - #[test] fn empty_iter_len() { - let buf = Bytes::from(&b""[..]).into_buf(); + let buf = Bytes::from_static(b""); let iter = buf.iter(); assert_eq!(iter.size_hint(), (0, Some(0))); diff -Nru rust-bytes-0.4.12/tests/test_reader.rs rust-bytes-1.1.0/tests/test_reader.rs --- rust-bytes-0.4.12/tests/test_reader.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/tests/test_reader.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,13 +1,14 @@ -extern crate bytes; +#![warn(rust_2018_idioms)] +#![cfg(feature = "std")] -use std::io::{BufRead, Cursor, Read}; +use std::io::{BufRead, Read}; use bytes::Buf; #[test] fn read() { - let buf1 = Cursor::new(b"hello "); - let buf2 = Cursor::new(b"world"); + let buf1 = &b"hello "[..]; + let buf2 = &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(); @@ -16,8 +17,8 @@ #[test] fn buf_read() { - let buf1 = Cursor::new(b"hell"); - let buf2 = Cursor::new(b"o\nworld"); + let buf1 = &b"hell"[..]; + let buf2 = &b"o\nworld"[..]; let mut reader = Buf::chain(buf1, buf2).reader(); let mut line = String::new(); reader.read_line(&mut line).unwrap(); diff -Nru rust-bytes-0.4.12/tests/test_serde.rs rust-bytes-1.1.0/tests/test_serde.rs --- rust-bytes-0.4.12/tests/test_serde.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/tests/test_serde.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,8 +1,7 @@ #![cfg(feature = "serde")] +#![warn(rust_2018_idioms)] -extern crate bytes; -extern crate serde_test; -use serde_test::{Token, assert_tokens}; +use serde_test::{assert_tokens, Token}; #[test] fn test_ser_de_empty() { diff -Nru rust-bytes-0.4.12/tests/test_take.rs rust-bytes-1.1.0/tests/test_take.rs --- rust-bytes-0.4.12/tests/test_take.rs 2018-11-26 05:44:40.000000000 +0000 +++ rust-bytes-1.1.0/tests/test_take.rs 1973-11-29 21:33:09.000000000 +0000 @@ -1,13 +1,32 @@ -extern crate bytes; +#![warn(rust_2018_idioms)] -use bytes::Buf; -use std::io::Cursor; +use bytes::buf::Buf; +use bytes::Bytes; #[test] fn long_take() { - // Tests that take with a size greater than the buffer length will not + // Tests that get a take with a size greater than the buffer length will not // overrun the buffer. Regression test for #138. - let buf = Cursor::new(b"hello world").take(100); + let buf = b"hello world".take(100); assert_eq!(11, buf.remaining()); - assert_eq!(b"hello world", buf.bytes()); + assert_eq!(b"hello world", buf.chunk()); +} + +#[test] +fn take_copy_to_bytes() { + let mut abcd = Bytes::copy_from_slice(b"abcd"); + let abcd_ptr = abcd.as_ptr(); + let mut take = (&mut abcd).take(2); + let a = take.copy_to_bytes(1); + assert_eq!(Bytes::copy_from_slice(b"a"), a); + // assert `to_bytes` did not allocate + assert_eq!(abcd_ptr, a.as_ptr()); + assert_eq!(Bytes::copy_from_slice(b"bcd"), abcd); +} + +#[test] +#[should_panic] +fn take_copy_to_bytes_panics() { + let abcd = Bytes::copy_from_slice(b"abcd"); + abcd.take(2).copy_to_bytes(3); }