mirror of
https://github.com/ntex-rs/ntex.git
synced 2025-04-01 20:07:39 +03:00
fork bytes crate
This commit is contained in:
parent
f577c2acf3
commit
45463f209b
23 changed files with 7502 additions and 0 deletions
90
ntex-bytes/CHANGELOG.md
Normal file
90
ntex-bytes/CHANGELOG.md
Normal file
|
@ -0,0 +1,90 @@
|
|||
# 0.5.0 (06-25-2021)
|
||||
|
||||
* Initial fork
|
||||
|
||||
# 0.4.12 (March 6, 2019)
|
||||
|
||||
### Added
|
||||
- Implement `FromIterator<&'a u8>` for `BytesMut`/`Bytes` (#244).
|
||||
- Implement `Buf` for `VecDeque` (#249).
|
||||
|
||||
# 0.4.11 (November 17, 2018)
|
||||
|
||||
* Use raw pointers for potentially racy loads (#233).
|
||||
* Implement `BufRead` for `buf::Reader` (#232).
|
||||
* Documentation tweaks (#234).
|
||||
|
||||
# 0.4.10 (September 4, 2018)
|
||||
|
||||
* impl `Buf` and `BufMut` for `Either` (#225).
|
||||
* Add `Bytes::slice_ref` (#208).
|
||||
|
||||
# 0.4.9 (July 12, 2018)
|
||||
|
||||
* Add 128 bit number support behind a feature flag (#209).
|
||||
* Implement `IntoBuf` for `&mut [u8]`
|
||||
|
||||
# 0.4.8 (May 25, 2018)
|
||||
|
||||
* Fix panic in `BytesMut` `FromIterator` implementation.
|
||||
* Bytes: Recycle space when reserving space in vec mode (#197).
|
||||
* Bytes: Add resize fn (#203).
|
||||
|
||||
# 0.4.7 (April 27, 2018)
|
||||
|
||||
* Make `Buf` and `BufMut` usable as trait objects (#186).
|
||||
* impl BorrowMut for BytesMut (#185).
|
||||
* Improve accessor performance (#195).
|
||||
|
||||
# 0.4.6 (Janary 8, 2018)
|
||||
|
||||
* Implement FromIterator for Bytes/BytesMut (#148).
|
||||
* Add `advance` fn to Bytes/BytesMut (#166).
|
||||
* Add `unsplit` fn to `BytesMut` (#162, #173).
|
||||
* Improvements to Bytes split fns (#92).
|
||||
|
||||
# 0.4.5 (August 12, 2017)
|
||||
|
||||
* Fix range bug in `Take::bytes`
|
||||
* Misc performance improvements
|
||||
* Add extra `PartialEq` implementations.
|
||||
* Add `Bytes::with_capacity`
|
||||
* Implement `AsMut[u8]` for `BytesMut`
|
||||
|
||||
# 0.4.4 (May 26, 2017)
|
||||
|
||||
* Add serde support behind feature flag
|
||||
* Add `extend_from_slice` on `Bytes` and `BytesMut`
|
||||
* Add `truncate` and `clear` on `Bytes`
|
||||
* Misc additional std trait implementations
|
||||
* Misc performance improvements
|
||||
|
||||
# 0.4.3 (April 30, 2017)
|
||||
|
||||
* Fix Vec::advance_mut bug
|
||||
* Bump minimum Rust version to 1.15
|
||||
* Misc performance tweaks
|
||||
|
||||
# 0.4.2 (April 5, 2017)
|
||||
|
||||
* Misc performance tweaks
|
||||
* Improved `Debug` implementation for `Bytes`
|
||||
* Avoid some incorrect assert panics
|
||||
|
||||
# 0.4.1 (March 15, 2017)
|
||||
|
||||
* Expose `buf` module and have most types available from there vs. root.
|
||||
* Implement `IntoBuf` for `T: Buf`.
|
||||
* Add `FromBuf` and `Buf::collect`.
|
||||
* Add iterator adapter for `Buf`.
|
||||
* Add scatter/gather support to `Buf` and `BufMut`.
|
||||
* Add `Buf::chain`.
|
||||
* Reduce allocations on repeated calls to `BytesMut::reserve`.
|
||||
* Implement `Debug` for more types.
|
||||
* Remove `Source` in favor of `IntoBuf`.
|
||||
* Implement `Extend` for `BytesMut`.
|
||||
|
||||
|
||||
# 0.4.0 (February 24, 2017)
|
||||
|
||||
* Initial release
|
19
ntex-bytes/Cargo.toml
Normal file
19
ntex-bytes/Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "ntex-bytes"
|
||||
version = "0.5.0"
|
||||
license = "MIT"
|
||||
authors = ["Carl Lerche <me@carllerche.com>"]
|
||||
description = "Types and traits for working with bytes (bytes crate fork)"
|
||||
documentation = "https://docs.rs/ntex-bytes"
|
||||
repository = "https://github.com/ntex/bytes"
|
||||
readme = "README.md"
|
||||
keywords = ["buffers", "zero-copy", "io"]
|
||||
categories = ["network-programming", "data-structures"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0", optional = true }
|
||||
bytes = "1.0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
serde_test = "1.0"
|
25
ntex-bytes/LICENSE
Normal file
25
ntex-bytes/LICENSE
Normal file
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2018 Carl Lerche
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
45
ntex-bytes/README.md
Normal file
45
ntex-bytes/README.md
Normal file
|
@ -0,0 +1,45 @@
|
|||
# Bytes
|
||||
|
||||
A utility library for working with bytes. This is fork of bytes crate (https://github.com/tokio-rs/bytes)
|
||||
|
||||
[![Crates.io][crates-badge]][crates-url]
|
||||
[![Build Status][azure-badge]][azure-url]
|
||||
|
||||
[crates-badge]: https://img.shields.io/crates/v/bytes.svg
|
||||
[crates-url]: https://crates.io/crates/ntex-bytes
|
||||
|
||||
[Documentation](https://docs.rs/ntex-bytes)
|
||||
|
||||
## Usage
|
||||
|
||||
To use `bytes`, first add this to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
bytes = "0.4.12"
|
||||
```
|
||||
|
||||
Next, add this to your crate:
|
||||
|
||||
```rust
|
||||
use bytes::{Bytes, BytesMut, Buf, BufMut};
|
||||
```
|
||||
|
||||
## Serde support
|
||||
|
||||
Serde support is optional and disabled by default. To enable use the feature `serde`.
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
bytes = { version = "0.4.12", features = ["serde"] }
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the [MIT license](LICENSE).
|
||||
|
||||
### Contribution
|
||||
|
||||
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.
|
187
ntex-bytes/benches/buf.rs
Normal file
187
ntex-bytes/benches/buf.rs
Normal file
|
@ -0,0 +1,187 @@
|
|||
#![feature(test)]
|
||||
#![deny(warnings, rust_2018_idioms)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use ntex_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 bytes(&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 bytes(&self) -> &[u8] {
|
||||
self.inner.bytes()
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
bench!(option, option);
|
||||
}
|
||||
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);
|
||||
}
|
255
ntex-bytes/benches/bytes.rs
Normal file
255
ntex-bytes/benches/bytes.rs
Normal file
|
@ -0,0 +1,255 @@
|
|||
#![feature(test)]
|
||||
#![deny(warnings, rust_2018_idioms)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use ntex_bytes::{BufMut, Bytes, 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 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][..]);
|
||||
|
||||
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_inline(b: &mut Bencher) {
|
||||
let mut buf = BytesMut::with_capacity(8);
|
||||
buf.put(&[0u8; 8][..]);
|
||||
|
||||
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_inline(b: &mut Bencher) {
|
||||
let bytes = Bytes::from_static(b"hello world");
|
||||
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
test::black_box(&bytes.clone());
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn clone_static(b: &mut Bencher) {
|
||||
let bytes = Bytes::from_static(
|
||||
"hello world 1234567890 and have a good byte 0987654321".as_bytes(),
|
||||
);
|
||||
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
test::black_box(&bytes.clone());
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn clone_arc(b: &mut Bencher) {
|
||||
let bytes =
|
||||
Bytes::from("hello world 1234567890 and have a good byte 0987654321".as_bytes());
|
||||
|
||||
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 from_long_slice(b: &mut Bencher) {
|
||||
let data = [0u8; 128];
|
||||
b.bytes = data.len() as u64;
|
||||
b.iter(|| {
|
||||
let buf = BytesMut::from(&data[..]);
|
||||
test::black_box(buf);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn slice_empty(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let b = Bytes::from(vec![17; 1024]).clone();
|
||||
for i in 0..1000 {
|
||||
test::black_box(b.slice(i % 100..i % 100));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn slice_short_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 {
|
||||
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) {
|
||||
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));
|
||||
}
|
||||
})
|
||||
}
|
939
ntex-bytes/src/buf/buf_impl.rs
Normal file
939
ntex-bytes/src/buf/buf_impl.rs
Normal file
|
@ -0,0 +1,939 @@
|
|||
use std::{cmp, io::IoSlice, mem, ptr};
|
||||
|
||||
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<ret> trick is to avoid keeping a borrow on self
|
||||
// when advance() is called (mut borrow) and to call bytes() only once
|
||||
let ret = $this
|
||||
.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 ntex_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 `bytes`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_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 ntex_bytes::Buf;
|
||||
///
|
||||
/// let mut buf = &b"hello world"[..];
|
||||
///
|
||||
/// assert_eq!(buf.bytes(), &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.
|
||||
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, `bytes_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 `bytes_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 `bytes_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
|
||||
fn bytes_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 `bytes` will return a slice starting `cnt` bytes
|
||||
/// further into the underlying buffer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 ntex_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 remaining bytes inside self and returns new instance of `Bytes`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::{Buf};
|
||||
///
|
||||
/// let bytes = "hello world".to_bytes();
|
||||
/// assert_eq!(&bytes[..], &b"hello world"[..]);
|
||||
/// ```
|
||||
fn to_bytes(&mut self) -> crate::Bytes {
|
||||
use super::BufMut;
|
||||
let mut ret = crate::BytesMut::with_capacity(self.remaining());
|
||||
ret.put(self);
|
||||
ret.freeze()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Buf + ?Sized> Buf for &mut T {
|
||||
fn remaining(&self) -> usize {
|
||||
(**self).remaining()
|
||||
}
|
||||
|
||||
fn chunk(&self) -> &[u8] {
|
||||
(**self).chunk()
|
||||
}
|
||||
|
||||
fn bytes_vectored<'b>(&'b self, dst: &mut [IoSlice<'b>]) -> usize {
|
||||
(**self).bytes_vectored(dst)
|
||||
}
|
||||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
(**self).advance(cnt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Buf + ?Sized> Buf for Box<T> {
|
||||
fn remaining(&self) -> usize {
|
||||
(**self).remaining()
|
||||
}
|
||||
|
||||
fn chunk(&self) -> &[u8] {
|
||||
(**self).chunk()
|
||||
}
|
||||
|
||||
fn bytes_vectored<'b>(&'b self, dst: &mut [IoSlice<'b>]) -> usize {
|
||||
(**self).bytes_vectored(dst)
|
||||
}
|
||||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
(**self).advance(cnt)
|
||||
}
|
||||
}
|
||||
|
||||
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..];
|
||||
}
|
||||
}
|
||||
|
||||
impl Buf for &str {
|
||||
#[inline]
|
||||
fn remaining(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn chunk(&self) -> &[u8] {
|
||||
self.as_bytes()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
*self = &self[cnt..];
|
||||
}
|
||||
}
|
||||
|
||||
impl Buf for Option<[u8; 1]> {
|
||||
fn remaining(&self) -> usize {
|
||||
if self.is_some() {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk(&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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<[u8]>> Buf for std::io::Cursor<T> {
|
||||
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) {}
|
964
ntex-bytes/src/buf/buf_mut.rs
Normal file
964
ntex-bytes/src/buf/buf_mut.rs
Normal file
|
@ -0,0 +1,964 @@
|
|||
use super::Writer;
|
||||
|
||||
use std::{cmp, mem, ptr, usize};
|
||||
|
||||
/// A trait for values that provide sequential write access to bytes.
|
||||
///
|
||||
/// Write bytes to a buffer
|
||||
///
|
||||
/// A buffer stores bytes in memory such that write operations are infallible.
|
||||
/// The underlying storage may or may not be in contiguous memory. A `BufMut`
|
||||
/// value is a cursor into the buffer. Writing to `BufMut` advances the cursor
|
||||
/// position.
|
||||
///
|
||||
/// The simplest `BufMut` is a `Vec<u8>`.
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
///
|
||||
/// buf.put("hello world");
|
||||
///
|
||||
/// assert_eq!(buf, b"hello world");
|
||||
/// ```
|
||||
pub 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`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut dst = [0; 10];
|
||||
/// let mut buf = &mut dst[..];
|
||||
///
|
||||
/// let original_remaining = buf.remaining_mut();
|
||||
/// buf.put("hello");
|
||||
///
|
||||
/// assert_eq!(original_remaining - 5, buf.remaining_mut());
|
||||
/// ```
|
||||
///
|
||||
/// # Implementer notes
|
||||
///
|
||||
/// Implementations of `remaining_mut` should ensure that the return value
|
||||
/// does not change unless a call is made to `advance_mut` or any other
|
||||
/// function that is documented to change the `BufMut`'s current position.
|
||||
fn remaining_mut(&self) -> usize;
|
||||
|
||||
/// Advance the internal cursor of the BufMut
|
||||
///
|
||||
/// The next call to `bytes_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
|
||||
/// being advanced past have been initialized.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = Vec::with_capacity(16);
|
||||
///
|
||||
/// unsafe {
|
||||
/// buf.bytes_mut()[0] = b'h';
|
||||
/// buf.bytes_mut()[1] = b'e';
|
||||
///
|
||||
/// buf.advance_mut(2);
|
||||
///
|
||||
/// buf.bytes_mut()[0] = b'l';
|
||||
/// buf.bytes_mut()[1..3].copy_from_slice(b"lo");
|
||||
///
|
||||
/// buf.advance_mut(3);
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(5, buf.len());
|
||||
/// assert_eq!(buf, b"hello");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function **may** panic if `cnt > self.remaining_mut()`.
|
||||
///
|
||||
/// # Implementer notes
|
||||
///
|
||||
/// It is recommended for implementations of `advance_mut` to panic if
|
||||
/// `cnt > self.remaining_mut()`. If the implementation does not panic,
|
||||
/// the call must behave as if `cnt == self.remaining_mut()`.
|
||||
///
|
||||
/// A call with `cnt == 0` should never panic and be a no-op.
|
||||
unsafe fn advance_mut(&mut self, cnt: usize);
|
||||
|
||||
/// Returns true if there is space in `self` for more bytes.
|
||||
///
|
||||
/// This is equivalent to `self.remaining_mut() != 0`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut dst = [0; 5];
|
||||
/// let mut buf = &mut dst[..];
|
||||
///
|
||||
/// assert!(buf.has_remaining_mut());
|
||||
///
|
||||
/// buf.put("hello");
|
||||
///
|
||||
/// assert!(!buf.has_remaining_mut());
|
||||
/// ```
|
||||
#[inline]
|
||||
fn has_remaining_mut(&self) -> bool {
|
||||
self.remaining_mut() > 0
|
||||
}
|
||||
|
||||
/// Returns a mutable slice starting at the current BufMut position and of
|
||||
/// length between 0 and `BufMut::remaining_mut()`. Note that this *can* be shorter than the
|
||||
/// whole remainder of the buffer (this allows non-continuous implementation).
|
||||
///
|
||||
/// This is a lower level function. Most operations are done with other
|
||||
/// functions.
|
||||
///
|
||||
/// The returned byte slice may represent uninitialized memory.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = Vec::with_capacity(16);
|
||||
///
|
||||
/// unsafe {
|
||||
/// buf.bytes_mut()[0] = b'h';
|
||||
/// buf.bytes_mut()[1] = b'e';
|
||||
///
|
||||
/// buf.advance_mut(2);
|
||||
///
|
||||
/// buf.bytes_mut()[0] = b'l';
|
||||
/// buf.bytes_mut()[1..3].copy_from_slice(b"lo");
|
||||
///
|
||||
/// buf.advance_mut(3);
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(5, buf.len());
|
||||
/// assert_eq!(buf, b"hello");
|
||||
/// ```
|
||||
///
|
||||
/// # 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
|
||||
/// return an empty slice.
|
||||
unsafe fn chunk_mut(&mut self) -> &mut [u8];
|
||||
|
||||
/// Transfer bytes into `self` from `src` and advance the cursor by the
|
||||
/// number of bytes written.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
///
|
||||
/// buf.put_u8(b'h');
|
||||
/// buf.put(&b"ello"[..]);
|
||||
/// buf.put(" world");
|
||||
///
|
||||
/// assert_eq!(buf, b"hello world");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `self` does not have enough capacity to contain `src`.
|
||||
fn put<T: super::Buf>(&mut self, mut src: T)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
assert!(self.remaining_mut() >= src.remaining());
|
||||
|
||||
while src.has_remaining() {
|
||||
let l;
|
||||
|
||||
unsafe {
|
||||
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);
|
||||
}
|
||||
|
||||
src.advance(l);
|
||||
unsafe {
|
||||
self.advance_mut(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Transfer bytes into `self` from `src` and advance the cursor by the
|
||||
/// number of bytes written.
|
||||
///
|
||||
/// `self` must have enough remaining capacity to contain all of `src`.
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut dst = [0; 6];
|
||||
///
|
||||
/// {
|
||||
/// let mut buf = &mut dst[..];
|
||||
/// buf.put_slice(b"hello");
|
||||
///
|
||||
/// assert_eq!(1, buf.remaining_mut());
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(b"hello\0", &dst);
|
||||
/// ```
|
||||
fn put_slice(&mut self, src: &[u8]) {
|
||||
let mut off = 0;
|
||||
|
||||
assert!(self.remaining_mut() >= src.len(), "buffer overflow");
|
||||
|
||||
while off < src.len() {
|
||||
let cnt;
|
||||
|
||||
unsafe {
|
||||
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);
|
||||
|
||||
off += cnt;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
self.advance_mut(cnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes an unsigned 8 bit integer to `self`.
|
||||
///
|
||||
/// The current position is advanced by 1.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_u8(0x01);
|
||||
/// assert_eq!(buf, b"\x01");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
fn put_u8(&mut self, n: u8) {
|
||||
let src = [n];
|
||||
self.put_slice(&src);
|
||||
}
|
||||
|
||||
/// Writes a signed 8 bit integer to `self`.
|
||||
///
|
||||
/// The current position is advanced by 1.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_i8(0x01);
|
||||
/// assert_eq!(buf, b"\x01");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
fn put_i8(&mut self, n: i8) {
|
||||
let src = [n as u8];
|
||||
self.put_slice(&src)
|
||||
}
|
||||
|
||||
/// Writes an unsigned 16 bit integer to `self` in big-endian byte order.
|
||||
///
|
||||
/// The current position is advanced by 2.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_u16(0x0809);
|
||||
/// assert_eq!(buf, b"\x08\x09");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
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.
|
||||
///
|
||||
/// The current position is advanced by 2.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_u16_le(0x0809);
|
||||
/// assert_eq!(buf, b"\x09\x08");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
fn put_u16_le(&mut self, n: u16) {
|
||||
self.put_slice(&n.to_le_bytes())
|
||||
}
|
||||
|
||||
/// Writes a signed 16 bit integer to `self` in big-endian byte order.
|
||||
///
|
||||
/// The current position is advanced by 2.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_i16(0x0809);
|
||||
/// assert_eq!(buf, b"\x08\x09");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
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.
|
||||
///
|
||||
/// The current position is advanced by 2.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_i16_le(0x0809);
|
||||
/// assert_eq!(buf, b"\x09\x08");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
fn put_i16_le(&mut self, n: i16) {
|
||||
self.put_slice(&n.to_le_bytes())
|
||||
}
|
||||
|
||||
/// Writes an unsigned 32 bit integer to `self` in big-endian byte order.
|
||||
///
|
||||
/// The current position is advanced by 4.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_u32(0x0809A0A1);
|
||||
/// assert_eq!(buf, b"\x08\x09\xA0\xA1");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
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.
|
||||
///
|
||||
/// The current position is advanced by 4.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_u32_le(0x0809A0A1);
|
||||
/// assert_eq!(buf, b"\xA1\xA0\x09\x08");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
fn put_u32_le(&mut self, n: u32) {
|
||||
self.put_slice(&n.to_le_bytes())
|
||||
}
|
||||
|
||||
/// Writes a signed 32 bit integer to `self` in big-endian byte order.
|
||||
///
|
||||
/// The current position is advanced by 4.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_i32(0x0809A0A1);
|
||||
/// assert_eq!(buf, b"\x08\x09\xA0\xA1");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
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.
|
||||
///
|
||||
/// The current position is advanced by 4.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_i32_le(0x0809A0A1);
|
||||
/// assert_eq!(buf, b"\xA1\xA0\x09\x08");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
fn put_i32_le(&mut self, n: i32) {
|
||||
self.put_slice(&n.to_le_bytes())
|
||||
}
|
||||
|
||||
/// Writes an unsigned 64 bit integer to `self` in the big-endian byte order.
|
||||
///
|
||||
/// The current position is advanced by 8.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_u64(0x0102030405060708);
|
||||
/// assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
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.
|
||||
///
|
||||
/// The current position is advanced by 8.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_u64_le(0x0102030405060708);
|
||||
/// assert_eq!(buf, b"\x08\x07\x06\x05\x04\x03\x02\x01");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
fn put_u64_le(&mut self, n: u64) {
|
||||
self.put_slice(&n.to_le_bytes())
|
||||
}
|
||||
|
||||
/// Writes a signed 64 bit integer to `self` in the big-endian byte order.
|
||||
///
|
||||
/// The current position is advanced by 8.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_i64(0x0102030405060708);
|
||||
/// assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
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.
|
||||
///
|
||||
/// The current position is advanced by 8.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_i64_le(0x0102030405060708);
|
||||
/// assert_eq!(buf, b"\x08\x07\x06\x05\x04\x03\x02\x01");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
fn put_i64_le(&mut self, n: i64) {
|
||||
self.put_slice(&n.to_le_bytes())
|
||||
}
|
||||
|
||||
/// Writes an unsigned 128 bit integer to `self` in the big-endian byte order.
|
||||
///
|
||||
/// The current position is advanced by 16.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_u128(0x01020304050607080910111213141516);
|
||||
/// assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
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.
|
||||
///
|
||||
/// The current position is advanced by 16.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_u128_le(0x01020304050607080910111213141516);
|
||||
/// assert_eq!(buf, b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
fn put_u128_le(&mut self, n: u128) {
|
||||
self.put_slice(&n.to_le_bytes())
|
||||
}
|
||||
|
||||
/// Writes a signed 128 bit integer to `self` in the big-endian byte order.
|
||||
///
|
||||
/// The current position is advanced by 16.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_i128(0x01020304050607080910111213141516);
|
||||
/// assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
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.
|
||||
///
|
||||
/// The current position is advanced by 16.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_i128_le(0x01020304050607080910111213141516);
|
||||
/// assert_eq!(buf, b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
fn put_i128_le(&mut self, n: i128) {
|
||||
self.put_slice(&n.to_le_bytes())
|
||||
}
|
||||
|
||||
/// Writes an unsigned n-byte integer to `self` in big-endian byte order.
|
||||
///
|
||||
/// The current position is advanced by `nbytes`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_uint(0x010203, 3);
|
||||
/// assert_eq!(buf, b"\x01\x02\x03");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
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.
|
||||
///
|
||||
/// The current position is advanced by `nbytes`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_uint_le(0x010203, 3);
|
||||
/// assert_eq!(buf, b"\x03\x02\x01");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
fn put_uint_le(&mut self, n: u64, nbytes: usize) {
|
||||
self.put_slice(&n.to_le_bytes()[0..nbytes]);
|
||||
}
|
||||
|
||||
/// Writes a signed n-byte integer to `self` in big-endian byte order.
|
||||
///
|
||||
/// The current position is advanced by `nbytes`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_int(0x010203, 3);
|
||||
/// assert_eq!(buf, b"\x01\x02\x03");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
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.
|
||||
///
|
||||
/// The current position is advanced by `nbytes`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_int_le(0x010203, 3);
|
||||
/// assert_eq!(buf, b"\x03\x02\x01");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
fn put_int_le(&mut self, n: i64, nbytes: usize) {
|
||||
self.put_slice(&n.to_le_bytes()[0..nbytes]);
|
||||
}
|
||||
|
||||
/// Writes an IEEE754 single-precision (4 bytes) floating point number to
|
||||
/// `self` in big-endian byte order.
|
||||
///
|
||||
/// The current position is advanced by 4.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_f32(1.2f32);
|
||||
/// assert_eq!(buf, b"\x3F\x99\x99\x9A");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
fn put_f32(&mut self, n: f32) {
|
||||
self.put_u32(n.to_bits());
|
||||
}
|
||||
|
||||
/// Writes an IEEE754 single-precision (4 bytes) floating point number to
|
||||
/// `self` in little-endian byte order.
|
||||
///
|
||||
/// The current position is advanced by 4.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_f32_le(1.2f32);
|
||||
/// assert_eq!(buf, b"\x9A\x99\x99\x3F");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
fn put_f32_le(&mut self, n: f32) {
|
||||
self.put_u32_le(n.to_bits());
|
||||
}
|
||||
|
||||
/// Writes an IEEE754 double-precision (8 bytes) floating point number to
|
||||
/// `self` in big-endian byte order.
|
||||
///
|
||||
/// The current position is advanced by 8.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_f64(1.2f64);
|
||||
/// assert_eq!(buf, b"\x3F\xF3\x33\x33\x33\x33\x33\x33");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
fn put_f64(&mut self, n: f64) {
|
||||
self.put_u64(n.to_bits());
|
||||
}
|
||||
|
||||
/// Writes an IEEE754 double-precision (8 bytes) floating point number to
|
||||
/// `self` in little-endian byte order.
|
||||
///
|
||||
/// The current position is advanced by 8.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_f64_le(1.2f64);
|
||||
/// assert_eq!(buf, b"\x33\x33\x33\x33\x33\x33\xF3\x3F");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
#[inline]
|
||||
fn put_f64_le(&mut self, n: f64) {
|
||||
self.put_u64_le(n.to_bits());
|
||||
}
|
||||
|
||||
/// Creates an adaptor which implements the `Write` trait for `self`.
|
||||
///
|
||||
/// This function returns a new value which implements `Write` by adapting
|
||||
/// the `Write` trait functions to the `BufMut` trait functions. Given that
|
||||
/// `BufMut` operations are infallible, none of the `Write` functions will
|
||||
/// return with `Err`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::BufMut;
|
||||
/// use std::io::Write;
|
||||
///
|
||||
/// let mut buf = vec![].writer();
|
||||
///
|
||||
/// let num = buf.write(&b"hello world"[..]).unwrap();
|
||||
/// assert_eq!(11, num);
|
||||
///
|
||||
/// let buf = buf.into_inner();
|
||||
///
|
||||
/// assert_eq!(*buf, b"hello world"[..]);
|
||||
/// ```
|
||||
fn writer(self) -> Writer<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
super::writer::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BufMut + ?Sized> BufMut for &mut T {
|
||||
fn remaining_mut(&self) -> usize {
|
||||
(**self).remaining_mut()
|
||||
}
|
||||
|
||||
unsafe fn chunk_mut(&mut self) -> &mut [u8] {
|
||||
(**self).chunk_mut()
|
||||
}
|
||||
|
||||
unsafe fn advance_mut(&mut self, cnt: usize) {
|
||||
(**self).advance_mut(cnt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BufMut + ?Sized> BufMut for Box<T> {
|
||||
fn remaining_mut(&self) -> usize {
|
||||
(**self).remaining_mut()
|
||||
}
|
||||
|
||||
unsafe fn chunk_mut(&mut self) -> &mut [u8] {
|
||||
(**self).chunk_mut()
|
||||
}
|
||||
|
||||
unsafe fn advance_mut(&mut self, cnt: usize) {
|
||||
(**self).advance_mut(cnt)
|
||||
}
|
||||
}
|
||||
|
||||
impl BufMut for &mut [u8] {
|
||||
#[inline]
|
||||
fn remaining_mut(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn chunk_mut(&mut self) -> &mut [u8] {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn advance_mut(&mut self, cnt: usize) {
|
||||
// Lifetime dance taken from `impl Write for &mut [u8]`.
|
||||
let (_, b) = std::mem::replace(self, &mut []).split_at_mut(cnt);
|
||||
*self = b;
|
||||
}
|
||||
}
|
||||
|
||||
impl BufMut for Vec<u8> {
|
||||
#[inline]
|
||||
fn remaining_mut(&self) -> usize {
|
||||
usize::MAX - 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);
|
||||
}
|
||||
|
||||
self.set_len(len + cnt);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn chunk_mut(&mut self) -> &mut [u8] {
|
||||
use std::slice;
|
||||
|
||||
if self.capacity() == self.len() {
|
||||
self.reserve(64); // Grow the vec
|
||||
}
|
||||
|
||||
let cap = self.capacity();
|
||||
let len = self.len();
|
||||
|
||||
let ptr = self.as_mut_ptr();
|
||||
&mut slice::from_raw_parts_mut(ptr, cap)[len..]
|
||||
}
|
||||
}
|
||||
|
||||
// The existence of this function makes the compiler catch if the BufMut
|
||||
// trait is "object-safe" or not.
|
||||
fn _assert_trait_object(_b: &dyn BufMut) {}
|
132
ntex-bytes/src/buf/iter.rs
Normal file
132
ntex-bytes/src/buf/iter.rs
Normal file
|
@ -0,0 +1,132 @@
|
|||
use crate::Buf;
|
||||
|
||||
/// Iterator over the bytes contained by the buffer.
|
||||
///
|
||||
/// This struct is created by the [`iter`] method on [`Buf`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::{Buf, Bytes};
|
||||
///
|
||||
/// 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'));
|
||||
/// assert_eq!(iter.next(), Some(b'c'));
|
||||
/// assert_eq!(iter.next(), None);
|
||||
/// ```
|
||||
///
|
||||
/// [`iter`]: trait.Buf.html#method.iter
|
||||
/// [`Buf`]: trait.Buf.html
|
||||
#[derive(Debug)]
|
||||
pub struct IntoIter<T> {
|
||||
inner: T,
|
||||
}
|
||||
|
||||
impl<T> IntoIter<T> {
|
||||
/// Creates an iterator over the bytes contained by the buffer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ntex_bytes::{Buf, Bytes};
|
||||
/// use ntex_bytes::buf::IntoIter;
|
||||
///
|
||||
/// let buf = Bytes::from_static(b"abc");
|
||||
/// let mut iter = IntoIter::new(buf);
|
||||
///
|
||||
/// 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 fn new(inner: T) -> IntoIter<T> {
|
||||
IntoIter { inner }
|
||||
}
|
||||
/// Consumes this `IntoIter`, returning the underlying value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use ntex_bytes::{Buf, Bytes};
|
||||
///
|
||||
/// let buf = Bytes::from(&b"abc"[..]);
|
||||
/// let mut iter = buf.into_iter();
|
||||
///
|
||||
/// assert_eq!(iter.next(), Some(b'a'));
|
||||
///
|
||||
/// let buf = iter.into_inner();
|
||||
/// assert_eq!(2, buf.remaining());
|
||||
/// ```
|
||||
pub fn into_inner(self) -> T {
|
||||
self.inner
|
||||
}
|
||||
|
||||
/// Gets a reference to the underlying `Buf`.
|
||||
///
|
||||
/// It is inadvisable to directly read from the underlying `Buf`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use ntex_bytes::{Buf, Bytes};
|
||||
///
|
||||
/// let buf = Bytes::from(&b"abc"[..]);
|
||||
/// let mut iter = buf.into_iter();
|
||||
///
|
||||
/// assert_eq!(iter.next(), Some(b'a'));
|
||||
///
|
||||
/// assert_eq!(2, iter.get_ref().remaining());
|
||||
/// ```
|
||||
pub fn get_ref(&self) -> &T {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the underlying `Buf`.
|
||||
///
|
||||
/// It is inadvisable to directly read from the underlying `Buf`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use ntex_bytes::{Buf, BytesMut};
|
||||
///
|
||||
/// let buf = BytesMut::from(&b"abc"[..]);
|
||||
/// let mut iter = buf.into_iter();
|
||||
///
|
||||
/// assert_eq!(iter.next(), Some(b'a'));
|
||||
///
|
||||
/// iter.get_mut().advance(1);
|
||||
///
|
||||
/// assert_eq!(iter.next(), Some(b'c'));
|
||||
/// ```
|
||||
pub fn get_mut(&mut self) -> &mut T {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Buf> Iterator for IntoIter<T> {
|
||||
type Item = u8;
|
||||
|
||||
fn next(&mut self) -> Option<u8> {
|
||||
if !self.inner.has_remaining() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let b = self.inner.chunk()[0];
|
||||
self.inner.advance(1);
|
||||
|
||||
Some(b)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let rem = self.inner.remaining();
|
||||
(rem, Some(rem))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Buf> ExactSizeIterator for IntoIter<T> {}
|
27
ntex-bytes/src/buf/mod.rs
Normal file
27
ntex-bytes/src/buf/mod.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
//! Utilities for working with buffers.
|
||||
//!
|
||||
//! A buffer is any structure that contains a sequence of bytes. The bytes may
|
||||
//! or may not be stored in contiguous memory. This module contains traits used
|
||||
//! to abstract over buffers as well as utilities for working with buffer types.
|
||||
//!
|
||||
//! # `Buf`, `BufMut`
|
||||
//!
|
||||
//! These are the two foundational traits for abstractly working with buffers.
|
||||
//! They can be thought as iterators for byte structures. They offer additional
|
||||
//! performance over `Iterator` by providing an API optimized for byte slices.
|
||||
//!
|
||||
//! See [`Buf`] and [`BufMut`] for more details.
|
||||
//!
|
||||
//! [rope]: https://en.wikipedia.org/wiki/Rope_(data_structure)
|
||||
//! [`Buf`]: trait.Buf.html
|
||||
//! [`BufMut`]: trait.BufMut.html
|
||||
|
||||
mod buf_impl;
|
||||
mod buf_mut;
|
||||
mod iter;
|
||||
mod writer;
|
||||
|
||||
pub use self::buf_impl::Buf;
|
||||
pub use self::buf_mut::BufMut;
|
||||
pub use self::iter::IntoIter;
|
||||
pub use self::writer::Writer;
|
88
ntex-bytes/src/buf/writer.rs
Normal file
88
ntex-bytes/src/buf/writer.rs
Normal file
|
@ -0,0 +1,88 @@
|
|||
use crate::BufMut;
|
||||
|
||||
use std::{cmp, io};
|
||||
|
||||
/// A `BufMut` adapter which implements `io::Write` for the inner value.
|
||||
///
|
||||
/// This struct is generally created by calling `writer()` on `BufMut`. See
|
||||
/// documentation of [`writer()`](trait.BufMut.html#method.writer) for more
|
||||
/// details.
|
||||
#[derive(Debug)]
|
||||
pub struct Writer<B> {
|
||||
buf: B,
|
||||
}
|
||||
|
||||
pub fn new<B>(buf: B) -> Writer<B> {
|
||||
Writer { buf }
|
||||
}
|
||||
|
||||
impl<B: BufMut> Writer<B> {
|
||||
/// Gets a reference to the underlying `BufMut`.
|
||||
///
|
||||
/// It is inadvisable to directly write to the underlying `BufMut`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = Vec::with_capacity(1024).writer();
|
||||
///
|
||||
/// assert_eq!(1024, buf.get_ref().capacity());
|
||||
/// ```
|
||||
pub fn get_ref(&self) -> &B {
|
||||
&self.buf
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the underlying `BufMut`.
|
||||
///
|
||||
/// It is inadvisable to directly write to the underlying `BufMut`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use ntex_bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![].writer();
|
||||
///
|
||||
/// buf.get_mut().reserve(1024);
|
||||
///
|
||||
/// assert_eq!(1024, buf.get_ref().capacity());
|
||||
/// ```
|
||||
pub fn get_mut(&mut self) -> &mut B {
|
||||
&mut self.buf
|
||||
}
|
||||
|
||||
/// Consumes this `Writer`, returning the underlying value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use ntex_bytes::BufMut;
|
||||
/// use std::io;
|
||||
///
|
||||
/// let mut buf = vec![].writer();
|
||||
/// let mut src = &b"hello world"[..];
|
||||
///
|
||||
/// io::copy(&mut src, &mut buf).unwrap();
|
||||
///
|
||||
/// let buf = buf.into_inner();
|
||||
/// assert_eq!(*buf, b"hello world"[..]);
|
||||
/// ```
|
||||
pub fn into_inner(self) -> B {
|
||||
self.buf
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BufMut + Sized> io::Write for Writer<B> {
|
||||
fn write(&mut self, src: &[u8]) -> io::Result<usize> {
|
||||
let n = cmp::min(self.buf.remaining_mut(), src.len());
|
||||
|
||||
self.buf.put(&src[0..n]);
|
||||
Ok(n)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
3081
ntex-bytes/src/bytes.rs
Normal file
3081
ntex-bytes/src/bytes.rs
Normal file
File diff suppressed because it is too large
Load diff
40
ntex-bytes/src/debug.rs
Normal file
40
ntex-bytes/src/debug.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
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 fmt::Debug for BsDebug<'_> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
write!(fmt, "b\"")?;
|
||||
for &c in self.0 {
|
||||
// https://doc.rust-lang.org/reference.html#byte-escapes
|
||||
if c == b'\n' {
|
||||
write!(fmt, "\\n")?;
|
||||
} else if c == b'\r' {
|
||||
write!(fmt, "\\r")?;
|
||||
} else if c == b'\t' {
|
||||
write!(fmt, "\\t")?;
|
||||
} else if c == b'\\' || c == b'"' {
|
||||
write!(fmt, "\\{}", c as char)?;
|
||||
} else if c == b'\0' {
|
||||
write!(fmt, "\\0")?;
|
||||
// ASCII printable
|
||||
} else if c >= 0x20 && c < 0x7f {
|
||||
write!(fmt, "{}", c as char)?;
|
||||
} else {
|
||||
write!(fmt, "\\x{:02x}", c)?;
|
||||
}
|
||||
}
|
||||
write!(fmt, "\"")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
37
ntex-bytes/src/hex.rs
Normal file
37
ntex-bytes/src/hex.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
use crate::{Bytes, BytesMut};
|
||||
use std::fmt::{Formatter, LowerHex, Result, UpperHex};
|
||||
|
||||
struct BytesRef<'a>(&'a [u8]);
|
||||
|
||||
impl<'a> LowerHex for BytesRef<'a> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
for b in self.0 {
|
||||
write!(f, "{:02x}", b)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> UpperHex for BytesRef<'a> {
|
||||
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);
|
94
ntex-bytes/src/lib.rs
Normal file
94
ntex-bytes/src/lib.rs
Normal file
|
@ -0,0 +1,94 @@
|
|||
//! Provides abstractions for working with bytes.
|
||||
//!
|
||||
//! This is fork of bytes crate (https://github.com/tokio-rs/bytes)
|
||||
//!
|
||||
//! The `bytes` crate provides an efficient byte buffer structure
|
||||
//! ([`Bytes`](struct.Bytes.html)) and traits for working with buffer
|
||||
//! implementations ([`Buf`], [`BufMut`]).
|
||||
//!
|
||||
//! [`Buf`]: trait.Buf.html
|
||||
//! [`BufMut`]: trait.BufMut.html
|
||||
//!
|
||||
//! # `Bytes`
|
||||
//!
|
||||
//! `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.
|
||||
//!
|
||||
//! A `Bytes` handle can be created directly from an existing byte store (such as `&[u8]`
|
||||
//! or `Vec<u8>`), but usually a `BytesMut` is used first and written to. For
|
||||
//! example:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use ntex_bytes::{BytesMut, BufMut};
|
||||
//!
|
||||
//! let mut buf = BytesMut::with_capacity(1024);
|
||||
//! buf.put(&b"hello world"[..]);
|
||||
//! buf.put_u16(1234);
|
||||
//!
|
||||
//! let a = buf.split();
|
||||
//! assert_eq!(a, b"hello world\x04\xD2"[..]);
|
||||
//!
|
||||
//! buf.put(&b"goodbye world"[..]);
|
||||
//!
|
||||
//! let b = buf.split();
|
||||
//! assert_eq!(b, b"goodbye world"[..]);
|
||||
//!
|
||||
//! assert_eq!(buf.capacity(), 998);
|
||||
//! ```
|
||||
//!
|
||||
//! In the above example, only a single buffer of 1024 is allocated. The handles
|
||||
//! `a` and `b` will share the underlying buffer and maintain indices tracking
|
||||
//! the view into the buffer represented by the handle.
|
||||
//!
|
||||
//! See the [struct docs] for more details.
|
||||
//!
|
||||
//! [struct docs]: struct.Bytes.html
|
||||
//!
|
||||
//! # `Buf`, `BufMut`
|
||||
//!
|
||||
//! These two traits provide read and write access to buffers. The underlying
|
||||
//! storage may or may not be in contiguous memory. For example, `Bytes` is a
|
||||
//! buffer that guarantees contiguous memory, but a [rope] stores the bytes in
|
||||
//! disjoint chunks. `Buf` and `BufMut` maintain cursors tracking the current
|
||||
//! position in the underlying byte storage. When bytes are read or written, the
|
||||
//! cursor is advanced.
|
||||
//!
|
||||
//! [rope]: https://en.wikipedia.org/wiki/Rope_(data_structure)
|
||||
//!
|
||||
//! ## Relation with `Read` and `Write`
|
||||
//!
|
||||
//! At first glance, it may seem that `Buf` and `BufMut` overlap in
|
||||
//! functionality with `std::io::Read` and `std::io::Write`. However, they
|
||||
//! serve different purposes. A buffer is the value that is provided as an
|
||||
//! argument to `Read::read` and `Write::write`. `Read` and `Write` may then
|
||||
//! perform a syscall, which has the potential of failing. Operations on `Buf`
|
||||
//! and `BufMut` are infallible.
|
||||
|
||||
#![deny(
|
||||
warnings,
|
||||
missing_docs,
|
||||
missing_debug_implementations,
|
||||
rust_2018_idioms
|
||||
)]
|
||||
#![doc(html_root_url = "https://docs.rs/bytes/0.5.0")]
|
||||
|
||||
pub mod buf;
|
||||
pub use crate::buf::{Buf, BufMut};
|
||||
|
||||
mod bytes;
|
||||
mod debug;
|
||||
mod hex;
|
||||
mod string;
|
||||
|
||||
pub use crate::bytes::{Bytes, BytesMut};
|
||||
pub use crate::string::ByteString;
|
||||
|
||||
// Optional Serde support
|
||||
#[cfg(feature = "serde")]
|
||||
mod serde;
|
87
ntex-bytes/src/serde.rs
Normal file
87
ntex-bytes/src/serde.rs
Normal file
|
@ -0,0 +1,87 @@
|
|||
use super::{Bytes, BytesMut};
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::{cmp, fmt};
|
||||
|
||||
macro_rules! serde_impl {
|
||||
($ty:ident, $visitor_ty:ident) => {
|
||||
impl Serialize for $ty {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_bytes(&self)
|
||||
}
|
||||
}
|
||||
|
||||
struct $visitor_ty;
|
||||
|
||||
impl<'de> de::Visitor<'de> for $visitor_ty {
|
||||
type Value = $ty;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.write_str("byte array")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
|
||||
where
|
||||
V: de::SeqAccess<'de>,
|
||||
{
|
||||
let len = cmp::min(seq.size_hint().unwrap_or(0), 4096);
|
||||
let mut values = Vec::with_capacity(len);
|
||||
|
||||
while let Some(value) = seq.next_element()? {
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
Ok(values.into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok($ty::from(v))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok($ty::from(v))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok($ty::from(v))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok($ty::from(v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for $ty {
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: D) -> Result<$ty, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_byte_buf($visitor_ty)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
serde_impl!(Bytes, BytesVisitor);
|
||||
serde_impl!(BytesMut, BytesMutVisitor);
|
309
ntex-bytes/src/string.rs
Normal file
309
ntex-bytes/src/string.rs
Normal file
|
@ -0,0 +1,309 @@
|
|||
//! A UTF-8 encoded read-only string using Bytes as storage.
|
||||
use std::{borrow, convert::TryFrom, fmt, hash, ops, str};
|
||||
|
||||
use crate::Bytes;
|
||||
|
||||
/// An immutable UTF-8 encoded string with [`Bytes`] as a storage.
|
||||
#[derive(Clone, Default, Eq, PartialOrd, Ord)]
|
||||
pub struct ByteString(Bytes);
|
||||
|
||||
impl ByteString {
|
||||
/// Creates a new empty `ByteString`.
|
||||
#[inline]
|
||||
pub const fn new() -> Self {
|
||||
ByteString(Bytes::new())
|
||||
}
|
||||
|
||||
/// Get a reference to the underlying `Bytes` object.
|
||||
#[inline]
|
||||
pub fn as_bytes(&self) -> &Bytes {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Unwraps this `ByteString` into the underlying `Bytes` object.
|
||||
#[inline]
|
||||
pub fn into_bytes(self) -> Bytes {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Creates a new `ByteString` from a `&'static str`.
|
||||
#[inline]
|
||||
pub const fn from_static(src: &'static str) -> ByteString {
|
||||
Self(Bytes::from_static(src.as_bytes()))
|
||||
}
|
||||
|
||||
/// Creates a new `ByteString` from a Bytes.
|
||||
///
|
||||
/// # Safety
|
||||
/// This function is unsafe because it does not check the bytes passed to it are valid UTF-8.
|
||||
/// If this constraint is violated, it may cause memory unsafety issues with future users of
|
||||
/// the `ByteString`, as we assume that `ByteString`s are valid UTF-8. However, the most likely
|
||||
/// issue is that the data gets corrupted.
|
||||
#[inline]
|
||||
pub const unsafe fn from_bytes_unchecked(src: Bytes) -> ByteString {
|
||||
Self(src)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<str> for ByteString {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
&self[..] == other
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<str>> PartialEq<T> for ByteString {
|
||||
fn eq(&self, other: &T) -> bool {
|
||||
&self[..] == other.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for ByteString {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &str {
|
||||
&*self
|
||||
}
|
||||
}
|
||||
|
||||
impl hash::Hash for ByteString {
|
||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||
(**self).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Deref for ByteString {
|
||||
type Target = str;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &str {
|
||||
let bytes = self.0.as_ref();
|
||||
// SAFETY:
|
||||
// UTF-8 validity is guaranteed at during construction.
|
||||
unsafe { str::from_utf8_unchecked(bytes) }
|
||||
}
|
||||
}
|
||||
|
||||
impl borrow::Borrow<str> for ByteString {
|
||||
#[inline]
|
||||
fn borrow(&self) -> &str {
|
||||
&*self
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for ByteString {
|
||||
#[inline]
|
||||
fn from(value: String) -> Self {
|
||||
Self(Bytes::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for ByteString {
|
||||
#[inline]
|
||||
fn from(value: &str) -> Self {
|
||||
Self(Bytes::copy_from_slice(value.as_ref()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<borrow::Cow<'a, str>> for ByteString {
|
||||
#[inline]
|
||||
fn from(value: borrow::Cow<'a, str>) -> Self {
|
||||
Self::from(value.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for ByteString {
|
||||
type Error = str::Utf8Error;
|
||||
|
||||
#[inline]
|
||||
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
|
||||
let _ = str::from_utf8(value)?;
|
||||
Ok(ByteString(Bytes::copy_from_slice(value)))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Vec<u8>> for ByteString {
|
||||
type Error = str::Utf8Error;
|
||||
|
||||
#[inline]
|
||||
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
|
||||
let buf = String::from_utf8(value).map_err(|err| err.utf8_error())?;
|
||||
Ok(ByteString(Bytes::from(buf)))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Bytes> for ByteString {
|
||||
type Error = str::Utf8Error;
|
||||
|
||||
#[inline]
|
||||
fn try_from(value: Bytes) -> Result<Self, Self::Error> {
|
||||
let _ = str::from_utf8(value.as_ref())?;
|
||||
Ok(ByteString(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<crate::BytesMut> for ByteString {
|
||||
type Error = str::Utf8Error;
|
||||
|
||||
#[inline]
|
||||
fn try_from(value: crate::BytesMut) -> Result<Self, Self::Error> {
|
||||
let _ = str::from_utf8(&value)?;
|
||||
Ok(ByteString(value.freeze()))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! array_impls {
|
||||
($($len:expr)+) => {
|
||||
$(
|
||||
impl TryFrom<[u8; $len]> for ByteString {
|
||||
type Error = str::Utf8Error;
|
||||
|
||||
#[inline]
|
||||
fn try_from(value: [u8; $len]) -> Result<Self, Self::Error> {
|
||||
ByteString::try_from(&value[..])
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8; $len]> for ByteString {
|
||||
type Error = str::Utf8Error;
|
||||
|
||||
#[inline]
|
||||
fn try_from(value: &[u8; $len]) -> Result<Self, Self::Error> {
|
||||
ByteString::try_from(&value[..])
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
array_impls!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32);
|
||||
|
||||
impl fmt::Debug for ByteString {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
(**self).fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ByteString {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
(**self).fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
mod serde {
|
||||
use alloc::string::String;
|
||||
|
||||
use serde::de::{Deserialize, Deserializer};
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
|
||||
use super::ByteString;
|
||||
|
||||
impl Serialize for ByteString {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(self.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ByteString {
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
String::deserialize(deserializer).map(ByteString::from)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use alloc::borrow::ToOwned;
|
||||
use core::hash::{Hash, Hasher};
|
||||
|
||||
use ahash::AHasher;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_partial_eq() {
|
||||
let s: ByteString = ByteString::from_static("test");
|
||||
assert_eq!(s, "test");
|
||||
assert_eq!(s, *"test");
|
||||
assert_eq!(s, "test".to_owned());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new() {
|
||||
let _: ByteString = ByteString::new();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash() {
|
||||
let mut hasher1 = AHasher::default();
|
||||
"str".hash(&mut hasher1);
|
||||
|
||||
let mut hasher2 = AHasher::default();
|
||||
let s = ByteString::from_static("str");
|
||||
s.hash(&mut hasher2);
|
||||
assert_eq!(hasher1.finish(), hasher2.finish());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_string() {
|
||||
let s: ByteString = "hello".to_owned().into();
|
||||
assert_eq!(&s, "hello");
|
||||
let t: &str = s.as_ref();
|
||||
assert_eq!(t, "hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str() {
|
||||
let _: ByteString = "str".into();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_static_str() {
|
||||
static _S: ByteString = ByteString::from_static("hello");
|
||||
let _ = ByteString::from_static("str");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_slice() {
|
||||
let _ = ByteString::try_from(b"nice bytes").unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_array() {
|
||||
assert_eq!(
|
||||
ByteString::try_from([b'h', b'i']).unwrap(),
|
||||
ByteString::from_static("hi")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_bytes() {
|
||||
let _ = ByteString::try_from(Bytes::from_static(b"nice bytes")).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_bytes_mut() {
|
||||
let _ = ByteString::try_from(bytes::BytesMut::from(&b"nice bytes"[..])).unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[test]
|
||||
fn test_serialize() {
|
||||
let s: ByteString = serde_json::from_str(r#""nice bytes""#).unwrap();
|
||||
assert_eq!(s, "nice bytes");
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[test]
|
||||
fn test_deserialize() {
|
||||
let s = serde_json::to_string(&ByteString::from_static("nice bytes")).unwrap();
|
||||
assert_eq!(s, r#""nice bytes""#);
|
||||
}
|
||||
}
|
42
ntex-bytes/tests/test_buf.rs
Normal file
42
ntex-bytes/tests/test_buf.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
#![deny(warnings, rust_2018_idioms)]
|
||||
|
||||
use ntex_bytes::Buf;
|
||||
|
||||
#[test]
|
||||
fn test_fresh_cursor_vec() {
|
||||
let mut buf = &b"hello"[..];
|
||||
|
||||
assert_eq!(buf.remaining(), 5);
|
||||
assert_eq!(buf.bytes(), b"hello");
|
||||
|
||||
buf.advance(2);
|
||||
|
||||
assert_eq!(buf.remaining(), 3);
|
||||
assert_eq!(buf.bytes(), b"llo");
|
||||
|
||||
buf.advance(3);
|
||||
|
||||
assert_eq!(buf.remaining(), 0);
|
||||
assert_eq!(buf.bytes(), b"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_u8() {
|
||||
let mut buf = &b"\x21zomg"[..];
|
||||
assert_eq!(0x21, buf.get_u8());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_u16() {
|
||||
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 = &b"\x21"[..];
|
||||
buf.get_u16();
|
||||
}
|
75
ntex-bytes/tests/test_buf_mut.rs
Normal file
75
ntex-bytes/tests/test_buf_mut.rs
Normal file
|
@ -0,0 +1,75 @@
|
|||
#![deny(warnings, rust_2018_idioms)]
|
||||
|
||||
use ntex_bytes::{BufMut, BytesMut};
|
||||
use std::fmt::Write;
|
||||
use std::usize;
|
||||
|
||||
#[test]
|
||||
fn test_vec_as_mut_buf() {
|
||||
let mut buf = Vec::with_capacity(64);
|
||||
|
||||
assert_eq!(buf.remaining_mut(), usize::MAX);
|
||||
|
||||
unsafe {
|
||||
assert!(buf.bytes_mut().len() >= 64);
|
||||
}
|
||||
|
||||
buf.put(&b"zomg"[..]);
|
||||
|
||||
assert_eq!(&buf, b"zomg");
|
||||
|
||||
assert_eq!(buf.remaining_mut(), usize::MAX - 4);
|
||||
assert_eq!(buf.capacity(), 64);
|
||||
|
||||
for _ in 0..16 {
|
||||
buf.put(&b"zomg"[..]);
|
||||
}
|
||||
|
||||
assert_eq!(buf.len(), 68);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_put_u8() {
|
||||
let mut buf = Vec::with_capacity(8);
|
||||
buf.put_u8(33);
|
||||
assert_eq!(b"\x21", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_put_u16() {
|
||||
let mut buf = Vec::with_capacity(8);
|
||||
buf.put_u16(8532);
|
||||
assert_eq!(b"\x21\x54", &buf[..]);
|
||||
|
||||
buf.clear();
|
||||
buf.put_u16_le(8532);
|
||||
assert_eq!(b"\x54\x21", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vec_advance_mut() {
|
||||
// Regression test for carllerche/bytes#108.
|
||||
let mut buf = Vec::with_capacity(8);
|
||||
unsafe {
|
||||
buf.advance_mut(12);
|
||||
assert_eq!(buf.len(), 12);
|
||||
assert!(buf.capacity() >= 12, "capacity: {}", buf.capacity());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clone() {
|
||||
let mut buf = BytesMut::with_capacity(100);
|
||||
buf.write_str("this is a test").unwrap();
|
||||
let buf2 = buf.clone();
|
||||
|
||||
buf.write_str(" of our emergency broadcast system").unwrap();
|
||||
assert!(buf != buf2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mut_slice() {
|
||||
let mut v = vec![0, 0, 0, 0];
|
||||
let mut s = &mut v[..];
|
||||
s.put_u32(42);
|
||||
}
|
890
ntex-bytes/tests/test_bytes.rs
Normal file
890
ntex-bytes/tests/test_bytes.rs
Normal file
|
@ -0,0 +1,890 @@
|
|||
#![deny(warnings, rust_2018_idioms)]
|
||||
|
||||
use ntex_bytes::{Buf, BufMut, Bytes, BytesMut};
|
||||
|
||||
const LONG: &'static [u8] = b"mary had a little lamb, little lamb, little lamb";
|
||||
const SHORT: &'static [u8] = b"hello world";
|
||||
|
||||
fn inline_cap() -> usize {
|
||||
use std::mem;
|
||||
4 * mem::size_of::<usize>() - 1
|
||||
}
|
||||
|
||||
fn is_sync<T: Sync>() {}
|
||||
fn is_send<T: Send>() {}
|
||||
|
||||
#[test]
|
||||
fn test_bounds() {
|
||||
is_sync::<Bytes>();
|
||||
is_sync::<BytesMut>();
|
||||
is_send::<Bytes>();
|
||||
is_send::<BytesMut>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_slice() {
|
||||
let a = Bytes::from(&b"abcdefgh"[..]);
|
||||
assert_eq!(a, b"abcdefgh"[..]);
|
||||
assert_eq!(a, &b"abcdefgh"[..]);
|
||||
assert_eq!(a, Vec::from(&b"abcdefgh"[..]));
|
||||
assert_eq!(b"abcdefgh"[..], a);
|
||||
assert_eq!(&b"abcdefgh"[..], a);
|
||||
assert_eq!(Vec::from(&b"abcdefgh"[..]), a);
|
||||
|
||||
let a = BytesMut::from(&b"abcdefgh"[..]);
|
||||
assert_eq!(a, b"abcdefgh"[..]);
|
||||
assert_eq!(a, &b"abcdefgh"[..]);
|
||||
assert_eq!(a, Vec::from(&b"abcdefgh"[..]));
|
||||
assert_eq!(b"abcdefgh"[..], a);
|
||||
assert_eq!(&b"abcdefgh"[..], a);
|
||||
assert_eq!(Vec::from(&b"abcdefgh"[..]), a);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fmt() {
|
||||
let a = format!("{:?}", Bytes::from(&b"abcdefg"[..]));
|
||||
let b = "b\"abcdefg\"";
|
||||
|
||||
assert_eq!(a, b);
|
||||
|
||||
let a = format!("{:?}", BytesMut::from(&b"abcdefg"[..]));
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fmt_write() {
|
||||
use std::fmt::Write;
|
||||
use std::iter::FromIterator;
|
||||
let s = String::from_iter((0..10).map(|_| "abcdefg"));
|
||||
|
||||
let mut a = BytesMut::with_capacity(64);
|
||||
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());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn len() {
|
||||
let a = Bytes::from(&b"abcdefg"[..]);
|
||||
assert_eq!(a.len(), 7);
|
||||
|
||||
let a = BytesMut::from(&b"abcdefg"[..]);
|
||||
assert_eq!(a.len(), 7);
|
||||
|
||||
let a = Bytes::from(&b""[..]);
|
||||
assert!(a.is_empty());
|
||||
|
||||
let a = BytesMut::from(&b""[..]);
|
||||
assert!(a.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn index() {
|
||||
let a = Bytes::from(&b"hello world"[..]);
|
||||
assert_eq!(a[0..5], *b"hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slice() {
|
||||
let a = Bytes::from(&b"hello world"[..]);
|
||||
|
||||
let b = a.slice(3..5);
|
||||
assert_eq!(b, b"lo"[..]);
|
||||
|
||||
let b = a.slice(0..0);
|
||||
assert_eq!(b, b""[..]);
|
||||
|
||||
let b = a.slice(3..3);
|
||||
assert_eq!(b, b""[..]);
|
||||
|
||||
let b = a.slice(a.len()..a.len());
|
||||
assert_eq!(b, b""[..]);
|
||||
|
||||
let b = a.slice(..5);
|
||||
assert_eq!(b, b"hello"[..]);
|
||||
|
||||
let b = a.slice(3..);
|
||||
assert_eq!(b, b"lo world"[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn slice_oob_1() {
|
||||
let a = Bytes::from(&b"hello world"[..]);
|
||||
a.slice(5..(inline_cap() + 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn slice_oob_2() {
|
||||
let a = Bytes::from(&b"hello world"[..]);
|
||||
a.slice((inline_cap() + 1)..(inline_cap() + 5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_off() {
|
||||
let mut hello = Bytes::from(&b"helloworld"[..]);
|
||||
let world = hello.split_off(5);
|
||||
|
||||
assert_eq!(hello, &b"hello"[..]);
|
||||
assert_eq!(world, &b"world"[..]);
|
||||
|
||||
let mut hello = BytesMut::from(&b"helloworld"[..]);
|
||||
let world = hello.split_off(5);
|
||||
|
||||
assert_eq!(hello, &b"hello"[..]);
|
||||
assert_eq!(world, &b"world"[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn split_off_oob() {
|
||||
let mut hello = Bytes::from(&b"helloworld"[..]);
|
||||
hello.split_off(inline_cap() + 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_off_uninitialized() {
|
||||
let mut bytes = BytesMut::with_capacity(1024);
|
||||
let other = bytes.split_off(128);
|
||||
|
||||
assert_eq!(bytes.len(), 0);
|
||||
assert_eq!(bytes.capacity(), 128);
|
||||
|
||||
assert_eq!(other.len(), 0);
|
||||
assert_eq!(other.capacity(), 896);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_off_to_loop() {
|
||||
let s = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
for i in 0..(s.len() + 1) {
|
||||
{
|
||||
let mut bytes = Bytes::from(&s[..]);
|
||||
let off = bytes.split_off(i);
|
||||
assert_eq!(i, bytes.len());
|
||||
let mut sum = Vec::new();
|
||||
sum.extend(bytes.iter());
|
||||
sum.extend(off.iter());
|
||||
assert_eq!(&s[..], &sum[..]);
|
||||
}
|
||||
{
|
||||
let mut bytes = BytesMut::from(&s[..]);
|
||||
let off = bytes.split_off(i);
|
||||
assert_eq!(i, bytes.len());
|
||||
let mut sum = Vec::new();
|
||||
sum.extend(&bytes);
|
||||
sum.extend(&off);
|
||||
assert_eq!(&s[..], &sum[..]);
|
||||
}
|
||||
{
|
||||
let mut bytes = Bytes::from(&s[..]);
|
||||
let off = bytes.split_to(i);
|
||||
assert_eq!(i, off.len());
|
||||
let mut sum = Vec::new();
|
||||
sum.extend(off.iter());
|
||||
sum.extend(bytes.iter());
|
||||
assert_eq!(&s[..], &sum[..]);
|
||||
}
|
||||
{
|
||||
let mut bytes = BytesMut::from(&s[..]);
|
||||
let off = bytes.split_to(i);
|
||||
assert_eq!(i, off.len());
|
||||
let mut sum = Vec::new();
|
||||
sum.extend(&off);
|
||||
sum.extend(&bytes);
|
||||
assert_eq!(&s[..], &sum[..]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_to_1() {
|
||||
// Inline
|
||||
let mut a = Bytes::from(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 b = a.split_to(4);
|
||||
|
||||
assert_eq!(LONG[4..], a);
|
||||
assert_eq!(LONG[..4], b);
|
||||
|
||||
let mut a = Bytes::from(LONG);
|
||||
let b = a.split_to(30);
|
||||
|
||||
assert_eq!(LONG[30..], a);
|
||||
assert_eq!(LONG[..30], b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_to_2() {
|
||||
let mut a = Bytes::from(LONG);
|
||||
assert_eq!(LONG, a);
|
||||
|
||||
let b = a.split_to(1);
|
||||
|
||||
assert_eq!(LONG[1..], a);
|
||||
drop(b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn split_to_oob() {
|
||||
let mut hello = Bytes::from(&b"helloworld"[..]);
|
||||
hello.split_to(inline_cap() + 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn split_to_oob_mut() {
|
||||
let mut hello = BytesMut::from(&b"helloworld"[..]);
|
||||
hello.split_to(inline_cap() + 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn split_to_uninitialized() {
|
||||
let mut bytes = BytesMut::with_capacity(1024);
|
||||
let _other = bytes.split_to(128);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_off_to_at_gt_len() {
|
||||
fn make_bytes() -> Bytes {
|
||||
let mut bytes = BytesMut::with_capacity(100);
|
||||
bytes.put_slice(&[10, 20, 30, 40]);
|
||||
bytes.freeze()
|
||||
}
|
||||
|
||||
use std::panic;
|
||||
|
||||
make_bytes().split_to(4);
|
||||
make_bytes().split_off(4);
|
||||
|
||||
assert!(panic::catch_unwind(move || {
|
||||
make_bytes().split_to(5);
|
||||
})
|
||||
.is_err());
|
||||
|
||||
assert!(panic::catch_unwind(move || {
|
||||
make_bytes().split_off(5);
|
||||
})
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fns_defined_for_bytes_mut() {
|
||||
let mut bytes = BytesMut::from(&b"hello world"[..]);
|
||||
|
||||
bytes.as_ptr();
|
||||
bytes.as_mut_ptr();
|
||||
|
||||
// Iterator
|
||||
let v: Vec<u8> = bytes.as_ref().iter().cloned().collect();
|
||||
assert_eq!(&v[..], bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reserve_convert() {
|
||||
// Inline -> Vec
|
||||
let mut bytes = BytesMut::with_capacity(8);
|
||||
bytes.put("hello".as_bytes());
|
||||
bytes.reserve(40);
|
||||
assert_eq!(bytes.capacity(), 45);
|
||||
assert_eq!(bytes, "hello");
|
||||
|
||||
// Inline -> Inline
|
||||
let mut bytes = BytesMut::with_capacity(inline_cap());
|
||||
bytes.put("abcdefghijkl".as_bytes());
|
||||
|
||||
let a = bytes.split_to(10);
|
||||
bytes.reserve(inline_cap() - 3);
|
||||
assert_eq!(inline_cap(), bytes.capacity());
|
||||
|
||||
assert_eq!(bytes, "kl");
|
||||
assert_eq!(a, "abcdefghij");
|
||||
|
||||
// Vec -> Vec
|
||||
let mut bytes = BytesMut::from(LONG);
|
||||
bytes.reserve(64);
|
||||
assert_eq!(bytes.capacity(), LONG.len() + 64);
|
||||
|
||||
// Arc -> Vec
|
||||
let mut bytes = BytesMut::from(LONG);
|
||||
let a = bytes.split_to(30);
|
||||
|
||||
bytes.reserve(128);
|
||||
assert!(bytes.capacity() >= bytes.len() + 128);
|
||||
|
||||
drop(a);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reserve_growth() {
|
||||
let mut bytes = BytesMut::with_capacity(64);
|
||||
bytes.put("hello world".as_bytes());
|
||||
let _ = bytes.split();
|
||||
|
||||
bytes.reserve(65);
|
||||
assert_eq!(bytes.capacity(), 128);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reserve_allocates_at_least_original_capacity() {
|
||||
let mut bytes = BytesMut::with_capacity(1024);
|
||||
|
||||
for i in 0..1020 {
|
||||
bytes.put_u8(i as u8);
|
||||
}
|
||||
|
||||
let _other = bytes.split();
|
||||
|
||||
bytes.reserve(16);
|
||||
assert_eq!(bytes.capacity(), 1024);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reserve_max_original_capacity_value() {
|
||||
const SIZE: usize = 128 * 1024;
|
||||
|
||||
let mut bytes = BytesMut::with_capacity(SIZE);
|
||||
|
||||
for _ in 0..SIZE {
|
||||
bytes.put_u8(0u8);
|
||||
}
|
||||
|
||||
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));
|
||||
assert_eq!(bytes.capacity(), 16);
|
||||
bytes.put("0123456789012345".as_bytes());
|
||||
bytes.advance(10);
|
||||
assert_eq!(bytes.capacity(), 6);
|
||||
bytes.reserve(8);
|
||||
assert_eq!(bytes.capacity(), 16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reserve_in_arc_unique_does_not_overallocate() {
|
||||
let mut bytes = BytesMut::with_capacity(1000);
|
||||
bytes.split();
|
||||
|
||||
// now bytes is Arc and refcount == 1
|
||||
|
||||
assert_eq!(1000, bytes.capacity());
|
||||
bytes.reserve(2001);
|
||||
assert_eq!(2001, bytes.capacity());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reserve_in_arc_unique_doubles() {
|
||||
let mut bytes = BytesMut::with_capacity(1000);
|
||||
bytes.split();
|
||||
|
||||
// now bytes is Arc and refcount == 1
|
||||
|
||||
assert_eq!(1000, bytes.capacity());
|
||||
bytes.reserve(1001);
|
||||
assert_eq!(2000, bytes.capacity());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reserve_in_arc_nonunique_does_not_overallocate() {
|
||||
let mut bytes = BytesMut::with_capacity(1000);
|
||||
let _copy = bytes.split();
|
||||
|
||||
// now bytes is Arc and refcount == 2
|
||||
|
||||
assert_eq!(1000, bytes.capacity());
|
||||
bytes.reserve(2001);
|
||||
assert_eq!(2001, bytes.capacity());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inline_storage() {
|
||||
let mut bytes = BytesMut::with_capacity(inline_cap());
|
||||
let zero = [0u8; 64];
|
||||
|
||||
bytes.put(&zero[0..inline_cap()]);
|
||||
assert_eq!(*bytes, zero[0..inline_cap()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extend_mut() {
|
||||
let mut bytes = BytesMut::with_capacity(0);
|
||||
bytes.extend(LONG);
|
||||
assert_eq!(*bytes, LONG[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extend_shr() {
|
||||
let mut bytes = Bytes::new();
|
||||
bytes.extend(LONG);
|
||||
assert_eq!(*bytes, LONG[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extend_from_slice_mut() {
|
||||
for &i in &[3, 34] {
|
||||
let mut bytes = BytesMut::new();
|
||||
bytes.extend_from_slice(&LONG[..i]);
|
||||
bytes.extend_from_slice(&LONG[i..]);
|
||||
assert_eq!(LONG[..], *bytes);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extend_from_slice_shr() {
|
||||
for &i in &[3, 34] {
|
||||
let mut bytes = Bytes::new();
|
||||
bytes.extend_from_slice(&LONG[..i]);
|
||||
bytes.extend_from_slice(&LONG[i..]);
|
||||
assert_eq!(LONG[..], *bytes);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_static() {
|
||||
let mut a = Bytes::from_static(b"ab");
|
||||
let b = a.split_off(1);
|
||||
|
||||
assert_eq!(a, b"a"[..]);
|
||||
assert_eq!(b, b"b"[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn advance_inline() {
|
||||
let mut a = Bytes::from(&b"hello world"[..]);
|
||||
a.advance(6);
|
||||
assert_eq!(a, &b"world"[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn advance_static() {
|
||||
let mut a = Bytes::from_static(b"hello world");
|
||||
a.advance(6);
|
||||
assert_eq!(a, &b"world"[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn advance_vec() {
|
||||
let mut a = BytesMut::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"[..]);
|
||||
|
||||
// Reserve some space.
|
||||
a.reserve(1024);
|
||||
assert_eq!(a, b"h world zomg wat wat"[..]);
|
||||
|
||||
a.advance(6);
|
||||
assert_eq!(a, b"d zomg wat wat"[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn advance_past_len() {
|
||||
let mut a = BytesMut::from(b"hello world".to_vec());
|
||||
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")]
|
||||
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;
|
||||
|
||||
for i in 0..ITERS {
|
||||
let data = [i as u8; 256];
|
||||
let buf = Arc::new(Bytes::copy_from_slice(&data[..]));
|
||||
|
||||
let barrier = Arc::new(Barrier::new(THREADS));
|
||||
let mut joins = Vec::with_capacity(THREADS);
|
||||
|
||||
for _ in 0..THREADS {
|
||||
let c = barrier.clone();
|
||||
let buf = buf.clone();
|
||||
|
||||
joins.push(thread::spawn(move || {
|
||||
c.wait();
|
||||
let buf: Bytes = (*buf).clone();
|
||||
drop(buf);
|
||||
}));
|
||||
}
|
||||
|
||||
for th in joins {
|
||||
th.join().unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(*buf, data[..]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn partial_eq_bytesmut() {
|
||||
let bytes = Bytes::from(&b"The quick red fox"[..]);
|
||||
let bytesmut = BytesMut::from(&b"The quick red fox"[..]);
|
||||
assert!(bytes == bytesmut);
|
||||
assert!(bytesmut == bytes);
|
||||
let bytes2 = Bytes::from(&b"Jumped over the lazy brown dog"[..]);
|
||||
assert!(bytes2 != bytesmut);
|
||||
assert!(bytesmut != bytes2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_unsplit_basic() {
|
||||
let mut buf = Bytes::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[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_unsplit_empty_other() {
|
||||
let mut buf = Bytes::with_capacity(64);
|
||||
buf.extend_from_slice(b"aaabbbcccddd");
|
||||
|
||||
// empty other
|
||||
let other = Bytes::new();
|
||||
|
||||
buf.unsplit(other);
|
||||
assert_eq!(b"aaabbbcccddd", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_unsplit_empty_self() {
|
||||
// empty self
|
||||
let mut buf = Bytes::new();
|
||||
|
||||
let mut other = Bytes::with_capacity(64);
|
||||
other.extend_from_slice(b"aaabbbcccddd");
|
||||
|
||||
buf.unsplit(other);
|
||||
assert_eq!(b"aaabbbcccddd", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_unsplit_inline_arc() {
|
||||
let mut buf = Bytes::with_capacity(8); //inline
|
||||
buf.extend_from_slice(b"aaaabbbb");
|
||||
|
||||
let mut buf2 = Bytes::with_capacity(64);
|
||||
buf2.extend_from_slice(b"ccccddddeeee");
|
||||
|
||||
buf2.split_off(8); //arc
|
||||
|
||||
buf.unsplit(buf2);
|
||||
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_unsplit_arc_inline() {
|
||||
let mut buf = Bytes::with_capacity(64);
|
||||
buf.extend_from_slice(b"aaaabbbbeeee");
|
||||
|
||||
buf.split_off(8); //arc
|
||||
|
||||
let mut buf2 = Bytes::with_capacity(8); //inline
|
||||
buf2.extend_from_slice(b"ccccdddd");
|
||||
|
||||
buf.unsplit(buf2);
|
||||
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_unsplit_both_inline() {
|
||||
let mut buf = Bytes::with_capacity(16); //inline
|
||||
buf.extend_from_slice(b"aaaabbbbccccdddd");
|
||||
|
||||
let splitted = buf.split_off(8); // both inline
|
||||
assert_eq!(b"aaaabbbb", &buf[..]);
|
||||
assert_eq!(b"ccccdddd", &splitted[..]);
|
||||
|
||||
buf.unsplit(splitted);
|
||||
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_unsplit_arc_different() {
|
||||
let mut buf = Bytes::with_capacity(64);
|
||||
buf.extend_from_slice(b"aaaabbbbeeee");
|
||||
|
||||
buf.split_off(8); //arc
|
||||
|
||||
let mut buf2 = Bytes::with_capacity(64);
|
||||
buf2.extend_from_slice(b"ccccddddeeee");
|
||||
|
||||
buf2.split_off(8); //arc
|
||||
|
||||
buf.unsplit(buf2);
|
||||
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_unsplit_arc_non_contiguous() {
|
||||
let mut buf = Bytes::with_capacity(64);
|
||||
buf.extend_from_slice(b"aaaabbbbeeeeccccdddd");
|
||||
|
||||
let mut buf2 = buf.split_off(8); //arc
|
||||
|
||||
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 bytes_mut_unsplit_basic() {
|
||||
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[..]);
|
||||
}
|
||||
|
||||
#[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_inline_arc() {
|
||||
let mut buf = BytesMut::with_capacity(8); //inline
|
||||
buf.extend_from_slice(b"aaaabbbb");
|
||||
|
||||
let mut buf2 = BytesMut::with_capacity(64);
|
||||
buf2.extend_from_slice(b"ccccddddeeee");
|
||||
|
||||
buf2.split_off(8); //arc
|
||||
|
||||
buf.unsplit(buf2);
|
||||
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_mut_unsplit_arc_inline() {
|
||||
let mut buf = BytesMut::with_capacity(64);
|
||||
buf.extend_from_slice(b"aaaabbbbeeee");
|
||||
|
||||
buf.split_off(8); //arc
|
||||
|
||||
let mut buf2 = BytesMut::with_capacity(8); //inline
|
||||
buf2.extend_from_slice(b"ccccdddd");
|
||||
|
||||
buf.unsplit(buf2);
|
||||
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_mut_unsplit_both_inline() {
|
||||
let mut buf = BytesMut::with_capacity(16); //inline
|
||||
buf.extend_from_slice(b"aaaabbbbccccdddd");
|
||||
|
||||
let splitted = buf.split_off(8); // both inline
|
||||
assert_eq!(b"aaaabbbb", &buf[..]);
|
||||
assert_eq!(b"ccccdddd", &splitted[..]);
|
||||
|
||||
buf.unsplit(splitted);
|
||||
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_mut_unsplit_arc_different() {
|
||||
let mut buf = BytesMut::with_capacity(64);
|
||||
buf.extend_from_slice(b"aaaabbbbeeee");
|
||||
|
||||
buf.split_off(8); //arc
|
||||
|
||||
let mut buf2 = BytesMut::with_capacity(64);
|
||||
buf2.extend_from_slice(b"ccccddddeeee");
|
||||
|
||||
buf2.split_off(8); //arc
|
||||
|
||||
buf.unsplit(buf2);
|
||||
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_mut_unsplit_arc_non_contiguous() {
|
||||
let mut buf = BytesMut::with_capacity(64);
|
||||
buf.extend_from_slice(b"aaaabbbbeeeeccccdddd");
|
||||
|
||||
let mut buf2 = buf.split_off(8); //arc
|
||||
|
||||
let buf3 = buf2.split_off(4); //arc
|
||||
|
||||
buf.unsplit(buf3);
|
||||
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_mut_unsplit_two_split_offs() {
|
||||
let mut buf = BytesMut::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 from_iter_no_size_hint() {
|
||||
use std::iter;
|
||||
|
||||
let mut expect = vec![];
|
||||
|
||||
let actual: Bytes = iter::repeat(b'x')
|
||||
.scan(100, |cnt, item| {
|
||||
if *cnt >= 1 {
|
||||
*cnt -= 1;
|
||||
expect.push(item);
|
||||
Some(item)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
assert_eq!(&actual[..], &expect[..]);
|
||||
}
|
||||
|
||||
fn test_slice_ref(bytes: &Bytes, start: usize, end: usize, expected: &[u8]) {
|
||||
let slice = &(bytes.as_ref()[start..end]);
|
||||
let sub = bytes.slice_ref(&slice);
|
||||
assert_eq!(&sub[..], expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slice_ref_works() {
|
||||
let bytes = Bytes::from(&b"012345678"[..]);
|
||||
|
||||
test_slice_ref(&bytes, 0, 0, b"");
|
||||
test_slice_ref(&bytes, 0, 3, b"012");
|
||||
test_slice_ref(&bytes, 2, 6, b"2345");
|
||||
test_slice_ref(&bytes, 7, 9, b"78");
|
||||
test_slice_ref(&bytes, 9, 9, b"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slice_ref_empty() {
|
||||
let bytes = Bytes::from(&b""[..]);
|
||||
let slice = &(bytes.as_ref()[0..0]);
|
||||
|
||||
let sub = bytes.slice_ref(&slice);
|
||||
assert_eq!(&sub[..], b"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn slice_ref_catches_not_a_subset() {
|
||||
let bytes = Bytes::from(&b"012345678"[..]);
|
||||
let slice = &b"012345"[0..4];
|
||||
|
||||
bytes.slice_ref(slice);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn slice_ref_catches_not_an_empty_subset() {
|
||||
let bytes = Bytes::from(&b"012345678"[..]);
|
||||
let slice = &b""[0..0];
|
||||
|
||||
bytes.slice_ref(slice);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn empty_slice_ref_catches_not_an_empty_subset() {
|
||||
let bytes = Bytes::copy_from_slice(&b""[..]);
|
||||
let slice = &b""[0..0];
|
||||
|
||||
bytes.slice_ref(slice);
|
||||
}
|
35
ntex-bytes/tests/test_debug.rs
Normal file
35
ntex-bytes/tests/test_debug.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
#![deny(warnings, rust_2018_idioms)]
|
||||
|
||||
use ntex_bytes::Bytes;
|
||||
|
||||
#[test]
|
||||
fn fmt() {
|
||||
let vec: Vec<_> = (0..0x100).map(|b| b as u8).collect();
|
||||
|
||||
let expected = "b\"\
|
||||
\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\
|
||||
\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\
|
||||
\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\
|
||||
\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\
|
||||
\x20!\\\"#$%&'()*+,-./0123456789:;<=>?\
|
||||
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_\
|
||||
`abcdefghijklmnopqrstuvwxyz{|}~\\x7f\
|
||||
\\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87\
|
||||
\\x88\\x89\\x8a\\x8b\\x8c\\x8d\\x8e\\x8f\
|
||||
\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\
|
||||
\\x98\\x99\\x9a\\x9b\\x9c\\x9d\\x9e\\x9f\
|
||||
\\xa0\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6\\xa7\
|
||||
\\xa8\\xa9\\xaa\\xab\\xac\\xad\\xae\\xaf\
|
||||
\\xb0\\xb1\\xb2\\xb3\\xb4\\xb5\\xb6\\xb7\
|
||||
\\xb8\\xb9\\xba\\xbb\\xbc\\xbd\\xbe\\xbf\
|
||||
\\xc0\\xc1\\xc2\\xc3\\xc4\\xc5\\xc6\\xc7\
|
||||
\\xc8\\xc9\\xca\\xcb\\xcc\\xcd\\xce\\xcf\
|
||||
\\xd0\\xd1\\xd2\\xd3\\xd4\\xd5\\xd6\\xd7\
|
||||
\\xd8\\xd9\\xda\\xdb\\xdc\\xdd\\xde\\xdf\
|
||||
\\xe0\\xe1\\xe2\\xe3\\xe4\\xe5\\xe6\\xe7\
|
||||
\\xe8\\xe9\\xea\\xeb\\xec\\xed\\xee\\xef\
|
||||
\\xf0\\xf1\\xf2\\xf3\\xf4\\xf5\\xf6\\xf7\
|
||||
\\xf8\\xf9\\xfa\\xfb\\xfc\\xfd\\xfe\\xff\"";
|
||||
|
||||
assert_eq!(expected, format!("{:?}", Bytes::from(vec)));
|
||||
}
|
21
ntex-bytes/tests/test_iter.rs
Normal file
21
ntex-bytes/tests/test_iter.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
#![deny(warnings, rust_2018_idioms)]
|
||||
|
||||
use ntex_bytes::Bytes;
|
||||
|
||||
#[test]
|
||||
fn iter_len() {
|
||||
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_static(b"");
|
||||
let iter = buf.iter();
|
||||
|
||||
assert_eq!(iter.size_hint(), (0, Some(0)));
|
||||
assert_eq!(iter.len(), 0);
|
||||
}
|
20
ntex-bytes/tests/test_serde.rs
Normal file
20
ntex-bytes/tests/test_serde.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
#![cfg(feature = "serde")]
|
||||
#![deny(warnings, rust_2018_idioms)]
|
||||
|
||||
use serde_test::{assert_tokens, Token};
|
||||
|
||||
#[test]
|
||||
fn test_ser_de_empty() {
|
||||
let b = bytes::Bytes::new();
|
||||
assert_tokens(&b, &[Token::Bytes(b"")]);
|
||||
let b = bytes::BytesMut::with_capacity(0);
|
||||
assert_tokens(&b, &[Token::Bytes(b"")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ser_de() {
|
||||
let b = bytes::Bytes::from(&b"bytes"[..]);
|
||||
assert_tokens(&b, &[Token::Bytes(b"bytes")]);
|
||||
let b = bytes::BytesMut::from(&b"bytes"[..]);
|
||||
assert_tokens(&b, &[Token::Bytes(b"bytes")]);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue