mirror of
https://github.com/tokio-rs/bytes.git
synced 2026-08-08 00:00:26 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3240fb9cd9 | ||
|
|
9ae51c9f0c | ||
|
|
2b0602e756 | ||
|
|
3f5890be70 | ||
|
|
70ee87ea29 | ||
|
|
edf1af958a | ||
|
|
7110d57b2f | ||
|
|
07db74b009 | ||
|
|
6af66c4f21 | ||
|
|
fa44c7e355 | ||
|
|
2c0cb1b6b8 | ||
|
|
b196559818 | ||
|
|
37f6cabd96 | ||
|
|
e5c7ef3b86 | ||
|
|
30bd7c1f21 | ||
|
|
923d927bd1 | ||
|
|
0b4185c716 | ||
|
|
e158160418 | ||
|
|
4645f6ec4b | ||
|
|
1a6901cdcd | ||
|
|
9aa24ebea1 | ||
|
|
627864187c | ||
|
|
b78bb3baaa | ||
|
|
6c6c55d8e1 | ||
|
|
613d4bd5d5 | ||
|
|
dc9c8e304e | ||
|
|
bed128b2c0 | ||
|
|
5a265cc8eb | ||
|
|
4fe4e9429a | ||
|
|
9a4018e757 | ||
|
|
99fba239db | ||
|
|
dcd6c184e4 | ||
|
|
9e6d65a1d6 | ||
|
|
02b6144644 | ||
|
|
2e319b51be | ||
|
|
06b94c55b0 | ||
|
|
d70f575afd | ||
|
|
933b8b26f6 | ||
|
|
b44fc31463 | ||
|
|
d0142aa6da | ||
|
|
94396162b2 | ||
|
|
bb9bf7ee3e | ||
|
|
4462056e26 | ||
|
|
30c0e4e9c8 | ||
|
|
d19c929018 | ||
|
|
8fec8a92ad | ||
|
|
4f8c565111 | ||
|
|
fd8f716e68 | ||
|
|
22a5fb8d9b | ||
|
|
e842296c4d | ||
|
|
f7f8d6c9ef | ||
|
|
87160b6232 | ||
|
|
4466b75ae4 |
+6
-3
@@ -19,7 +19,7 @@ matrix:
|
||||
#
|
||||
# This job will also build and deploy the docs to gh-pages.
|
||||
- env: TARGET=x86_64-unknown-linux-gnu
|
||||
rust: 1.10.0
|
||||
rust: 1.15.0
|
||||
after_success:
|
||||
- |
|
||||
pip install 'travis-cargo<0.2' --user &&
|
||||
@@ -30,8 +30,11 @@ matrix:
|
||||
# Run tests on some extra platforms
|
||||
- env: TARGET=i686-unknown-linux-gnu
|
||||
- env: TARGET=armv7-unknown-linux-gnueabihf
|
||||
- env: TARGET=powerpc-unknown-linux-gnu
|
||||
- env: TARGET=powerpc64-unknown-linux-gnu
|
||||
- env: RUST_TEST_THREADS=1 TARGET=powerpc-unknown-linux-gnu
|
||||
- env: RUST_TEST_THREADS=1 TARGET=powerpc64-unknown-linux-gnu
|
||||
|
||||
# Serde implementation
|
||||
- env: EXTRA_ARGS="--features serde"
|
||||
|
||||
before_install: set -e
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# 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
|
||||
+4
-2
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
|
||||
name = "bytes"
|
||||
version = "0.4.0"
|
||||
version = "0.4.4"
|
||||
license = "MIT"
|
||||
authors = ["Carl Lerche <[email protected]>"]
|
||||
description = "Types and traits for working with bytes"
|
||||
@@ -21,6 +21,8 @@ categories = ["network-programming", "data-structures"]
|
||||
|
||||
[dependencies]
|
||||
byteorder = "1.0.0"
|
||||
iovec = "0.1"
|
||||
serde = { version = "1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio-core = "0.1.0"
|
||||
serde_test = "1.0"
|
||||
|
||||
@@ -24,6 +24,15 @@ extern crate bytes;
|
||||
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", features = ["serde"] }
|
||||
```
|
||||
|
||||
# License
|
||||
|
||||
`bytes` is primarily distributed under the terms of both the MIT license and the
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
#![feature(test)]
|
||||
|
||||
extern crate bytes;
|
||||
extern crate test;
|
||||
|
||||
use test::Bencher;
|
||||
use bytes::{Bytes, BytesMut, BufMut};
|
||||
|
||||
#[bench]
|
||||
fn alloc_small(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
test::black_box(BytesMut::with_capacity(12));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn alloc_mid(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
test::black_box(BytesMut::with_capacity(128));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn alloc_big(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
test::black_box(BytesMut::with_capacity(4096));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn 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 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 slice_empty(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
// Use empty vec to avoid measure of allocation/deallocation
|
||||
let bytes = Bytes::from(Vec::new());
|
||||
(bytes.slice(0, 0), bytes)
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn slice_not_empty(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let b = Bytes::from(b"aabbccddeeffgghh".to_vec());
|
||||
for _ in 0..1024 {
|
||||
test::black_box(b.slice(3, 5));
|
||||
test::black_box(&b);
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
#![feature(test)]
|
||||
|
||||
extern crate tokio_core;
|
||||
extern crate bytes;
|
||||
extern crate test;
|
||||
|
||||
mod bench_easy_buf {
|
||||
use test::{self, Bencher};
|
||||
use tokio_core::io::EasyBuf;
|
||||
|
||||
#[bench]
|
||||
fn alloc_small(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
test::black_box(EasyBuf::with_capacity(12));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn alloc_mid(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
test::black_box(EasyBuf::with_capacity(128));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn alloc_big(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
test::black_box(EasyBuf::with_capacity(4096));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deref_front(b: &mut Bencher) {
|
||||
let mut buf = EasyBuf::with_capacity(4096);
|
||||
buf.get_mut().extend_from_slice(&[0; 1024][..]);
|
||||
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
test::black_box(buf.as_slice());
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deref_mid(b: &mut Bencher) {
|
||||
let mut buf = EasyBuf::with_capacity(4096);
|
||||
buf.get_mut().extend_from_slice(&[0; 1024][..]);
|
||||
let _a = buf.drain_to(512);
|
||||
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
test::black_box(buf.as_slice());
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn alloc_write_drain_to_mid(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let mut buf = EasyBuf::with_capacity(128);
|
||||
buf.get_mut().extend_from_slice(&[0u8; 64]);
|
||||
test::black_box(buf.drain_to(64));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn drain_write_drain(b: &mut Bencher) {
|
||||
let data = [0u8; 128];
|
||||
|
||||
b.iter(|| {
|
||||
let mut buf = EasyBuf::with_capacity(1024);
|
||||
let mut parts = Vec::with_capacity(8);
|
||||
|
||||
for _ in 0..8 {
|
||||
buf.get_mut().extend_from_slice(&data[..]);
|
||||
parts.push(buf.drain_to(128));
|
||||
}
|
||||
|
||||
test::black_box(parts);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
mod bench_bytes {
|
||||
use test::{self, Bencher};
|
||||
use bytes::{BytesMut, BufMut};
|
||||
|
||||
#[bench]
|
||||
fn alloc_small(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
test::black_box(BytesMut::with_capacity(12));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn alloc_mid(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
test::black_box(BytesMut::with_capacity(128));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn alloc_big(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
test::black_box(BytesMut::with_capacity(4096));
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn 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 alloc_write_drain_to_mid(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let mut buf = BytesMut::with_capacity(128);
|
||||
buf.put_slice(&[0u8; 64]);
|
||||
test::black_box(buf.drain_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.drain_to(128));
|
||||
}
|
||||
|
||||
test::black_box(parts);
|
||||
})
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -3,13 +3,13 @@
|
||||
set -ex
|
||||
|
||||
main() {
|
||||
cross build --target $TARGET
|
||||
cross build --target $TARGET $EXTRA_ARGS
|
||||
|
||||
if [ ! -z $DISABLE_TESTS ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
cross test --target $TARGET
|
||||
cross test --target $TARGET $EXTRA_ARGS
|
||||
}
|
||||
|
||||
# we don't run the "test phase" when doing deploys
|
||||
|
||||
-1733
File diff suppressed because it is too large
Load Diff
+751
@@ -0,0 +1,751 @@
|
||||
use super::{IntoBuf, Take, Reader, Iter, FromBuf, Chain};
|
||||
use byteorder::ByteOrder;
|
||||
use iovec::IoVec;
|
||||
|
||||
use std::{cmp, io, ptr};
|
||||
|
||||
/// Read bytes from a buffer.
|
||||
///
|
||||
/// A buffer stores bytes in memory such that read operations are infallible.
|
||||
/// The underlying storage may or may not be in contiguous memory. A `Buf` value
|
||||
/// is a cursor into the buffer. Reading from `Buf` advances the cursor
|
||||
/// position. It can be thought of as an efficient `Iterator` for collections of
|
||||
/// bytes.
|
||||
///
|
||||
/// The simplest `Buf` is a `Cursor` wrapping a `[u8]`.
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::Buf;
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"hello world");
|
||||
///
|
||||
/// assert_eq!(b'h', buf.get_u8());
|
||||
/// assert_eq!(b'e', buf.get_u8());
|
||||
/// assert_eq!(b'l', buf.get_u8());
|
||||
///
|
||||
/// let mut rest = [0; 8];
|
||||
/// buf.copy_to_slice(&mut rest);
|
||||
///
|
||||
/// assert_eq!(&rest[..], b"lo world");
|
||||
/// ```
|
||||
pub trait Buf {
|
||||
/// Returns the number of bytes between the current position and the end of
|
||||
/// the buffer.
|
||||
///
|
||||
/// This value is greater than or equal to the length of the slice returned
|
||||
/// by `bytes`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::Buf;
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"hello world");
|
||||
///
|
||||
/// assert_eq!(buf.remaining(), 11);
|
||||
///
|
||||
/// buf.get_u8();
|
||||
///
|
||||
/// assert_eq!(buf.remaining(), 10);
|
||||
/// ```
|
||||
///
|
||||
/// # Implementer notes
|
||||
///
|
||||
/// Implementations of `remaining` should ensure that the return value does
|
||||
/// not change unless a call is made to `advance` or any other function that
|
||||
/// is documented to change the `Buf`'s current position.
|
||||
fn remaining(&self) -> usize;
|
||||
|
||||
/// Returns a slice starting at the current position and of length between 0
|
||||
/// and `Buf::remaining()`.
|
||||
///
|
||||
/// This is a lower level function. Most operations are done with other
|
||||
/// functions.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::Buf;
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"hello world");
|
||||
///
|
||||
/// assert_eq!(buf.bytes(), b"hello world");
|
||||
///
|
||||
/// buf.advance(6);
|
||||
///
|
||||
/// assert_eq!(buf.bytes(), b"world");
|
||||
/// ```
|
||||
///
|
||||
/// # Implementer notes
|
||||
///
|
||||
/// This function should never panic. Once the end of the buffer is reached,
|
||||
/// i.e., `Buf::remaining` returns 0, calls to `bytes` should return an
|
||||
/// empty slice.
|
||||
fn bytes(&self) -> &[u8];
|
||||
|
||||
/// Fills `dst` with potentially multiple slices starting at `self`'s
|
||||
/// current position.
|
||||
///
|
||||
/// If the `Buf` is backed by disjoint slices of bytes, `bytes_vec` enables
|
||||
/// fetching more than one slice at once. `dst` is a slice of `IoVec`
|
||||
/// references, enabling the slice to be directly used with [`writev`]
|
||||
/// without any further conversion. The sum of the lengths of all the
|
||||
/// buffers in `dst` will be less than or equal to `Buf::remaining()`.
|
||||
///
|
||||
/// The entries in `dst` will be overwritten, but the data **contained** by
|
||||
/// the slices **will not** be modified. If `bytes_vec` does not fill every
|
||||
/// entry in `dst`, then `dst` is guaranteed to contain all remaining slices
|
||||
/// in `self.
|
||||
///
|
||||
/// This is a lower level function. Most operations are done with other
|
||||
/// functions.
|
||||
///
|
||||
/// # Implementer notes
|
||||
///
|
||||
/// This function should never panic. Once the end of the buffer is reached,
|
||||
/// i.e., `Buf::remaining` returns 0, calls to `bytes_vec` must return 0
|
||||
/// without mutating `dst`.
|
||||
///
|
||||
/// Implementations should also take care to properly handle being called
|
||||
/// with `dst` being a zero length slice.
|
||||
///
|
||||
/// [`writev`]: http://man7.org/linux/man-pages/man2/readv.2.html
|
||||
fn bytes_vec<'a>(&'a self, dst: &mut [&'a IoVec]) -> usize {
|
||||
if dst.is_empty() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if self.has_remaining() {
|
||||
dst[0] = self.bytes().into();
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
/// Advance the internal cursor of the Buf
|
||||
///
|
||||
/// The next call to `bytes` will return a slice starting `cnt` bytes
|
||||
/// further into the underlying buffer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::Buf;
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"hello world");
|
||||
///
|
||||
/// assert_eq!(buf.bytes(), b"hello world");
|
||||
///
|
||||
/// buf.advance(6);
|
||||
///
|
||||
/// assert_eq!(buf.bytes(), b"world");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function **may** panic if `cnt > self.remaining()`.
|
||||
///
|
||||
/// # Implementer notes
|
||||
///
|
||||
/// It is recommended for implementations of `advance` to panic if `cnt >
|
||||
/// self.remaining()`. If the implementation does not panic, the call must
|
||||
/// behave as if `cnt == self.remaining()`.
|
||||
///
|
||||
/// A call with `cnt == 0` should never panic and be a no-op.
|
||||
fn advance(&mut self, cnt: usize);
|
||||
|
||||
/// Returns true if there are any more bytes to consume
|
||||
///
|
||||
/// This is equivalent to `self.remaining() != 0`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::Buf;
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"a");
|
||||
///
|
||||
/// assert!(buf.has_remaining());
|
||||
///
|
||||
/// buf.get_u8();
|
||||
///
|
||||
/// assert!(!buf.has_remaining());
|
||||
/// ```
|
||||
fn has_remaining(&self) -> bool {
|
||||
self.remaining() > 0
|
||||
}
|
||||
|
||||
/// Copies bytes from `self` into `dst`.
|
||||
///
|
||||
/// The cursor is advanced by the number of bytes copied. `self` must have
|
||||
/// enough remaining bytes to fill `dst`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::Buf;
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"hello world");
|
||||
/// let mut dst = [0; 5];
|
||||
///
|
||||
/// buf.copy_to_slice(&mut dst);
|
||||
/// assert_eq!(b"hello", &dst);
|
||||
/// assert_eq!(6, buf.remaining());
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if `self.remaining() < dst.len()`
|
||||
fn copy_to_slice(&mut self, dst: &mut [u8]) {
|
||||
let mut off = 0;
|
||||
|
||||
assert!(self.remaining() >= dst.len());
|
||||
|
||||
while off < dst.len() {
|
||||
let cnt;
|
||||
|
||||
unsafe {
|
||||
let src = self.bytes();
|
||||
cnt = cmp::min(src.len(), dst.len() - off);
|
||||
|
||||
ptr::copy_nonoverlapping(
|
||||
src.as_ptr(), dst[off..].as_mut_ptr(), cnt);
|
||||
|
||||
off += src.len();
|
||||
}
|
||||
|
||||
self.advance(cnt);
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets an unsigned 8 bit integer from `self`.
|
||||
///
|
||||
/// The current position is advanced by 1.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::Buf;
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"\x08 hello");
|
||||
/// assert_eq!(8, buf.get_u8());
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is no more remaining data in `self`.
|
||||
fn get_u8(&mut self) -> u8 {
|
||||
let mut buf = [0; 1];
|
||||
self.copy_to_slice(&mut buf);
|
||||
buf[0]
|
||||
}
|
||||
|
||||
/// Gets a signed 8 bit integer from `self`.
|
||||
///
|
||||
/// The current position is advanced by 1.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::Buf;
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"\x08 hello");
|
||||
/// assert_eq!(8, buf.get_i8());
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is no more remaining data in `self`.
|
||||
fn get_i8(&mut self) -> i8 {
|
||||
let mut buf = [0; 1];
|
||||
self.copy_to_slice(&mut buf);
|
||||
buf[0] as i8
|
||||
}
|
||||
|
||||
/// Gets an unsigned 16 bit integer from `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 2.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, BigEndian};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"\x08\x09 hello");
|
||||
/// assert_eq!(0x0809, buf.get_u16::<BigEndian>());
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining data in `self`.
|
||||
fn get_u16<T: ByteOrder>(&mut self) -> u16 {
|
||||
let mut buf = [0; 2];
|
||||
self.copy_to_slice(&mut buf);
|
||||
T::read_u16(&buf)
|
||||
}
|
||||
|
||||
/// Gets a signed 16 bit integer from `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 2.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, BigEndian};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"\x08\x09 hello");
|
||||
/// assert_eq!(0x0809, buf.get_i16::<BigEndian>());
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining data in `self`.
|
||||
fn get_i16<T: ByteOrder>(&mut self) -> i16 {
|
||||
let mut buf = [0; 2];
|
||||
self.copy_to_slice(&mut buf);
|
||||
T::read_i16(&buf)
|
||||
}
|
||||
|
||||
/// Gets an unsigned 32 bit integer from `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 4.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, BigEndian};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"\x08\x09\xA0\xA1 hello");
|
||||
/// assert_eq!(0x0809A0A1, buf.get_u32::<BigEndian>());
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining data in `self`.
|
||||
fn get_u32<T: ByteOrder>(&mut self) -> u32 {
|
||||
let mut buf = [0; 4];
|
||||
self.copy_to_slice(&mut buf);
|
||||
T::read_u32(&buf)
|
||||
}
|
||||
|
||||
/// Gets a signed 32 bit integer from `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 4.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, BigEndian};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"\x08\x09\xA0\xA1 hello");
|
||||
/// assert_eq!(0x0809A0A1, buf.get_i32::<BigEndian>());
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining data in `self`.
|
||||
fn get_i32<T: ByteOrder>(&mut self) -> i32 {
|
||||
let mut buf = [0; 4];
|
||||
self.copy_to_slice(&mut buf);
|
||||
T::read_i32(&buf)
|
||||
}
|
||||
|
||||
/// Gets an unsigned 64 bit integer from `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 8.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, BigEndian};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"\x01\x02\x03\x04\x05\x06\x07\x08 hello");
|
||||
/// assert_eq!(0x0102030405060708, buf.get_u64::<BigEndian>());
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining data in `self`.
|
||||
fn get_u64<T: ByteOrder>(&mut self) -> u64 {
|
||||
let mut buf = [0; 8];
|
||||
self.copy_to_slice(&mut buf);
|
||||
T::read_u64(&buf)
|
||||
}
|
||||
|
||||
/// Gets a signed 64 bit integer from `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 8.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, BigEndian};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"\x01\x02\x03\x04\x05\x06\x07\x08 hello");
|
||||
/// assert_eq!(0x0102030405060708, buf.get_i64::<BigEndian>());
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining data in `self`.
|
||||
fn get_i64<T: ByteOrder>(&mut self) -> i64 {
|
||||
let mut buf = [0; 8];
|
||||
self.copy_to_slice(&mut buf);
|
||||
T::read_i64(&buf)
|
||||
}
|
||||
|
||||
/// Gets an unsigned n-byte integer from `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by `nbytes`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, BigEndian};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"\x01\x02\x03 hello");
|
||||
/// assert_eq!(0x010203, buf.get_uint::<BigEndian>(3));
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining data in `self`.
|
||||
fn get_uint<T: ByteOrder>(&mut self, nbytes: usize) -> u64 {
|
||||
let mut buf = [0; 8];
|
||||
self.copy_to_slice(&mut buf[..nbytes]);
|
||||
T::read_uint(&buf[..nbytes], nbytes)
|
||||
}
|
||||
|
||||
/// Gets a signed n-byte integer from `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by `nbytes`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, BigEndian};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"\x01\x02\x03 hello");
|
||||
/// assert_eq!(0x010203, buf.get_int::<BigEndian>(3));
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining data in `self`.
|
||||
fn get_int<T: ByteOrder>(&mut self, nbytes: usize) -> i64 {
|
||||
let mut buf = [0; 8];
|
||||
self.copy_to_slice(&mut buf[..nbytes]);
|
||||
T::read_int(&buf[..nbytes], nbytes)
|
||||
}
|
||||
|
||||
/// Gets an IEEE754 single-precision (4 bytes) floating point number from
|
||||
/// `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 4.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, BigEndian};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"\x3F\x99\x99\x9A hello");
|
||||
/// assert_eq!(1.2f32, buf.get_f32::<BigEndian>());
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining data in `self`.
|
||||
fn get_f32<T: ByteOrder>(&mut self) -> f32 {
|
||||
let mut buf = [0; 4];
|
||||
self.copy_to_slice(&mut buf);
|
||||
T::read_f32(&buf)
|
||||
}
|
||||
|
||||
/// Gets an IEEE754 double-precision (8 bytes) floating point number from
|
||||
/// `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 8.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, BigEndian};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"\x3F\xF3\x33\x33\x33\x33\x33\x33 hello");
|
||||
/// assert_eq!(1.2f64, buf.get_f64::<BigEndian>());
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining data in `self`.
|
||||
fn get_f64<T: ByteOrder>(&mut self) -> f64 {
|
||||
let mut buf = [0; 8];
|
||||
self.copy_to_slice(&mut buf);
|
||||
T::read_f64(&buf)
|
||||
}
|
||||
|
||||
/// Transforms a `Buf` into a concrete buffer.
|
||||
///
|
||||
/// `collect()` can operate on any value that implements `Buf`, and turn it
|
||||
/// into the relevent concrete buffer type.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Collecting a buffer and loading the contents into a `Vec<u8>`.
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, Bytes, IntoBuf};
|
||||
///
|
||||
/// let buf = Bytes::from(&b"hello world"[..]).into_buf();
|
||||
/// let vec: Vec<u8> = buf.collect();
|
||||
///
|
||||
/// assert_eq!(vec, &b"hello world"[..]);
|
||||
/// ```
|
||||
fn collect<B>(self) -> B
|
||||
where Self: Sized,
|
||||
B: FromBuf,
|
||||
{
|
||||
B::from_buf(self)
|
||||
}
|
||||
|
||||
/// Creates an adaptor which will read at most `limit` bytes from `self`.
|
||||
///
|
||||
/// This function returns a new instance of `Buf` which will read at most
|
||||
/// `limit` bytes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, BufMut};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new("hello world").take(5);
|
||||
/// let mut dst = vec![];
|
||||
///
|
||||
/// dst.put(&mut buf);
|
||||
/// assert_eq!(dst, b"hello");
|
||||
///
|
||||
/// let mut buf = buf.into_inner();
|
||||
/// dst.clear();
|
||||
/// dst.put(&mut buf);
|
||||
/// assert_eq!(dst, b" world");
|
||||
/// ```
|
||||
fn take(self, limit: usize) -> Take<Self>
|
||||
where Self: Sized
|
||||
{
|
||||
super::take::new(self, limit)
|
||||
}
|
||||
|
||||
/// Creates an adaptor which will chain this buffer with another.
|
||||
///
|
||||
/// The returned `Buf` instance will first consume all bytes from `self`.
|
||||
/// Afterwards the output is equivalent to the output of next.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Bytes, Buf, IntoBuf};
|
||||
/// use bytes::buf::Chain;
|
||||
///
|
||||
/// let buf = Bytes::from(&b"hello "[..]).into_buf()
|
||||
/// .chain(Bytes::from(&b"world"[..]));
|
||||
///
|
||||
/// let full: Bytes = buf.collect();
|
||||
/// assert_eq!(full[..], b"hello world"[..]);
|
||||
/// ```
|
||||
fn chain<U>(self, next: U) -> Chain<Self, U::Buf>
|
||||
where U: IntoBuf,
|
||||
Self: Sized,
|
||||
{
|
||||
Chain::new(self, next.into_buf())
|
||||
}
|
||||
|
||||
/// Creates a "by reference" adaptor for this instance of `Buf`.
|
||||
///
|
||||
/// The returned adaptor also implements `Buf` and will simply borrow `self`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, BufMut};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new("hello world");
|
||||
/// let mut dst = vec![];
|
||||
///
|
||||
/// {
|
||||
/// let mut reference = buf.by_ref();
|
||||
/// dst.put(&mut reference.take(5));
|
||||
/// assert_eq!(dst, b"hello");
|
||||
/// } // drop our &mut reference so we can use `buf` again
|
||||
///
|
||||
/// dst.clear();
|
||||
/// dst.put(&mut buf);
|
||||
/// assert_eq!(dst, b" world");
|
||||
/// ```
|
||||
fn by_ref(&mut self) -> &mut Self where Self: Sized {
|
||||
self
|
||||
}
|
||||
|
||||
/// Creates an adaptor which implements the `Read` trait for `self`.
|
||||
///
|
||||
/// This function returns a new value which implements `Read` by adapting
|
||||
/// the `Read` trait functions to the `Buf` trait functions. Given that
|
||||
/// `Buf` operations are infallible, none of the `Read` functions will
|
||||
/// return with `Err`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, IntoBuf, Bytes};
|
||||
/// use std::io::Read;
|
||||
///
|
||||
/// let buf = Bytes::from("hello world").into_buf();
|
||||
///
|
||||
/// let mut reader = buf.reader();
|
||||
/// let mut dst = [0; 1024];
|
||||
///
|
||||
/// let num = reader.read(&mut dst).unwrap();
|
||||
///
|
||||
/// assert_eq!(11, num);
|
||||
/// assert_eq!(&dst[..11], b"hello world");
|
||||
/// ```
|
||||
fn reader(self) -> Reader<Self> where Self: Sized {
|
||||
super::reader::new(self)
|
||||
}
|
||||
|
||||
/// Returns an iterator over the bytes contained by the buffer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, IntoBuf, Bytes};
|
||||
///
|
||||
/// let buf = Bytes::from(&b"abc"[..]).into_buf();
|
||||
/// let mut iter = buf.iter();
|
||||
///
|
||||
/// assert_eq!(iter.next(), Some(b'a'));
|
||||
/// assert_eq!(iter.next(), Some(b'b'));
|
||||
/// assert_eq!(iter.next(), Some(b'c'));
|
||||
/// assert_eq!(iter.next(), None);
|
||||
/// ```
|
||||
fn iter(self) -> Iter<Self> where Self: Sized {
|
||||
super::iter::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Buf + ?Sized> Buf for &'a mut T {
|
||||
fn remaining(&self) -> usize {
|
||||
(**self).remaining()
|
||||
}
|
||||
|
||||
fn bytes(&self) -> &[u8] {
|
||||
(**self).bytes()
|
||||
}
|
||||
|
||||
fn bytes_vec<'b>(&'b self, dst: &mut [&'b IoVec]) -> usize {
|
||||
(**self).bytes_vec(dst)
|
||||
}
|
||||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
(**self).advance(cnt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Buf + ?Sized> Buf for Box<T> {
|
||||
fn remaining(&self) -> usize {
|
||||
(**self).remaining()
|
||||
}
|
||||
|
||||
fn bytes(&self) -> &[u8] {
|
||||
(**self).bytes()
|
||||
}
|
||||
|
||||
fn bytes_vec<'b>(&'b self, dst: &mut [&'b IoVec]) -> usize {
|
||||
(**self).bytes_vec(dst)
|
||||
}
|
||||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
(**self).advance(cnt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<[u8]>> Buf for 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 bytes(&self) -> &[u8] {
|
||||
let len = self.get_ref().as_ref().len();
|
||||
let pos = self.position() as usize;
|
||||
|
||||
if pos >= len {
|
||||
return Default::default();
|
||||
}
|
||||
|
||||
&(self.get_ref().as_ref())[pos..]
|
||||
}
|
||||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
let pos = (self.position() as usize)
|
||||
.checked_add(cnt).expect("overflow");
|
||||
|
||||
assert!(pos <= self.get_ref().as_ref().len());
|
||||
|
||||
self.set_position(pos as u64);
|
||||
}
|
||||
}
|
||||
|
||||
impl Buf for Option<[u8; 1]> {
|
||||
fn remaining(&self) -> usize {
|
||||
if self.is_some() {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn bytes(&self) -> &[u8] {
|
||||
self.as_ref().map(AsRef::as_ref)
|
||||
.unwrap_or(Default::default())
|
||||
}
|
||||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
if cnt == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.is_none() {
|
||||
panic!("overflow");
|
||||
} else {
|
||||
assert_eq!(1, cnt);
|
||||
*self = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,736 @@
|
||||
use super::{IntoBuf, Writer};
|
||||
use byteorder::ByteOrder;
|
||||
use iovec::IoVec;
|
||||
|
||||
use std::{cmp, io, 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 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 bytes::BufMut;
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut dst = [0; 10];
|
||||
/// let mut buf = Cursor::new(&mut dst[..]);
|
||||
///
|
||||
/// assert_eq!(10, buf.remaining_mut());
|
||||
/// buf.put("hello");
|
||||
///
|
||||
/// assert_eq!(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 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 bytes::BufMut;
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut dst = [0; 5];
|
||||
/// let mut buf = Cursor::new(&mut dst);
|
||||
///
|
||||
/// assert!(buf.has_remaining_mut());
|
||||
///
|
||||
/// buf.put("hello");
|
||||
///
|
||||
/// assert!(!buf.has_remaining_mut());
|
||||
/// ```
|
||||
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()`.
|
||||
///
|
||||
/// This is a lower level function. Most operations are done with other
|
||||
/// functions.
|
||||
///
|
||||
/// The returned byte slice may represent uninitialized memory.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use 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 bytes_mut(&mut self) -> &mut [u8];
|
||||
|
||||
/// Fills `dst` with potentially multiple mutable slices starting at `self`'s
|
||||
/// current position.
|
||||
///
|
||||
/// If the `BufMut` is backed by disjoint slices of bytes, `bytes_vec_mut`
|
||||
/// enables fetching more than one slice at once. `dst` is a slice of
|
||||
/// mutable `IoVec` references, enabling the slice to be directly used with
|
||||
/// [`readv`] without any further conversion. The sum of the lengths of all
|
||||
/// the buffers in `dst` will be less than or equal to
|
||||
/// `Buf::remaining_mut()`.
|
||||
///
|
||||
/// The entries in `dst` will be overwritten, but the data **contained** by
|
||||
/// the slices **will not** be modified. If `bytes_vec_mut` does not fill every
|
||||
/// entry in `dst`, then `dst` is guaranteed to contain all remaining slices
|
||||
/// in `self.
|
||||
///
|
||||
/// This is a lower level function. Most operations are done with other
|
||||
/// functions.
|
||||
///
|
||||
/// # Implementer notes
|
||||
///
|
||||
/// This function should never panic. Once the end of the buffer is reached,
|
||||
/// i.e., `BufMut::remaining_mut` returns 0, calls to `bytes_vec_mut` must
|
||||
/// return 0 without mutating `dst`.
|
||||
///
|
||||
/// Implementations should also take care to properly handle being called
|
||||
/// with `dst` being a zero length slice.
|
||||
///
|
||||
/// [`readv`]: http://man7.org/linux/man-pages/man2/readv.2.html
|
||||
unsafe fn bytes_vec_mut<'a>(&'a mut self, dst: &mut [&'a mut IoVec]) -> usize {
|
||||
if dst.is_empty() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if self.has_remaining_mut() {
|
||||
dst[0] = self.bytes_mut().into();
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
/// Transfer bytes into `self` from `src` and advance the cursor by the
|
||||
/// number of bytes written.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::BufMut;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
///
|
||||
/// buf.put(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: IntoBuf>(&mut self, src: T) where Self: Sized {
|
||||
use super::Buf;
|
||||
|
||||
let mut src = src.into_buf();
|
||||
|
||||
assert!(self.remaining_mut() >= src.remaining());
|
||||
|
||||
while src.has_remaining() {
|
||||
let l;
|
||||
|
||||
unsafe {
|
||||
let s = src.bytes();
|
||||
let d = self.bytes_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 bytes::BufMut;
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut dst = [0; 6];
|
||||
///
|
||||
/// {
|
||||
/// let mut buf = Cursor::new(&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.bytes_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 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`.
|
||||
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 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 the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 2.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{BufMut, BigEndian};
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_u16::<BigEndian>(0x0809);
|
||||
/// assert_eq!(buf, b"\x08\x09");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
fn put_u16<T: ByteOrder>(&mut self, n: u16) {
|
||||
let mut buf = [0; 2];
|
||||
T::write_u16(&mut buf, n);
|
||||
self.put_slice(&buf)
|
||||
}
|
||||
|
||||
/// Writes a signed 16 bit integer to `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 2.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{BufMut, BigEndian};
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_i16::<BigEndian>(0x0809);
|
||||
/// assert_eq!(buf, b"\x08\x09");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
fn put_i16<T: ByteOrder>(&mut self, n: i16) {
|
||||
let mut buf = [0; 2];
|
||||
T::write_i16(&mut buf, n);
|
||||
self.put_slice(&buf)
|
||||
}
|
||||
|
||||
/// Writes an unsigned 32 bit integer to `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 4.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{BufMut, BigEndian};
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_u32::<BigEndian>(0x0809A0A1);
|
||||
/// assert_eq!(buf, b"\x08\x09\xA0\xA1");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
fn put_u32<T: ByteOrder>(&mut self, n: u32) {
|
||||
let mut buf = [0; 4];
|
||||
T::write_u32(&mut buf, n);
|
||||
self.put_slice(&buf)
|
||||
}
|
||||
|
||||
/// Writes a signed 32 bit integer to `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 4.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{BufMut, BigEndian};
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_i32::<BigEndian>(0x0809A0A1);
|
||||
/// assert_eq!(buf, b"\x08\x09\xA0\xA1");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
fn put_i32<T: ByteOrder>(&mut self, n: i32) {
|
||||
let mut buf = [0; 4];
|
||||
T::write_i32(&mut buf, n);
|
||||
self.put_slice(&buf)
|
||||
}
|
||||
|
||||
/// Writes an unsigned 64 bit integer to `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 8.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{BufMut, BigEndian};
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_u64::<BigEndian>(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`.
|
||||
fn put_u64<T: ByteOrder>(&mut self, n: u64) {
|
||||
let mut buf = [0; 8];
|
||||
T::write_u64(&mut buf, n);
|
||||
self.put_slice(&buf)
|
||||
}
|
||||
|
||||
/// Writes a signed 64 bit integer to `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 8.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{BufMut, BigEndian};
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_i64::<BigEndian>(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`.
|
||||
fn put_i64<T: ByteOrder>(&mut self, n: i64) {
|
||||
let mut buf = [0; 8];
|
||||
T::write_i64(&mut buf, n);
|
||||
self.put_slice(&buf)
|
||||
}
|
||||
|
||||
/// Writes an unsigned n-byte integer to `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by `nbytes`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{BufMut, BigEndian};
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_uint::<BigEndian>(0x010203, 3);
|
||||
/// assert_eq!(buf, b"\x01\x02\x03");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
fn put_uint<T: ByteOrder>(&mut self, n: u64, nbytes: usize) {
|
||||
let mut buf = [0; 8];
|
||||
T::write_uint(&mut buf, n, nbytes);
|
||||
self.put_slice(&buf[0..nbytes])
|
||||
}
|
||||
|
||||
/// Writes a signed n-byte integer to `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by `nbytes`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{BufMut, BigEndian};
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_int::<BigEndian>(0x010203, 3);
|
||||
/// assert_eq!(buf, b"\x01\x02\x03");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
fn put_int<T: ByteOrder>(&mut self, n: i64, nbytes: usize) {
|
||||
let mut buf = [0; 8];
|
||||
T::write_int(&mut buf, n, nbytes);
|
||||
self.put_slice(&buf[0..nbytes])
|
||||
}
|
||||
|
||||
/// Writes an IEEE754 single-precision (4 bytes) floating point number to
|
||||
/// `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 4.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{BufMut, BigEndian};
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_f32::<BigEndian>(1.2f32);
|
||||
/// assert_eq!(buf, b"\x3F\x99\x99\x9A");
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is not enough remaining capacity in
|
||||
/// `self`.
|
||||
fn put_f32<T: ByteOrder>(&mut self, n: f32) {
|
||||
let mut buf = [0; 4];
|
||||
T::write_f32(&mut buf, n);
|
||||
self.put_slice(&buf)
|
||||
}
|
||||
|
||||
/// Writes an IEEE754 double-precision (8 bytes) floating point number to
|
||||
/// `self` in the specified byte order.
|
||||
///
|
||||
/// The current position is advanced by 8.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{BufMut, BigEndian};
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
/// buf.put_f64::<BigEndian>(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`.
|
||||
fn put_f64<T: ByteOrder>(&mut self, n: f64) {
|
||||
let mut buf = [0; 8];
|
||||
T::write_f64(&mut buf, n);
|
||||
self.put_slice(&buf)
|
||||
}
|
||||
|
||||
/// Creates a "by reference" adaptor for this instance of `BufMut`.
|
||||
///
|
||||
/// The returned adapter also implements `BufMut` and will simply borrow
|
||||
/// `self`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::BufMut;
|
||||
/// use std::io;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
///
|
||||
/// {
|
||||
/// let mut reference = buf.by_ref();
|
||||
///
|
||||
/// // Adapt reference to `std::io::Write`.
|
||||
/// let mut writer = reference.writer();
|
||||
///
|
||||
/// // Use the buffer as a writter
|
||||
/// io::Write::write(&mut writer, &b"hello world"[..]).unwrap();
|
||||
/// } // drop our &mut reference so that we can use `buf` again
|
||||
///
|
||||
/// assert_eq!(buf, &b"hello world"[..]);
|
||||
/// ```
|
||||
fn by_ref(&mut self) -> &mut Self where Self: Sized {
|
||||
self
|
||||
}
|
||||
|
||||
/// 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 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<'a, T: BufMut + ?Sized> BufMut for &'a mut T {
|
||||
fn remaining_mut(&self) -> usize {
|
||||
(**self).remaining_mut()
|
||||
}
|
||||
|
||||
unsafe fn bytes_mut(&mut self) -> &mut [u8] {
|
||||
(**self).bytes_mut()
|
||||
}
|
||||
|
||||
unsafe fn bytes_vec_mut<'b>(&'b mut self, dst: &mut [&'b mut IoVec]) -> usize {
|
||||
(**self).bytes_vec_mut(dst)
|
||||
}
|
||||
|
||||
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 bytes_mut(&mut self) -> &mut [u8] {
|
||||
(**self).bytes_mut()
|
||||
}
|
||||
|
||||
unsafe fn bytes_vec_mut<'b>(&'b mut self, dst: &mut [&'b mut IoVec]) -> usize {
|
||||
(**self).bytes_vec_mut(dst)
|
||||
}
|
||||
|
||||
unsafe fn advance_mut(&mut self, cnt: usize) {
|
||||
(**self).advance_mut(cnt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsMut<[u8]> + AsRef<[u8]>> BufMut for io::Cursor<T> {
|
||||
fn remaining_mut(&self) -> usize {
|
||||
use Buf;
|
||||
self.remaining()
|
||||
}
|
||||
|
||||
/// Advance the internal cursor of the BufMut
|
||||
unsafe fn advance_mut(&mut self, cnt: usize) {
|
||||
use Buf;
|
||||
self.advance(cnt);
|
||||
}
|
||||
|
||||
/// Returns a mutable slice starting at the current BufMut position and of
|
||||
/// length between 0 and `BufMut::remaining()`.
|
||||
///
|
||||
/// The returned byte slice may represent uninitialized memory.
|
||||
unsafe fn bytes_mut(&mut self) -> &mut [u8] {
|
||||
let len = self.get_ref().as_ref().len();
|
||||
let pos = self.position() as usize;
|
||||
|
||||
if pos >= len {
|
||||
return Default::default();
|
||||
}
|
||||
|
||||
&mut (self.get_mut().as_mut())[pos..]
|
||||
}
|
||||
}
|
||||
|
||||
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 bytes_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..]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
use {Buf, BufMut};
|
||||
use iovec::IoVec;
|
||||
|
||||
/// A `Chain` sequences two buffers.
|
||||
///
|
||||
/// `Chain` is an adapter that links two underlying buffers and provides a
|
||||
/// continous view across both buffers. It is able to sequence either immutable
|
||||
/// buffers ([`Buf`] values) or mutable buffers ([`BufMut`] values).
|
||||
///
|
||||
/// This struct is generally created by calling [`Buf::chain`]. Please see that
|
||||
/// function's documentation for more detail.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Bytes, Buf, IntoBuf};
|
||||
/// use bytes::buf::Chain;
|
||||
///
|
||||
/// let buf = Bytes::from(&b"hello "[..]).into_buf()
|
||||
/// .chain(Bytes::from(&b"world"[..]));
|
||||
///
|
||||
/// let full: Bytes = buf.collect();
|
||||
/// assert_eq!(full[..], b"hello world"[..]);
|
||||
/// ```
|
||||
///
|
||||
/// [`Buf::chain`]: trait.Buf.html#method.chain
|
||||
/// [`Buf`]: trait.Buf.html
|
||||
/// [`BufMut`]: trait.BufMut.html
|
||||
#[derive(Debug)]
|
||||
pub struct Chain<T, U> {
|
||||
a: T,
|
||||
b: U,
|
||||
}
|
||||
|
||||
impl<T, U> Chain<T, U> {
|
||||
/// Creates a new `Chain` sequencing the provided values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::BytesMut;
|
||||
/// use bytes::buf::Chain;
|
||||
///
|
||||
/// let buf = Chain::new(
|
||||
/// BytesMut::with_capacity(1024),
|
||||
/// BytesMut::with_capacity(1024));
|
||||
///
|
||||
/// // Use the chained buffer
|
||||
/// ```
|
||||
pub fn new(a: T, b: U) -> Chain<T, U> {
|
||||
Chain {
|
||||
a: a,
|
||||
b: b,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a reference to the first underlying `Buf`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Bytes, Buf, IntoBuf};
|
||||
///
|
||||
/// let buf = Bytes::from(&b"hello"[..]).into_buf()
|
||||
/// .chain(Bytes::from(&b"world"[..]));
|
||||
///
|
||||
/// assert_eq!(buf.first_ref().get_ref()[..], b"hello"[..]);
|
||||
/// ```
|
||||
pub fn first_ref(&self) -> &T {
|
||||
&self.a
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the first underlying `Buf`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Bytes, Buf, IntoBuf};
|
||||
///
|
||||
/// let mut buf = Bytes::from(&b"hello "[..]).into_buf()
|
||||
/// .chain(Bytes::from(&b"world"[..]));
|
||||
///
|
||||
/// buf.first_mut().set_position(1);
|
||||
///
|
||||
/// let full: Bytes = buf.collect();
|
||||
/// assert_eq!(full[..], b"ello world"[..]);
|
||||
/// ```
|
||||
pub fn first_mut(&mut self) -> &mut T {
|
||||
&mut self.a
|
||||
}
|
||||
|
||||
/// Gets a reference to the last underlying `Buf`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Bytes, Buf, IntoBuf};
|
||||
///
|
||||
/// let buf = Bytes::from(&b"hello"[..]).into_buf()
|
||||
/// .chain(Bytes::from(&b"world"[..]));
|
||||
///
|
||||
/// assert_eq!(buf.last_ref().get_ref()[..], b"world"[..]);
|
||||
/// ```
|
||||
pub fn last_ref(&self) -> &U {
|
||||
&self.b
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the last underlying `Buf`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Bytes, Buf, IntoBuf};
|
||||
///
|
||||
/// let mut buf = Bytes::from(&b"hello "[..]).into_buf()
|
||||
/// .chain(Bytes::from(&b"world"[..]));
|
||||
///
|
||||
/// buf.last_mut().set_position(1);
|
||||
///
|
||||
/// let full: Bytes = buf.collect();
|
||||
/// assert_eq!(full[..], b"hello orld"[..]);
|
||||
/// ```
|
||||
pub fn last_mut(&mut self) -> &mut U {
|
||||
&mut self.b
|
||||
}
|
||||
|
||||
/// Consumes this `Chain`, returning the underlying values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Bytes, Buf, IntoBuf};
|
||||
///
|
||||
/// let buf = Bytes::from(&b"hello"[..]).into_buf()
|
||||
/// .chain(Bytes::from(&b"world"[..]));
|
||||
///
|
||||
/// let (first, last) = buf.into_inner();
|
||||
/// assert_eq!(first.get_ref()[..], b"hello"[..]);
|
||||
/// assert_eq!(last.get_ref()[..], b"world"[..]);
|
||||
/// ```
|
||||
pub fn into_inner(self) -> (T, U) {
|
||||
(self.a, self.b)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Buf for Chain<T, U>
|
||||
where T: Buf,
|
||||
U: Buf,
|
||||
{
|
||||
fn remaining(&self) -> usize {
|
||||
self.a.remaining() + self.b.remaining()
|
||||
}
|
||||
|
||||
fn bytes(&self) -> &[u8] {
|
||||
if self.a.has_remaining() {
|
||||
self.a.bytes()
|
||||
} else {
|
||||
self.b.bytes()
|
||||
}
|
||||
}
|
||||
|
||||
fn advance(&mut self, mut cnt: usize) {
|
||||
let a_rem = self.a.remaining();
|
||||
|
||||
if a_rem != 0 {
|
||||
if a_rem >= cnt {
|
||||
self.a.advance(cnt);
|
||||
return;
|
||||
}
|
||||
|
||||
// Consume what is left of a
|
||||
self.a.advance(a_rem);
|
||||
|
||||
cnt -= a_rem;
|
||||
}
|
||||
|
||||
self.b.advance(cnt);
|
||||
}
|
||||
|
||||
fn bytes_vec<'a>(&'a self, dst: &mut [&'a IoVec]) -> usize {
|
||||
let mut n = self.a.bytes_vec(dst);
|
||||
n += self.b.bytes_vec(&mut dst[n..]);
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> BufMut for Chain<T, U>
|
||||
where T: BufMut,
|
||||
U: BufMut,
|
||||
{
|
||||
fn remaining_mut(&self) -> usize {
|
||||
self.a.remaining_mut() + self.b.remaining_mut()
|
||||
}
|
||||
|
||||
unsafe fn bytes_mut(&mut self) -> &mut [u8] {
|
||||
if self.a.has_remaining_mut() {
|
||||
self.a.bytes_mut()
|
||||
} else {
|
||||
self.b.bytes_mut()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn advance_mut(&mut self, mut cnt: usize) {
|
||||
let a_rem = self.a.remaining_mut();
|
||||
|
||||
if a_rem != 0 {
|
||||
if a_rem >= cnt {
|
||||
self.a.advance_mut(cnt);
|
||||
return;
|
||||
}
|
||||
|
||||
// Consume what is left of a
|
||||
self.a.advance_mut(a_rem);
|
||||
|
||||
cnt -= a_rem;
|
||||
}
|
||||
|
||||
self.b.advance_mut(cnt);
|
||||
}
|
||||
|
||||
unsafe fn bytes_vec_mut<'a>(&'a mut self, dst: &mut [&'a mut IoVec]) -> usize {
|
||||
let mut n = self.a.bytes_vec_mut(dst);
|
||||
n += self.b.bytes_vec_mut(&mut dst[n..]);
|
||||
n
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
use {Buf, BufMut, IntoBuf, Bytes, BytesMut};
|
||||
|
||||
/// Conversion from a [`Buf`]
|
||||
///
|
||||
/// Implementing `FromBuf` for a type defines how it is created from a buffer.
|
||||
/// This is common for types which represent byte storage of some kind.
|
||||
///
|
||||
/// [`FromBuf::from_buf`] is rarely called explicitly, and it is instead used
|
||||
/// through [`Buf::collect`]. See [`Buf::collect`] documentation for more examples.
|
||||
///
|
||||
/// See also [`IntoBuf`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Bytes, IntoBuf};
|
||||
/// use bytes::buf::FromBuf;
|
||||
///
|
||||
/// let buf = Bytes::from(&b"hello world"[..]).into_buf();
|
||||
/// let vec = Vec::from_buf(buf);
|
||||
///
|
||||
/// assert_eq!(vec, &b"hello world"[..]);
|
||||
/// ```
|
||||
///
|
||||
/// Using [`Buf::collect`] to implicitly use `FromBuf`:
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, Bytes, IntoBuf};
|
||||
///
|
||||
/// let buf = Bytes::from(&b"hello world"[..]).into_buf();
|
||||
/// let vec: Vec<u8> = buf.collect();
|
||||
///
|
||||
/// assert_eq!(vec, &b"hello world"[..]);
|
||||
/// ```
|
||||
///
|
||||
/// Implementing `FromBuf` for your type:
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{BufMut, Bytes};
|
||||
/// use bytes::buf::{IntoBuf, FromBuf};
|
||||
///
|
||||
/// // A sample buffer, that's just a wrapper over Vec<u8>
|
||||
/// struct MyBuffer(Vec<u8>);
|
||||
///
|
||||
/// impl FromBuf for MyBuffer {
|
||||
/// fn from_buf<B>(buf: B) -> Self where B: IntoBuf {
|
||||
/// let mut v = Vec::new();
|
||||
/// v.put(buf.into_buf());
|
||||
/// MyBuffer(v)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // Now we can make a new buf
|
||||
/// let buf = Bytes::from(&b"hello world"[..]);
|
||||
///
|
||||
/// // And make a MyBuffer out of it
|
||||
/// let my_buf = MyBuffer::from_buf(buf);
|
||||
///
|
||||
/// assert_eq!(my_buf.0, &b"hello world"[..]);
|
||||
/// ```
|
||||
///
|
||||
/// [`Buf`]: trait.Buf.html
|
||||
/// [`FromBuf::from_buf`]: #method.from_buf
|
||||
/// [`Buf::collect`]: trait.Buf.html#method.collect
|
||||
/// [`IntoBuf`]: trait.IntoBuf.html
|
||||
pub trait FromBuf {
|
||||
/// Creates a value from a buffer.
|
||||
///
|
||||
/// See the [type-level documentation](#) for more details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Bytes, IntoBuf};
|
||||
/// use bytes::buf::FromBuf;
|
||||
///
|
||||
/// let buf = Bytes::from(&b"hello world"[..]).into_buf();
|
||||
/// let vec = Vec::from_buf(buf);
|
||||
///
|
||||
/// assert_eq!(vec, &b"hello world"[..]);
|
||||
/// ```
|
||||
fn from_buf<T>(buf: T) -> Self where T: IntoBuf;
|
||||
}
|
||||
|
||||
impl FromBuf for Vec<u8> {
|
||||
fn from_buf<T>(buf: T) -> Self
|
||||
where T: IntoBuf
|
||||
{
|
||||
let buf = buf.into_buf();
|
||||
let mut ret = Vec::with_capacity(buf.remaining());
|
||||
ret.put(buf);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl FromBuf for Bytes {
|
||||
fn from_buf<T>(buf: T) -> Self
|
||||
where T: IntoBuf
|
||||
{
|
||||
BytesMut::from_buf(buf).freeze()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromBuf for BytesMut {
|
||||
fn from_buf<T>(buf: T) -> Self
|
||||
where T: IntoBuf
|
||||
{
|
||||
let buf = buf.into_buf();
|
||||
let mut ret = BytesMut::with_capacity(buf.remaining());
|
||||
ret.put(buf);
|
||||
ret
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
use super::{Buf};
|
||||
|
||||
use std::io;
|
||||
|
||||
/// Conversion into a `Buf`
|
||||
///
|
||||
/// An `IntoBuf` implementation defines how to convert a value into a `Buf`.
|
||||
/// This is common for types that represent byte storage of some kind. `IntoBuf`
|
||||
/// may be implemented directly for types or on references for those types.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, IntoBuf, BigEndian};
|
||||
///
|
||||
/// let bytes = b"\x00\x01hello world";
|
||||
/// let mut buf = bytes.into_buf();
|
||||
///
|
||||
/// assert_eq!(1, buf.get_u16::<BigEndian>());
|
||||
///
|
||||
/// let mut rest = [0; 11];
|
||||
/// buf.copy_to_slice(&mut rest);
|
||||
///
|
||||
/// assert_eq!(b"hello world", &rest);
|
||||
/// ```
|
||||
pub trait IntoBuf {
|
||||
/// The `Buf` type that `self` is being converted into
|
||||
type Buf: Buf;
|
||||
|
||||
/// Creates a `Buf` from a value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, IntoBuf, BigEndian};
|
||||
///
|
||||
/// let bytes = b"\x00\x01hello world";
|
||||
/// let mut buf = bytes.into_buf();
|
||||
///
|
||||
/// assert_eq!(1, buf.get_u16::<BigEndian>());
|
||||
///
|
||||
/// let mut rest = [0; 11];
|
||||
/// buf.copy_to_slice(&mut rest);
|
||||
///
|
||||
/// assert_eq!(b"hello world", &rest);
|
||||
/// ```
|
||||
fn into_buf(self) -> Self::Buf;
|
||||
}
|
||||
|
||||
impl<T: Buf> IntoBuf for T {
|
||||
type Buf = Self;
|
||||
|
||||
fn into_buf(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoBuf for &'a [u8] {
|
||||
type Buf = io::Cursor<&'a [u8]>;
|
||||
|
||||
fn into_buf(self) -> Self::Buf {
|
||||
io::Cursor::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoBuf for &'a str {
|
||||
type Buf = io::Cursor<&'a [u8]>;
|
||||
|
||||
fn into_buf(self) -> Self::Buf {
|
||||
self.as_bytes().into_buf()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoBuf for Vec<u8> {
|
||||
type Buf = io::Cursor<Vec<u8>>;
|
||||
|
||||
fn into_buf(self) -> Self::Buf {
|
||||
io::Cursor::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoBuf for &'a Vec<u8> {
|
||||
type Buf = io::Cursor<&'a [u8]>;
|
||||
|
||||
fn into_buf(self) -> Self::Buf {
|
||||
io::Cursor::new(&self[..])
|
||||
}
|
||||
}
|
||||
|
||||
// Kind of annoying... but this impl is required to allow passing `&'static
|
||||
// [u8]` where for<'a> &'a T: IntoBuf is required.
|
||||
impl<'a> IntoBuf for &'a &'static [u8] {
|
||||
type Buf = io::Cursor<&'static [u8]>;
|
||||
|
||||
fn into_buf(self) -> Self::Buf {
|
||||
io::Cursor::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoBuf for &'a &'static str {
|
||||
type Buf = io::Cursor<&'static [u8]>;
|
||||
|
||||
fn into_buf(self) -> Self::Buf {
|
||||
self.as_bytes().into_buf()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoBuf for String {
|
||||
type Buf = io::Cursor<Vec<u8>>;
|
||||
|
||||
fn into_buf(self) -> Self::Buf {
|
||||
self.into_bytes().into_buf()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoBuf for &'a String {
|
||||
type Buf = io::Cursor<&'a [u8]>;
|
||||
|
||||
fn into_buf(self) -> Self::Buf {
|
||||
self.as_bytes().into_buf()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoBuf for u8 {
|
||||
type Buf = Option<[u8; 1]>;
|
||||
|
||||
fn into_buf(self) -> Self::Buf {
|
||||
Some([self])
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoBuf for i8 {
|
||||
type Buf = Option<[u8; 1]>;
|
||||
|
||||
fn into_buf(self) -> Self::Buf {
|
||||
Some([self as u8; 1])
|
||||
}
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
use Buf;
|
||||
|
||||
/// Iterator over the bytes contained by the buffer.
|
||||
///
|
||||
/// This struct is created by the [`iter`] method on [`Buf`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use bytes::{Buf, IntoBuf, Bytes};
|
||||
///
|
||||
/// let buf = Bytes::from(&b"abc"[..]).into_buf();
|
||||
/// let mut iter = buf.iter();
|
||||
///
|
||||
/// assert_eq!(iter.next(), Some(b'a'));
|
||||
/// assert_eq!(iter.next(), Some(b'b'));
|
||||
/// assert_eq!(iter.next(), Some(b'c'));
|
||||
/// assert_eq!(iter.next(), None);
|
||||
/// ```
|
||||
///
|
||||
/// [`iter`]: trait.Buf.html#method.iter
|
||||
/// [`Buf`]: trait.Buf.html
|
||||
#[derive(Debug)]
|
||||
pub struct Iter<T> {
|
||||
inner: T,
|
||||
}
|
||||
|
||||
impl<T> Iter<T> {
|
||||
/// Consumes this `Iter`, returning the underlying value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use bytes::{Buf, IntoBuf, Bytes};
|
||||
///
|
||||
/// let buf = Bytes::from(&b"abc"[..]).into_buf();
|
||||
/// let mut iter = buf.iter();
|
||||
///
|
||||
/// assert_eq!(iter.next(), Some(b'a'));
|
||||
///
|
||||
/// 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 bytes::{Buf, IntoBuf, Bytes};
|
||||
///
|
||||
/// let buf = Bytes::from(&b"abc"[..]).into_buf();
|
||||
/// let mut iter = buf.iter();
|
||||
///
|
||||
/// assert_eq!(iter.next(), Some(b'a'));
|
||||
///
|
||||
/// assert_eq!(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 bytes::{Buf, IntoBuf, BytesMut};
|
||||
///
|
||||
/// let buf = BytesMut::from(&b"abc"[..]).into_buf();
|
||||
/// let mut iter = buf.iter();
|
||||
///
|
||||
/// assert_eq!(iter.next(), Some(b'a'));
|
||||
///
|
||||
/// iter.get_mut().set_position(0);
|
||||
///
|
||||
/// assert_eq!(iter.next(), Some(b'a'));
|
||||
/// ```
|
||||
pub fn get_mut(&mut self) -> &mut T {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new<T>(inner: T) -> Iter<T> {
|
||||
Iter { inner: inner }
|
||||
}
|
||||
|
||||
impl<T: Buf> Iterator for Iter<T> {
|
||||
type Item = u8;
|
||||
|
||||
fn next(&mut self) -> Option<u8> {
|
||||
if !self.inner.has_remaining() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let b = self.inner.bytes()[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 Iter<T> { }
|
||||
@@ -0,0 +1,37 @@
|
||||
//! 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;
|
||||
mod buf_mut;
|
||||
mod from_buf;
|
||||
mod chain;
|
||||
mod into_buf;
|
||||
mod iter;
|
||||
mod reader;
|
||||
mod take;
|
||||
mod writer;
|
||||
|
||||
pub use self::buf::Buf;
|
||||
pub use self::buf_mut::BufMut;
|
||||
pub use self::from_buf::FromBuf;
|
||||
pub use self::chain::Chain;
|
||||
pub use self::into_buf::IntoBuf;
|
||||
pub use self::iter::Iter;
|
||||
pub use self::reader::Reader;
|
||||
pub use self::take::Take;
|
||||
pub use self::writer::Writer;
|
||||
@@ -0,0 +1,88 @@
|
||||
use {Buf};
|
||||
|
||||
use std::{cmp, io};
|
||||
|
||||
/// A `Buf` adapter which implements `io::Read` for the inner value.
|
||||
///
|
||||
/// This struct is generally created by calling `reader()` on `Buf`. See
|
||||
/// documentation of [`reader()`](trait.Buf.html#method.reader) for more
|
||||
/// details.
|
||||
#[derive(Debug)]
|
||||
pub struct Reader<B> {
|
||||
buf: B,
|
||||
}
|
||||
|
||||
pub fn new<B>(buf: B) -> Reader<B> {
|
||||
Reader { buf: buf }
|
||||
}
|
||||
|
||||
impl<B: Buf> Reader<B> {
|
||||
/// Gets a reference to the underlying `Buf`.
|
||||
///
|
||||
/// It is inadvisable to directly read from the underlying `Buf`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use bytes::Buf;
|
||||
/// use std::io::{self, Cursor};
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"hello world").reader();
|
||||
///
|
||||
/// assert_eq!(0, buf.get_ref().position());
|
||||
/// ```
|
||||
pub fn get_ref(&self) -> &B {
|
||||
&self.buf
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the underlying `Buf`.
|
||||
///
|
||||
/// It is inadvisable to directly read from the underlying `Buf`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use bytes::Buf;
|
||||
/// use std::io::{self, Cursor};
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"hello world").reader();
|
||||
/// let mut dst = vec![];
|
||||
///
|
||||
/// buf.get_mut().set_position(2);
|
||||
/// io::copy(&mut buf, &mut dst).unwrap();
|
||||
///
|
||||
/// assert_eq!(*dst, b"llo world"[..]);
|
||||
/// ```
|
||||
pub fn get_mut(&mut self) -> &mut B {
|
||||
&mut self.buf
|
||||
}
|
||||
|
||||
/// Consumes this `Reader`, returning the underlying value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use bytes::Buf;
|
||||
/// use std::io::{self, Cursor};
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"hello world").reader();
|
||||
/// let mut dst = vec![];
|
||||
///
|
||||
/// io::copy(&mut buf, &mut dst).unwrap();
|
||||
///
|
||||
/// let buf = buf.into_inner();
|
||||
/// assert_eq!(0, buf.remaining());
|
||||
/// ```
|
||||
pub fn into_inner(self) -> B {
|
||||
self.buf
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Buf + Sized> io::Read for Reader<B> {
|
||||
fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
|
||||
let len = cmp::min(self.buf.remaining(), dst.len());
|
||||
|
||||
Buf::copy_to_slice(&mut self.buf, &mut dst[0..len]);
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
use {Buf};
|
||||
|
||||
use std::cmp;
|
||||
|
||||
/// A `Buf` adapter which limits the bytes read from an underlying buffer.
|
||||
///
|
||||
/// This struct is generally created by calling `take()` on `Buf`. See
|
||||
/// documentation of [`take()`](trait.Buf.html#method.take) for more details.
|
||||
#[derive(Debug)]
|
||||
pub struct Take<T> {
|
||||
inner: T,
|
||||
limit: usize,
|
||||
}
|
||||
|
||||
pub fn new<T>(inner: T, limit: usize) -> Take<T> {
|
||||
Take {
|
||||
inner: inner,
|
||||
limit: limit,
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Take<T> {
|
||||
/// Consumes this `Take`, returning the underlying value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use bytes::{Buf, BufMut};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"hello world").take(2);
|
||||
/// let mut dst = vec![];
|
||||
///
|
||||
/// dst.put(&mut buf);
|
||||
/// assert_eq!(*dst, b"he"[..]);
|
||||
///
|
||||
/// let mut buf = buf.into_inner();
|
||||
///
|
||||
/// dst.clear();
|
||||
/// dst.put(&mut buf);
|
||||
/// assert_eq!(*dst, b"llo world"[..]);
|
||||
/// ```
|
||||
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 bytes::{Buf, BufMut};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"hello world").take(2);
|
||||
///
|
||||
/// assert_eq!(0, buf.get_ref().position());
|
||||
/// ```
|
||||
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 bytes::{Buf, BufMut};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"hello world").take(2);
|
||||
/// let mut dst = vec![];
|
||||
///
|
||||
/// buf.get_mut().set_position(2);
|
||||
///
|
||||
/// dst.put(&mut buf);
|
||||
/// assert_eq!(*dst, b"ll"[..]);
|
||||
/// ```
|
||||
pub fn get_mut(&mut self) -> &mut T {
|
||||
&mut self.inner
|
||||
}
|
||||
|
||||
/// Returns the maximum number of bytes that can be read.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// If the inner `Buf` has fewer bytes than indicated by this method then
|
||||
/// that is the actual number of available bytes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use bytes::Buf;
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"hello world").take(2);
|
||||
///
|
||||
/// assert_eq!(2, buf.limit());
|
||||
/// assert_eq!(b'h', buf.get_u8());
|
||||
/// assert_eq!(1, buf.limit());
|
||||
/// ```
|
||||
pub fn limit(&self) -> usize {
|
||||
self.limit
|
||||
}
|
||||
|
||||
/// Sets the maximum number of bytes that can be read.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// If the inner `Buf` has fewer bytes than `lim` then that is the actual
|
||||
/// number of available bytes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use bytes::{Buf, BufMut};
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buf = Cursor::new(b"hello world").take(2);
|
||||
/// let mut dst = vec![];
|
||||
///
|
||||
/// dst.put(&mut buf);
|
||||
/// assert_eq!(*dst, b"he"[..]);
|
||||
///
|
||||
/// dst.clear();
|
||||
///
|
||||
/// buf.set_limit(3);
|
||||
/// dst.put(&mut buf);
|
||||
/// assert_eq!(*dst, b"llo"[..]);
|
||||
/// ```
|
||||
pub fn set_limit(&mut self, lim: usize) {
|
||||
self.limit = lim
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Buf> Buf for Take<T> {
|
||||
fn remaining(&self) -> usize {
|
||||
cmp::min(self.inner.remaining(), self.limit)
|
||||
}
|
||||
|
||||
fn bytes(&self) -> &[u8] {
|
||||
&self.inner.bytes()[..self.limit]
|
||||
}
|
||||
|
||||
fn advance(&mut self, cnt: usize) {
|
||||
assert!(cnt <= self.limit);
|
||||
self.inner.advance(cnt);
|
||||
self.limit -= cnt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
use 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: 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 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 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 bytes::BufMut;
|
||||
/// use std::io::{self, Cursor};
|
||||
///
|
||||
/// let mut buf = vec![].writer();
|
||||
/// let mut src = Cursor::new(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(())
|
||||
}
|
||||
}
|
||||
+519
-150
File diff suppressed because it is too large
Load Diff
@@ -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<'a> fmt::Debug for BsDebug<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
try!(write!(fmt, "b\""));
|
||||
for &c in self.0 {
|
||||
// https://doc.rust-lang.org/reference.html#byte-escapes
|
||||
if c == b'\n' {
|
||||
try!(write!(fmt, "\\n"));
|
||||
} else if c == b'\r' {
|
||||
try!(write!(fmt, "\\r"));
|
||||
} else if c == b'\t' {
|
||||
try!(write!(fmt, "\\t"));
|
||||
} else if c == b'\\' || c == b'"' {
|
||||
try!(write!(fmt, "\\{}", c as char));
|
||||
} else if c == b'\0' {
|
||||
try!(write!(fmt, "\\0"));
|
||||
// ASCII printable except space
|
||||
} else if c > 0x20 && c < 0x7f {
|
||||
try!(write!(fmt, "{}", c as char));
|
||||
} else {
|
||||
try!(write!(fmt, "\\x{:02x}", c));
|
||||
}
|
||||
}
|
||||
try!(write!(fmt, "\""));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
+20
-8
@@ -29,12 +29,12 @@
|
||||
//! buf.put(&b"hello world"[..]);
|
||||
//! buf.put_u16::<BigEndian>(1234);
|
||||
//!
|
||||
//! let a = buf.drain();
|
||||
//! let a = buf.take();
|
||||
//! assert_eq!(a, b"hello world\x04\xD2"[..]);
|
||||
//!
|
||||
//! buf.put(&b"goodbye world"[..]);
|
||||
//!
|
||||
//! let b = buf.drain();
|
||||
//! let b = buf.take();
|
||||
//! assert_eq!(b, b"goodbye world"[..]);
|
||||
//!
|
||||
//! assert_eq!(buf.capacity(), 998);
|
||||
@@ -62,27 +62,39 @@
|
||||
//! ## Relation with `Read` and `Write`
|
||||
//!
|
||||
//! At first glance, it may seem that `Buf` and `BufMut` overlap in
|
||||
//! functionality with `std::io::Ready` and `std::io::Write`. However, they
|
||||
//! 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)]
|
||||
#![deny(warnings, missing_docs, missing_debug_implementations)]
|
||||
#![doc(html_root_url = "https://docs.rs/bytes/0.4")]
|
||||
|
||||
extern crate byteorder;
|
||||
extern crate iovec;
|
||||
|
||||
mod buf;
|
||||
mod bytes;
|
||||
|
||||
pub mod buf;
|
||||
pub use buf::{
|
||||
Buf,
|
||||
BufMut,
|
||||
IntoBuf,
|
||||
Source,
|
||||
};
|
||||
#[deprecated(since = "0.4.1", note = "moved to `buf` module")]
|
||||
#[doc(hidden)]
|
||||
pub use buf::{
|
||||
Reader,
|
||||
Writer,
|
||||
Take,
|
||||
};
|
||||
|
||||
mod bytes;
|
||||
mod debug;
|
||||
pub use bytes::{Bytes, BytesMut};
|
||||
|
||||
pub use byteorder::{ByteOrder, BigEndian, LittleEndian};
|
||||
|
||||
// Optional Serde support
|
||||
#[cfg(feature = "serde")]
|
||||
#[doc(hidden)]
|
||||
pub mod serde;
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
extern crate serde;
|
||||
|
||||
use std::{cmp, fmt};
|
||||
use self::serde::{Serialize, Serializer, Deserialize, Deserializer, de};
|
||||
use super::{Bytes, BytesMut};
|
||||
|
||||
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) = try!(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);
|
||||
+10
-5
@@ -1,7 +1,9 @@
|
||||
extern crate bytes;
|
||||
extern crate byteorder;
|
||||
extern crate iovec;
|
||||
|
||||
use bytes::Buf;
|
||||
use iovec::IoVec;
|
||||
use std::io::Cursor;
|
||||
|
||||
#[test]
|
||||
@@ -20,11 +22,6 @@ fn test_fresh_cursor_vec() {
|
||||
|
||||
assert_eq!(buf.remaining(), 0);
|
||||
assert_eq!(buf.bytes(), b"");
|
||||
|
||||
buf.advance(1);
|
||||
|
||||
assert_eq!(buf.remaining(), 0);
|
||||
assert_eq!(buf.bytes(), b"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -46,3 +43,11 @@ fn test_get_u16_buffer_underflow() {
|
||||
let mut buf = Cursor::new(b"\x21");
|
||||
buf.get_u16::<byteorder::BigEndian>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bufs_vec() {
|
||||
let buf = Cursor::new(b"hello world");
|
||||
let mut dst: [&IoVec; 2] = Default::default();
|
||||
|
||||
assert_eq!(1, buf.bytes_vec(&mut dst[..]));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
extern crate bytes;
|
||||
extern crate byteorder;
|
||||
extern crate iovec;
|
||||
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use iovec::IoVec;
|
||||
use std::usize;
|
||||
use std::fmt::Write;
|
||||
|
||||
@@ -47,6 +49,17 @@ fn test_put_u16() {
|
||||
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);
|
||||
@@ -56,3 +69,15 @@ fn test_clone() {
|
||||
buf.write_str(" of our emergecy broadcast system").unwrap();
|
||||
assert!(buf != buf2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bufs_vec_mut() {
|
||||
use std::mem;
|
||||
|
||||
let mut buf = BytesMut::from(&b"hello world"[..]);
|
||||
|
||||
unsafe {
|
||||
let mut dst: [&mut IoVec; 2] = mem::zeroed();
|
||||
assert_eq!(1, buf.bytes_vec_mut(&mut dst[..]));
|
||||
}
|
||||
}
|
||||
+207
-19
@@ -43,7 +43,7 @@ fn from_slice() {
|
||||
#[test]
|
||||
fn fmt() {
|
||||
let a = format!("{:?}", Bytes::from(&b"abcdefg"[..]));
|
||||
let b = format!("{:?}", b"abcdefg");
|
||||
let b = "b\"abcdefg\"";
|
||||
|
||||
assert_eq!(a, b);
|
||||
|
||||
@@ -79,6 +79,15 @@ fn slice() {
|
||||
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_to(5);
|
||||
assert_eq!(b, b"hello"[..]);
|
||||
|
||||
@@ -135,34 +144,78 @@ fn split_off_uninitialized() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drain_to_1() {
|
||||
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);
|
||||
sum.extend(&off);
|
||||
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);
|
||||
sum.extend(&bytes);
|
||||
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.drain_to(4);
|
||||
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.drain_to(4);
|
||||
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.drain_to(30);
|
||||
let b = a.split_to(30);
|
||||
|
||||
assert_eq!(LONG[30..], a);
|
||||
assert_eq!(LONG[..30], b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drain_to_2() {
|
||||
fn split_to_2() {
|
||||
let mut a = Bytes::from(LONG);
|
||||
assert_eq!(LONG, a);
|
||||
|
||||
let b = a.drain_to(1);
|
||||
let b = a.split_to(1);
|
||||
|
||||
assert_eq!(LONG[1..], a);
|
||||
drop(b);
|
||||
@@ -170,22 +223,22 @@ fn drain_to_2() {
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn drain_to_oob() {
|
||||
fn split_to_oob() {
|
||||
let mut hello = Bytes::from(&b"helloworld"[..]);
|
||||
hello.drain_to(inline_cap() + 1);
|
||||
hello.split_to(inline_cap() + 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn drain_to_oob_mut() {
|
||||
fn split_to_oob_mut() {
|
||||
let mut hello = BytesMut::from(&b"helloworld"[..]);
|
||||
hello.drain_to(inline_cap() + 1);
|
||||
hello.split_to(inline_cap() + 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drain_to_uninitialized() {
|
||||
fn split_to_uninitialized() {
|
||||
let mut bytes = BytesMut::with_capacity(1024);
|
||||
let other = bytes.drain_to(128);
|
||||
let other = bytes.split_to(128);
|
||||
|
||||
assert_eq!(bytes.len(), 0);
|
||||
assert_eq!(bytes.capacity(), 896);
|
||||
@@ -194,6 +247,28 @@ fn drain_to_uninitialized() {
|
||||
assert_eq!(other.capacity(), 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"[..]);
|
||||
@@ -219,7 +294,7 @@ fn reserve_convert() {
|
||||
let mut bytes = BytesMut::with_capacity(inline_cap());
|
||||
bytes.put("abcdefghijkl");
|
||||
|
||||
let a = bytes.drain_to(10);
|
||||
let a = bytes.split_to(10);
|
||||
bytes.reserve(inline_cap() - 3);
|
||||
assert_eq!(inline_cap(), bytes.capacity());
|
||||
|
||||
@@ -233,10 +308,10 @@ fn reserve_convert() {
|
||||
|
||||
// Arc -> Vec
|
||||
let mut bytes = BytesMut::from(LONG);
|
||||
let a = bytes.drain_to(30);
|
||||
let a = bytes.split_to(30);
|
||||
|
||||
bytes.reserve(128);
|
||||
assert_eq!(bytes.capacity(), (bytes.len() + 128).next_power_of_two());
|
||||
assert!(bytes.capacity() >= bytes.len() + 128);
|
||||
|
||||
drop(a);
|
||||
}
|
||||
@@ -245,12 +320,78 @@ fn reserve_convert() {
|
||||
fn reserve_growth() {
|
||||
let mut bytes = BytesMut::with_capacity(64);
|
||||
bytes.put("hello world");
|
||||
let _ = bytes.drain();
|
||||
let _ = bytes.take();
|
||||
|
||||
bytes.reserve(65);
|
||||
assert_eq!(bytes.capacity(), 128);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reserve_allocates_at_least_original_capacity() {
|
||||
let mut bytes = BytesMut::with_capacity(128);
|
||||
|
||||
for i in 0..120 {
|
||||
bytes.put(i as u8);
|
||||
}
|
||||
|
||||
let _other = bytes.take();
|
||||
|
||||
bytes.reserve(16);
|
||||
assert_eq!(bytes.capacity(), 128);
|
||||
}
|
||||
|
||||
#[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(0u8);
|
||||
}
|
||||
|
||||
let _other = bytes.take();
|
||||
|
||||
bytes.reserve(16);
|
||||
assert_eq!(bytes.capacity(), 64 * 1024);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reserve_in_arc_unique_does_not_overallocate() {
|
||||
let mut bytes = BytesMut::with_capacity(1000);
|
||||
bytes.take();
|
||||
|
||||
// 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.take();
|
||||
|
||||
// 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.take();
|
||||
|
||||
// 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());
|
||||
@@ -261,6 +402,52 @@ fn inline_storage() {
|
||||
}
|
||||
|
||||
#[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]
|
||||
// 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};
|
||||
@@ -271,7 +458,7 @@ fn stress() {
|
||||
|
||||
for i in 0..ITERS {
|
||||
let data = [i as u8; 256];
|
||||
let buf = Arc::new(BytesMut::from(&data[..]));
|
||||
let buf = Arc::new(Bytes::from(&data[..]));
|
||||
|
||||
let barrier = Arc::new(Barrier::new(THREADS));
|
||||
let mut joins = Vec::with_capacity(THREADS);
|
||||
@@ -282,7 +469,8 @@ fn stress() {
|
||||
|
||||
joins.push(thread::spawn(move || {
|
||||
c.wait();
|
||||
let _buf = buf.clone();
|
||||
let buf: Bytes = (*buf).clone();
|
||||
drop(buf);
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
extern crate bytes;
|
||||
extern crate iovec;
|
||||
|
||||
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
||||
use bytes::buf::Chain;
|
||||
use iovec::IoVec;
|
||||
use std::io::Cursor;
|
||||
|
||||
#[test]
|
||||
fn collect_two_bufs() {
|
||||
let a = Cursor::new(Bytes::from(&b"hello"[..]));
|
||||
let b = Cursor::new(Bytes::from(&b"world"[..]));
|
||||
|
||||
let res: Vec<u8> = a.chain(b).collect();
|
||||
assert_eq!(res, &b"helloworld"[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn writing_chained() {
|
||||
let mut a = BytesMut::with_capacity(64);
|
||||
let mut b = BytesMut::with_capacity(64);
|
||||
|
||||
{
|
||||
let mut buf = Chain::new(&mut a, &mut b);
|
||||
|
||||
for i in 0..128 {
|
||||
buf.put(i as u8);
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(64, a.len());
|
||||
assert_eq!(64, b.len());
|
||||
|
||||
for i in 0..64 {
|
||||
let expect = i as u8;
|
||||
assert_eq!(expect, a[i]);
|
||||
assert_eq!(expect + 64, b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterating_two_bufs() {
|
||||
let a = Cursor::new(Bytes::from(&b"hello"[..]));
|
||||
let b = Cursor::new(Bytes::from(&b"world"[..]));
|
||||
|
||||
let res: Vec<u8> = a.chain(b).iter().collect();
|
||||
assert_eq!(res, &b"helloworld"[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vectored_read() {
|
||||
let a = Cursor::new(Bytes::from(&b"hello"[..]));
|
||||
let b = Cursor::new(Bytes::from(&b"world"[..]));
|
||||
|
||||
let mut buf = a.chain(b);
|
||||
|
||||
{
|
||||
let mut iovecs: [&IoVec; 4] = Default::default();
|
||||
|
||||
assert_eq!(2, buf.bytes_vec(&mut iovecs));
|
||||
assert_eq!(iovecs[0][..], b"hello"[..]);
|
||||
assert_eq!(iovecs[1][..], b"world"[..]);
|
||||
assert!(iovecs[2].is_empty());
|
||||
assert!(iovecs[3].is_empty());
|
||||
}
|
||||
|
||||
buf.advance(2);
|
||||
|
||||
{
|
||||
let mut iovecs: [&IoVec; 4] = Default::default();
|
||||
|
||||
assert_eq!(2, buf.bytes_vec(&mut iovecs));
|
||||
assert_eq!(iovecs[0][..], b"llo"[..]);
|
||||
assert_eq!(iovecs[1][..], b"world"[..]);
|
||||
assert!(iovecs[2].is_empty());
|
||||
assert!(iovecs[3].is_empty());
|
||||
}
|
||||
|
||||
buf.advance(3);
|
||||
|
||||
{
|
||||
let mut iovecs: [&IoVec; 4] = Default::default();
|
||||
|
||||
assert_eq!(1, buf.bytes_vec(&mut iovecs));
|
||||
assert_eq!(iovecs[0][..], b"world"[..]);
|
||||
assert!(iovecs[1].is_empty());
|
||||
assert!(iovecs[2].is_empty());
|
||||
assert!(iovecs[3].is_empty());
|
||||
}
|
||||
|
||||
buf.advance(3);
|
||||
|
||||
{
|
||||
let mut iovecs: [&IoVec; 4] = Default::default();
|
||||
|
||||
assert_eq!(1, buf.bytes_vec(&mut iovecs));
|
||||
assert_eq!(iovecs[0][..], b"ld"[..]);
|
||||
assert!(iovecs[1].is_empty());
|
||||
assert!(iovecs[2].is_empty());
|
||||
assert!(iovecs[3].is_empty());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
extern crate bytes;
|
||||
|
||||
use 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)));
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
extern crate bytes;
|
||||
|
||||
use bytes::{Buf, Bytes, BytesMut};
|
||||
use std::io::Cursor;
|
||||
|
||||
const LONG: &'static [u8] = b"mary had a little lamb, little lamb, little lamb";
|
||||
const SHORT: &'static [u8] = b"hello world";
|
||||
|
||||
#[test]
|
||||
fn collect_to_vec() {
|
||||
let buf: Vec<u8> = Cursor::new(SHORT).collect();
|
||||
assert_eq!(buf, SHORT);
|
||||
|
||||
let buf: Vec<u8> = Cursor::new(LONG).collect();
|
||||
assert_eq!(buf, LONG);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collect_to_bytes() {
|
||||
let buf: Bytes = Cursor::new(SHORT).collect();
|
||||
assert_eq!(buf, SHORT);
|
||||
|
||||
let buf: Bytes = Cursor::new(LONG).collect();
|
||||
assert_eq!(buf, LONG);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collect_to_bytes_mut() {
|
||||
let buf: BytesMut = Cursor::new(SHORT).collect();
|
||||
assert_eq!(buf, SHORT);
|
||||
|
||||
let buf: BytesMut = Cursor::new(LONG).collect();
|
||||
assert_eq!(buf, LONG);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
extern crate bytes;
|
||||
|
||||
use bytes::{Buf, IntoBuf, Bytes};
|
||||
|
||||
#[test]
|
||||
fn iter_len() {
|
||||
let buf = Bytes::from(&b"hello world"[..]).into_buf();
|
||||
let iter = buf.iter();
|
||||
|
||||
assert_eq!(iter.size_hint(), (11, Some(11)));
|
||||
assert_eq!(iter.len(), 11);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn empty_iter_len() {
|
||||
let buf = Bytes::from(&b""[..]).into_buf();
|
||||
let iter = buf.iter();
|
||||
|
||||
assert_eq!(iter.size_hint(), (0, Some(0)));
|
||||
assert_eq!(iter.len(), 0);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#![cfg(feature = "serde")]
|
||||
|
||||
extern crate bytes;
|
||||
extern crate serde_test;
|
||||
use serde_test::{Token, assert_tokens};
|
||||
|
||||
#[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")]);
|
||||
}
|
||||
Reference in New Issue
Block a user