Compare commits

...
62 Commits
Author SHA1 Message Date
Carl LercheandGitHub 406b048ae6 Bump version to v0.4.8 (#206) 2018-05-25 16:50:42 -07:00
Carl Lerche 8c041142a0 Filter out tsan warnings in test harness (#205) 2018-05-25 15:54:13 -07:00
Luke HorsleyandCarl Lerche e9a7098658 Added a resize function for BytesMut (#203) 2018-05-25 13:54:32 -07:00
Carl LercheandGitHub 32ea8281b3 Use sanitizers in CI (#204) 2018-05-25 12:40:37 -07:00
Noah ZentzisandCarl Lerche dfce95b89d Recycle space when reserving from Vec-backed Bytes (#197)
* Recycle space when reserving from Vec-backed Bytes

BytesMut::reserve, when called on a BytesMut instance which is backed by
a non-shared Vec<u8>, would previously just delegate to Vec::reserve
regardless of the current location in the buffer. If the Bytes is
actually the trailing component of a larger Vec, then the unused space
won't be recycled. In applications which continually move the pointer
forward to consume data as it comes in, this can cause the underlying
buffer to get extremely large.

This commit checks whether there's extra space at the start of the
backing Vec in this case, and reuses the unused space if possible
instead of allocating.

* Avoid excessive copying when reusing Vec space

Only reuse space in a Vec-backed Bytes when doing so would gain back
more than half of the current capacity. This avoids excessive copy
operations when a large buffer is almost (but not completely) full.
2018-05-24 16:37:13 -07:00
Carl Lerche b68fa46e3d Fix panic in FromIterator for BytesMut 2018-05-11 08:45:04 -07:00
Carl Lerche ef09e98fbc Bump version to v0.4.7 2018-04-27 10:51:09 -07:00
kohensuandCarl Lerche 51e435b7e0 Improve performance of Buf::get_*() (#195)
The new implementation tries to get the data directly from bytes() (this is
possible most of the time) and if there is not enough data in bytes() use the
previous code: copy the needed bytes in a temporary buffer before returning
the data

Here the bench results:
                               Before                After           x-faster
get_f32::cursor             64 ns/iter (+/- 0)    20 ns/iter (+/- 0)    3.2
get_f32::tbuf_1             77 ns/iter (+/- 1)    34 ns/iter (+/- 0)    2.3
get_f32::tbuf_1_costly      87 ns/iter (+/- 0)    62 ns/iter (+/- 0)    1.4
get_f32::tbuf_2            151 ns/iter (+/- 18)  160 ns/iter (+/- 1)    0.9
get_f32::tbuf_2_costly     180 ns/iter (+/- 2)   187 ns/iter (+/- 2)    1.0

get_f64::cursor             67 ns/iter (+/- 0)    21 ns/iter (+/- 0)    3.2
get_f64::tbuf_1             80 ns/iter (+/- 0)    35 ns/iter (+/- 0)    2.3
get_f64::tbuf_1_costly      82 ns/iter (+/- 3)    60 ns/iter (+/- 0)    1.4
get_f64::tbuf_2            154 ns/iter (+/- 1)   164 ns/iter (+/- 0)    0.9
get_f64::tbuf_2_costly     170 ns/iter (+/- 2)   187 ns/iter (+/- 1)    0.9

get_u16::cursor             66 ns/iter (+/- 0)    20 ns/iter (+/- 0)    3.3
get_u16::tbuf_1             77 ns/iter (+/- 0)    35 ns/iter (+/- 0)    2.2
get_u16::tbuf_1_costly      85 ns/iter (+/- 2)    62 ns/iter (+/- 0)    1.4
get_u16::tbuf_2            147 ns/iter (+/- 0)   154 ns/iter (+/- 0)    1.0
get_u16::tbuf_2_costly     160 ns/iter (+/- 1)   177 ns/iter (+/- 0)    0.9

get_u32::cursor             64 ns/iter (+/- 0)    20 ns/iter (+/- 0)    3.2
get_u32::tbuf_1             77 ns/iter (+/- 0)    35 ns/iter (+/- 0)    2.2
get_u32::tbuf_1_costly      91 ns/iter (+/- 2)    63 ns/iter (+/- 0)    1.4
get_u32::tbuf_2            151 ns/iter (+/- 40)  157 ns/iter (+/- 0)    1.0
get_u32::tbuf_2_costly     162 ns/iter (+/- 0)   180 ns/iter (+/- 0)    0.9

get_u64::cursor             67 ns/iter (+/- 0)    20 ns/iter (+/- 0)    3.4
get_u64::tbuf_1             78 ns/iter (+/- 0)    35 ns/iter (+/- 1)    2.2
get_u64::tbuf_1_costly      87 ns/iter (+/- 1)    59 ns/iter (+/- 1)    1.5
get_u64::tbuf_2            154 ns/iter (+/- 0)   160 ns/iter (+/- 0)    1.0
get_u64::tbuf_2_costly     168 ns/iter (+/- 0)   184 ns/iter (+/- 0)    0.9

get_u8::cursor              64 ns/iter (+/- 0)    19 ns/iter (+/- 0)    3.4
get_u8::tbuf_1              77 ns/iter (+/- 0)    35 ns/iter (+/- 0)    2.2
get_u8::tbuf_1_costly       68 ns/iter (+/- 0)    51 ns/iter (+/- 0)    1.3
get_u8::tbuf_2              85 ns/iter (+/- 0)    43 ns/iter (+/- 0)    2.0
get_u8::tbuf_2_costly       75 ns/iter (+/- 0)    61 ns/iter (+/- 0)    1.2
get_u8::option              77 ns/iter (+/- 0)    59 ns/iter (+/- 0)    1.3

Improvement on the basic std::Cursor implementation are clearly visible.

Other implementations are specific to the bench tests and just map a static
slice. Different variant are:
 - tbuf_1: only one call of 'bytes()' is needed.
 - tbuf_2: two calls of 'bytes()' is needed to read more than one byte.
 - _costly version are implemented with #[inline(never)] on 'bytes()',
   'remaining()' and 'advance()'.

The cases that are slower (slightly) correspond to implementations that are not
really realistic: more than one byte is never possible in one time
2018-04-27 10:18:52 -07:00
Alan SomersandCarl Lerche 15050b1da5 impl BorrowMut for BytesMut (#185) (#192) 2018-04-27 10:08:50 -07:00
Sean McArthurandCarl Lerche ce79f0a268 Make Buf and BufMut usable as trait objects (#186)
- All the `get_*` and `put_*` methods that take `T: ByteOrder` have
  a `where Self: Sized` bound added, so that they are only usable from
  sized types. It was impossible to make `Buf` or `BufMut` into trait
  objects before, so this change doesn't break anyone.
- Add `get_n_be`/`get_n_le`/`put_n_be`/`put_n_le` methods that can be
  used on trait objects.
- Deprecate the export of `ByteOrder` and methods generic on it.

Fixes #163
2018-03-12 09:25:59 -07:00
Carl LercheandGitHub 86c83959dc Have Travis build WASM target (#180) 2018-01-29 10:18:52 -08:00
Carl Lerche e5c4c6028d Bump version to v0.4.6 2018-01-08 09:11:42 -08:00
jq-rsandCarl Lerche ba9a975358 Unsplit improvements (#173)
* Handle empty self and other for unsplit.
* Change extend() to extend_from_slice().
2018-01-05 16:20:59 -08:00
Stepan KoltsovandCarl Lerche 6a3d20bb8d Optimize shallow_clone for Bytes::split_{off,to} (#92)
If `shallow_clone` is called with `&mut self`, and `Bytes` contains
`Vec`, then expensive CAS can be avoided, because no other thread
have references to this `Bytes` object.

Bench `split_off_and_drop` difference:

Before the diff:

```
test split_off_and_drop             ... bench:      91,858 ns/iter (+/- 17,401)
```

With the diff:

```
test split_off_and_drop             ... bench:      81,162 ns/iter (+/- 17,603)
```
2018-01-03 11:41:33 -08:00
jq-rsandCarl Lerche 2ca61d881d Add support for unsplit() to BytesMut (#162)
Add support for unsplit() to BytesMut which combines splitted contiguous memory blocks efficiently.
2018-01-03 09:54:51 -08:00
Carl LercheandGitHub 8d6c2b61cc Document correct inline capacity in bytes.rs (#171)
Fixes #164
2017-12-15 18:10:30 -06:00
Carl LercheandGitHub 02891144be Add advance on Bytes and BytesMut (#166)
* Compact Bytes original capacity representation

In order to avoid unnecessary allocations, a `Bytes` structure remembers
the capacity with which it was first created. When a reserve operation
is issued, this original capacity value is used to as a baseline for
reallocating new storage.

Previously, this original capacity value was stored in its raw form. In
other words, the original capacity `usize` was stored as is. In order to
reclaim some `Bytes` internal storage space for additional features,
this original capacity value is compressed from requiring 16 bits to 3.

To do this, instead of storing the exact original capacity. The original
capacity is rounded down to the nearest power of two. If the original
capacity is less than 1024, then it is rounded down to zero. This
roughly means that the original capacity is now stored as a table:

0 => 0
1 => 1k
2 => 2k
3 => 4k
4 => 8k
5 => 16k
6 => 32k
7 => 64k

For the purposes that the original capacity feature was introduced, this
is sufficient granularity.

* Provide `advance` on Bytes and BytesMut

This is the `advance` function that would be part of a `Buf`
implementation. However, `Bytes` and `BytesMut` cannot impl `Buf` until
the next breaking release.

The implementation uses the additional storage made available by the
previous commit to store the number of bytes that the view was advanced.
The `ptr` pointer will point to the start of the window, avoiding any
pointer arithmetic when dereferencing the `Bytes` handle.
2017-12-13 13:30:03 -06:00
Carl Lerche 149922d7cf Get test passing again 2017-10-21 15:47:45 -07:00
Dan BurkertandCarl Lerche 03d501b18d small fixups in bytes.rs (#145)
* Inner: make uninitialized construction explicit
* Remove Inner2
* Remove unnecessary transmutes
* Use AtomicPtr::get_mut where possible
* Some minor tweaks
2017-08-18 08:33:28 -07:00
JefandCarl Lerche 34540be54c Add FromIterator impl (#148) 2017-08-17 10:32:59 -07:00
Sean McArthurandCarl Lerche cfca1c04fa print space normally in Debug for Bytes (#155) 2017-08-17 10:28:06 -07:00
Carl Lerche c8c46d8513 Bump version to v0.4.5 2017-08-12 10:59:31 -07:00
Alex CrichtonandCarl Lerche 7839100389 Inline as_ref functions on Bytes and BytesMut (#154) 2017-08-05 21:12:26 -07:00
Paul CollierandCarl Lerche 6750a26fd0 impl AsMut<[u8]> for BytesMut (#143) (#144) 2017-07-02 14:21:30 -07:00
Stepan KoltsovandCarl Lerche b9ccd2a866 Optimize Bytes::slice for short slices (#136)
Slice operation should return inline when possible

It is cheaper than atomic increment/decrement.

Before this patch:

```
test slice_avg_le_inline_from_arc   ... bench:      28,582 ns/iter (+/- 3,880)
test slice_empty                    ... bench:       8,797 ns/iter (+/- 1,325)
test slice_large_le_inline_from_arc ... bench:      27,684 ns/iter (+/- 5,920)
test slice_short_from_arc           ... bench:      27,439 ns/iter (+/- 5,783)
```

After this patch:

```
test slice_avg_le_inline_from_arc   ... bench:      18,872 ns/iter (+/- 2,937)
test slice_empty                    ... bench:       9,136 ns/iter (+/- 1,908)
test slice_large_le_inline_from_arc ... bench:      18,052 ns/iter (+/- 2,981)
test slice_short_from_arc           ... bench:      18,200 ns/iter (+/- 2,534)
```
2017-07-01 14:10:09 -07:00
Georg BrandlandCarl Lerche 544997958f Minor doc spelling and consistency fixes (#142) 2017-07-01 14:03:23 -07:00
Stepan KoltsovandCarl Lerche d315d00a3b Bytes::with_capacity (#137) 2017-06-30 20:33:35 -07:00
Clint ByrumandCarl Lerche fb2d8cf1c0 Add convenience PartialEq for BytesMut and Bytes (#141)
Saves the cognitive load of having to wrap them in slices to compare
them when that seems like what one would expect.

Signed-off-by: Clint Byrum <[email protected]>
2017-06-30 20:33:01 -07:00
Dan BurkertandCarl Lerche 7ed78cef47 Fix index-oob panic in Take::bytes (#138)
The panic happens when `inner.bytes()` returns a slice smaller than the
limit.
2017-06-27 11:23:29 -07:00
Igor GnatenkoandCarl Lerche aab71ef82c reference Apache-2.0 in Cargo.toml (#134) 2017-06-26 10:33:17 -07:00
Sean McArthurandCarl Lerche 7e8373da8d Faster From<[u8]> for BytesMut, remove panic in fmt::Write (#133)
* use slice.to_vec instead of buf.put in From<[u8]>

* don't panic in fmt::Write for BytesMut
2017-06-15 10:55:02 -07:00
Carl Lerche 3240fb9cd9 Bump version to v0.4.4 2017-05-26 10:09:43 -07:00
Stepan KoltsovandCarl Lerche 9ae51c9f0c Implement truncate, clear for Bytes (#128) 2017-05-26 09:29:31 -07:00
brianwpandCarl Lerche 2b0602e756 impl ExactSizeIterator for Iter<T: Buf> (#127) 2017-05-24 08:13:19 -07:00
Stepan KoltsovandCarl Lerche 3f5890be70 Optimize Bytes::slice(n, n) (#123)
Return empty `Bytes` object

Bench for `slice_empty` difference is

```
55 ns/iter (+/- 1) # before this patch
17 ns/iter (+/- 5) # with this patch
```

Bench for `slice_not_empty` is

```
25,058 ns/iter (+/- 1,099) # before this patch
25,072 ns/iter (+/- 1,593) # with this patch
```
2017-05-22 13:15:08 -07:00
Carl Lerche 70ee87ea29 Fix benchmarks 2017-05-22 12:02:51 -07:00
Stepan KoltsovandCarl Lerche edf1af958a Minor doc fixes (#124) 2017-05-22 11:30:34 -07:00
Stepan KoltsovandCarl Lerche 7110d57b2f BytesMut::reserve should not overallocate (#117)
Round up to power of 2 is not necessary, because `reserve` already
doubles previous capacity in

```
	new_cap = cmp::max(
		cmp::max(v.capacity() << 1, new_cap),
		original_capacity);
```

which makes `reserve` calls constant in average. Avoiding rounding
up prevents `reserve` from wasting space when caller knows exactly
what space they need.

Patch adds three tests which would fail before this test. The most
important is this:

```
#[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());
}
```

It asserts that when user requests more than double of current
capacity, exactly the requested amount of memory is allocated and
is not wasted to next power of two.
2017-05-15 11:28:12 -07:00
Stepan KoltsovandCarl Lerche 07db74b009 Bytes::extend_from_slice (#120)
`extend_with_slice` is super-convenient operation on `Bytes`.

While `put_u8` would be expensive on `Bytes`, `extend_from_slice`
is OK, because it is batch, and it checks for kind only once.

Patch also adds `impl Extend for Bytes`.

cc #116
2017-05-15 11:27:45 -07:00
Jack O'ConnorandCarl Lerche 6af66c4f21 fix a docs typo (#115) 2017-05-02 12:35:06 -07:00
Stepan KoltsovandCarl Lerche fa44c7e355 BytesMut::extend_from_slice shortcut (#112)
Similar to `Vec::extend_from_slice`: it a reserve followed by
memcopy.
2017-05-02 11:28:12 -07:00
Stepan KoltsovandCarl Lerche 2c0cb1b6b8 BytesMut::new constructor (#114) 2017-05-02 11:23:20 -07:00
Arthur SilvaandCarl Lerche b196559818 Add serde support behind serde feature (#96) 2017-05-02 10:51:52 -07:00
Sean McArthurandCarl Lerche 37f6cabd96 implement Default for Bytes and BytesMut (#110) 2017-05-01 12:53:27 -07:00
Carl Lerche e5c7ef3b86 Bump version to v0.4.3 2017-04-30 16:25:54 -07:00
Dan BurkertandCarl Lerche 30bd7c1f21 Vec::advance_mut can advance past the end of the buffer (#108) 2017-04-30 16:14:54 -07:00
Arthur SilvaandCarl Lerche 923d927bd1 Bump minimum rust version to 1.15 (#107) 2017-04-26 11:35:10 -07:00
Phil RuffwindandCarl Lerche 0b4185c716 Fix typos in src/bytes.rs (#106) 2017-04-24 12:47:24 -07:00
jaystrictorandCarl Lerche e158160418 Remove calls to deprecated drain* methods from docs (#102) 2017-04-14 09:06:58 -07:00
Sean McArthurandCarl Lerche 4645f6ec4b implement put_u8 for BytesMut (#101) 2017-04-06 08:59:13 -07:00
Carl Lerche 1a6901cdcd Bump version to v0.4.2 2017-04-05 12:12:05 -07:00
Carl LercheandGitHub 9aa24ebea1 Bytes: only the vec repr is not shared (#100)
The shared debug_assert is to ensure that the internal Bytes
representation is such that offset views are supported. The only
representation that does not support offset views is vec.

Fixes #97
2017-03-30 14:49:30 -07:00
Stepan KoltsovandCarl Lerche 627864187c Bytes::split_{off,to} should panic if at > len (#91) 2017-03-28 12:38:48 -07:00
Stepan KoltsovandCarl Lerche b78bb3baaa Handle corner cases of Bytes::split_{off,to} (#87)
Before this commit `Bytes::split_{off,to}` always created a shallow copy if `self` is arc or vec.

However, in certain cases `split_off` or `split_to` is called with `len` or `0` parameter. E. g. if you are reading a frame from buffered stream, it is likely that buffer contains exactly the frame size bytes, so `split_to` will be called with `len` param.

Although, `split_off` and `split_to` functions are `O(1)`, shallow copy have downsides:

* shallow copy on vector does malloc and atomic cmpxchg
* after shallow copy, following operations (e. g. `drop`) on both `bytes` objects require atomics
* memory will be probably released to the system later
* `try_mut` will fail
* [into_vec](https://github.com/carllerche/bytes/issues/86) will copy
2017-03-27 20:45:22 -07:00
Alex CrichtonandCarl Lerche 6c6c55d8e1 Flag Deref methods as #[inline] (#93) 2017-03-24 07:39:57 -07:00
Stepan KoltsovandCarl Lerche 613d4bd5d5 Reimplement fmt::Debug for Bytes and BytesMut (#84)
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.
2017-03-20 21:09:44 -07:00
Carl LercheandGitHub dc9c8e304e Misc CI fixes (#89)
Limit the number of threads when using qemu to 1. Also, don't bother
running the stress test as this will trigger qemu bugs. Finally, also
make the stress test actually stress test.
2017-03-20 10:12:23 -07:00
Carl Lerche bed128b2c0 Clarify when BufMut::bytes_mut can return &[]
Closes #79
2017-03-19 13:58:44 -07:00
Dan BurkertandCarl Lerche 5a265cc8eb Add inline attributes to Vec's MutBuf methods (#80)
I found this significantly improved a
[benchmark](https://gist.github.com/danburkert/34a7d6680d97bc86dca7f396eb8d0abf)
which calls `bytes_mut`, writes 1 byte, and advances the pointer with
`advance_mut` in a pretty tight loop. In particular, it seems to be the
inline annotation on `bytes_mut` which had the most effect. I also took
the opportunity to simplify the bounds checking in advance_mut.

before:

```
test encode_varint_small  ... bench:         540 ns/iter (+/- 85) = 1481 MB/s
```

after:

```
test encode_varint_small  ... bench:         422 ns/iter (+/- 24) = 1895 MB/s
```

As you can see, the variance is also significantly improved.

Interestingly, I tried to change the last statement in `bytes_mut` from

```
&mut slice::from_raw_parts_mut(ptr, cap)[len..]
```

to

```
slice::from_raw_parts_mut(ptr.offset(len as isize), cap - len)
```

but, this caused a very measurable perf regression (almost completely
negating the gains from marking bytes_mut inline).
2017-03-19 13:54:09 -07:00
Dan BurkertandCarl Lerche 4fe4e9429a Clarify BufMut::advance_mut docs (#78)
Also fixes an issue with a line wrap in the middle of an inline code
block.
2017-03-19 13:53:33 -07:00
Carl Lerche 9a4018e757 Fix tests on nightly
Closes #83
2017-03-19 09:08:41 -07:00
Carl LercheandGitHub 99fba239db Tweak docs (#76) 2017-03-16 12:11:10 -07:00
24 changed files with 2751 additions and 795 deletions
+31 -3
View File
@@ -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,36 @@ 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"
# WASM support
- rust: beta
script:
- rustup target add wasm32-unknown-unknown
- cargo build --target=wasm32-unknown-unknown
# Sanitizers
- rust: nightly
os: linux
script:
- |
set -e
export RUST_TEST_THREADS=1
export ASAN_OPTIONS="detect_odr_violation=0 detect_leaks=0"
export TSAN_OPTIONS="suppressions=`pwd`/ci/tsan"
# Run address sanitizer
RUSTFLAGS="-Z sanitizer=address" \
cargo test --tests --target x86_64-unknown-linux-gnu
# Run thread sanitizer
RUSTFLAGS="-Z sanitizer=thread" \
cargo test --tests --target x86_64-unknown-linux-gnu
before_install: set -e
+46
View File
@@ -1,3 +1,49 @@
# 0.4.8 (May 25, 2018)
* Fix panic in `BytesMut` `FromIterator` implementation.
* Bytes: Recycle space when reserving space in vec mode (#197).
* Bytes: Add resize fn (#203).
# 0.4.7 (April 27, 2018)
* Make `Buf` and `BufMut` usable as trait objects (#186).
* impl BorrowMut for BytesMut (#185).
* Improve accessor performance (#195).
# 0.4.6 (Janary 8, 2018)
* Implement FromIterator for Bytes/BytesMut (#148).
* Add `advance` fn to Bytes/BytesMut (#166).
* Add `unsplit` fn to `BytesMut` (#162, #173).
* Improvements to Bytes split fns (#92).
# 0.4.5 (August 12, 2017)
* Fix range bug in `Take::bytes`
* Misc performance improvements
* Add extra `PartialEq` implementations.
* Add `Bytes::with_capacity`
* Implement `AsMut[u8]` for `BytesMut`
# 0.4.4 (May 26, 2017)
* Add serde support behind feature flag
* Add `extend_from_slice` on `Bytes` and `BytesMut`
* Add `truncate` and `clear` on `Bytes`
* Misc additional std trait implementations
* Misc performance improvements
# 0.4.3 (April 30, 2017)
* Fix Vec::advance_mut bug
* Bump minimum Rust version to 1.15
* Misc performance tweaks
# 0.4.2 (April 5, 2017)
* Misc performance tweaks
* Improved `Debug` implementation for `Bytes`
* Avoid some incorrect assert panics
# 0.4.1 (March 15, 2017)
+4 -3
View File
@@ -1,8 +1,8 @@
[package]
name = "bytes"
version = "0.4.1"
license = "MIT"
version = "0.4.8" # don't forget to update html_root_url
license = "MIT/Apache-2.0"
authors = ["Carl Lerche <[email protected]>"]
description = "Types and traits for working with bytes"
documentation = "https://carllerche.github.io/bytes/bytes"
@@ -22,6 +22,7 @@ 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"
+9
View File
@@ -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
+217
View File
@@ -0,0 +1,217 @@
#![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 split_off_and_drop(b: &mut Bencher) {
b.iter(|| {
for _ in 0..1024 {
let v = vec![10; 200];
let mut b = Bytes::from(v);
test::black_box(b.split_off(100));
test::black_box(b);
}
})
}
#[bench]
fn deref_unique(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(4096);
buf.put(&[0u8; 1024][..]);
b.iter(|| {
for _ in 0..1024 {
test::black_box(&buf[..]);
}
})
}
#[bench]
fn deref_unique_unroll(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(4096);
buf.put(&[0u8; 1024][..]);
b.iter(|| {
for _ in 0..128 {
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
}
})
}
#[bench]
fn deref_shared(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(4096);
buf.put(&[0u8; 1024][..]);
let _b2 = buf.split_off(1024);
b.iter(|| {
for _ in 0..1024 {
test::black_box(&buf[..]);
}
})
}
#[bench]
fn deref_inline(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(8);
buf.put(&[0u8; 8][..]);
b.iter(|| {
for _ in 0..1024 {
test::black_box(&buf[..]);
}
})
}
#[bench]
fn deref_two(b: &mut Bencher) {
let mut buf1 = BytesMut::with_capacity(8);
buf1.put(&[0u8; 8][..]);
let mut buf2 = BytesMut::with_capacity(4096);
buf2.put(&[0u8; 1024][..]);
b.iter(|| {
for _ in 0..512 {
test::black_box(&buf1[..]);
test::black_box(&buf2[..]);
}
})
}
#[bench]
fn alloc_write_split_to_mid(b: &mut Bencher) {
b.iter(|| {
let mut buf = BytesMut::with_capacity(128);
buf.put_slice(&[0u8; 64]);
test::black_box(buf.split_to(64));
})
}
#[bench]
fn drain_write_drain(b: &mut Bencher) {
let data = [0u8; 128];
b.iter(|| {
let mut buf = BytesMut::with_capacity(1024);
let mut parts = Vec::with_capacity(8);
for _ in 0..8 {
buf.put(&data[..]);
parts.push(buf.split_to(128));
}
test::black_box(parts);
})
}
#[bench]
fn fmt_write(b: &mut Bencher) {
use std::fmt::Write;
let mut buf = BytesMut::with_capacity(128);
let s = "foo bar baz quux lorem ipsum dolor et";
b.bytes = s.len() as u64;
b.iter(|| {
let _ = write!(buf, "{}", s);
test::black_box(&buf);
unsafe { buf.set_len(0); }
})
}
#[bench]
fn from_long_slice(b: &mut Bencher) {
let data = [0u8; 128];
b.bytes = data.len() as u64;
b.iter(|| {
let buf = BytesMut::from(&data[..]);
test::black_box(buf);
})
}
#[bench]
fn slice_empty(b: &mut Bencher) {
b.iter(|| {
let b = Bytes::from(vec![17; 1024]).clone();
for i in 0..1000 {
test::black_box(b.slice(i % 100, i % 100));
}
})
}
#[bench]
fn slice_short_from_arc(b: &mut Bencher) {
b.iter(|| {
// `clone` is to convert to ARC
let b = Bytes::from(vec![17; 1024]).clone();
for i in 0..1000 {
test::black_box(b.slice(1, 2 + i % 10));
}
})
}
// Keep in sync with bytes.rs
#[cfg(target_pointer_width = "64")]
const INLINE_CAP: usize = 4 * 8 - 1;
#[cfg(target_pointer_width = "32")]
const INLINE_CAP: usize = 4 * 4 - 1;
#[bench]
fn slice_avg_le_inline_from_arc(b: &mut Bencher) {
b.iter(|| {
// `clone` is to convert to ARC
let b = Bytes::from(vec![17; 1024]).clone();
for i in 0..1000 {
// [1, INLINE_CAP]
let len = 1 + i % (INLINE_CAP - 1);
test::black_box(b.slice(i % 10, i % 10 + len));
}
})
}
#[bench]
fn slice_large_le_inline_from_arc(b: &mut Bencher) {
b.iter(|| {
// `clone` is to convert to ARC
let b = Bytes::from(vec![17; 1024]).clone();
for i in 0..1000 {
// [INLINE_CAP - 10, INLINE_CAP]
let len = INLINE_CAP - 9 + i % 10;
test::black_box(b.slice(i % 10, i % 10 + len));
}
})
}
-210
View File
@@ -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
View File
@@ -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
+21
View File
@@ -0,0 +1,21 @@
# TSAN suppressions file for `bytes`
# TSAN does not understand fences and `Arc::drop` is implemented using a fence.
# This causes many false positives.
race:Arc*drop
race:arc*Weak*drop
# `std` mpsc is not used in any Bytes code base. This race is triggered by some
# rust runtime logic.
race:std*mpsc_queue
# Not sure why this is warning, but it is in the test harness and not the library.
race:TestEvent*clone
race:test::run_tests_console::*closure
# Probably more fences in std.
race:__call_tls_dtors
# `is_inline` is explicitly called concurrently without synchronization. The
# safety explanation can be found in a comment.
race:Inner::is_inline
+457 -146
View File
@@ -1,15 +1,48 @@
use super::{IntoBuf, Take, Reader, Iter, FromBuf, Chain};
use byteorder::ByteOrder;
use byteorder::{BigEndian, ByteOrder, LittleEndian};
use iovec::IoVec;
use std::{cmp, io, ptr};
macro_rules! buf_get_impl {
($this:ident, $size:expr, $conv:path) => ({
// try to convert directly from the bytes
let ret = {
// this Option<ret> trick is to avoid keeping a borrow on self
// when advance() is called (mut borrow) and to call bytes() only once
if let Some(src) = $this.bytes().get(..($size)) {
Some($conv(src))
} else {
None
}
};
if let Some(ret) = ret {
// if the direct convertion was possible, advance and return
$this.advance($size);
return ret;
} else {
// if not we copy the bytes in a temp buffer then convert
let mut buf = [0; ($size)];
$this.copy_to_slice(&mut buf); // (do the advance)
return $conv(&buf);
}
});
($this:ident, $buf_size:expr, $conv:path, $len_to_read:expr) => ({
// The same trick as above does not improve the best case speed.
// It seems to be linked to the way the method is optimised by the compiler
let mut buf = [0; ($buf_size)];
$this.copy_to_slice(&mut buf[..($len_to_read)]);
return $conv(&buf[..($len_to_read)], $len_to_read);
});
}
/// Read bytes from a buffer.
///
/// A buffer stores bytes in memory such that read operations are infallible.
/// The underlying storage may or may not be in contiguous memory. A `Buf` value
/// is a cursor into the buffer. Reading from `Buf` advances the cursor
/// position.
/// position. It can be thought of as an efficient `Iterator` for collections of
/// bytes.
///
/// The simplest `Buf` is a `Cursor` wrapping a `[u8]`.
///
@@ -242,9 +275,10 @@ pub trait Buf {
///
/// 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]
assert!(self.remaining() >= 1);
let ret = self.bytes()[0];
self.advance(1);
ret
}
/// Gets a signed 8 bit integer from `self`.
@@ -265,243 +299,516 @@ pub trait Buf {
///
/// 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
assert!(self.remaining() >= 1);
let ret = self.bytes()[0] as i8;
self.advance(1);
ret
}
/// 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 {
#[doc(hidden)]
#[deprecated(note="use get_u16_be or get_u16_le")]
fn get_u16<T: ByteOrder>(&mut self) -> u16 where Self: Sized {
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.
/// Gets an unsigned 16 bit integer from `self` in big-endian byte order.
///
/// The current position is advanced by 2.
///
/// # Examples
///
/// ```
/// use bytes::{Buf, BigEndian};
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x08\x09 hello");
/// assert_eq!(0x0809, buf.get_i16::<BigEndian>());
/// assert_eq!(0x0809, buf.get_u16_be());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_i16<T: ByteOrder>(&mut self) -> i16 {
fn get_u16_be(&mut self) -> u16 {
buf_get_impl!(self, 2, BigEndian::read_u16);
}
/// Gets an unsigned 16 bit integer from `self` in little-endian byte order.
///
/// The current position is advanced by 2.
///
/// # Examples
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x09\x08 hello");
/// assert_eq!(0x0809, buf.get_u16_le());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_u16_le(&mut self) -> u16 {
buf_get_impl!(self, 2, LittleEndian::read_u16);
}
#[doc(hidden)]
#[deprecated(note="use get_i16_be or get_i16_le")]
fn get_i16<T: ByteOrder>(&mut self) -> i16 where Self: Sized {
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.
/// Gets a signed 16 bit integer from `self` in big-endian byte order.
///
/// The current position is advanced by 4.
/// The current position is advanced by 2.
///
/// # Examples
///
/// ```
/// use bytes::{Buf, BigEndian};
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x08\x09\xA0\xA1 hello");
/// assert_eq!(0x0809A0A1, buf.get_u32::<BigEndian>());
/// let mut buf = Cursor::new(b"\x08\x09 hello");
/// assert_eq!(0x0809, buf.get_i16_be());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_u32<T: ByteOrder>(&mut self) -> u32 {
fn get_i16_be(&mut self) -> i16 {
buf_get_impl!(self, 2, BigEndian::read_i16);
}
/// Gets a signed 16 bit integer from `self` in little-endian byte order.
///
/// The current position is advanced by 2.
///
/// # Examples
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x09\x08 hello");
/// assert_eq!(0x0809, buf.get_i16_le());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_i16_le(&mut self) -> i16 {
buf_get_impl!(self, 2, LittleEndian::read_i16);
}
#[doc(hidden)]
#[deprecated(note="use get_u32_be or get_u32_le")]
fn get_u32<T: ByteOrder>(&mut self) -> u32 where Self: Sized {
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.
/// Gets an unsigned 32 bit integer from `self` in the big-endian byte order.
///
/// The current position is advanced by 4.
///
/// # Examples
///
/// ```
/// use bytes::{Buf, BigEndian};
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x08\x09\xA0\xA1 hello");
/// assert_eq!(0x0809A0A1, buf.get_i32::<BigEndian>());
/// assert_eq!(0x0809A0A1, buf.get_u32_be());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_i32<T: ByteOrder>(&mut self) -> i32 {
fn get_u32_be(&mut self) -> u32 {
buf_get_impl!(self, 4, BigEndian::read_u32);
}
/// Gets an unsigned 32 bit integer from `self` in the little-endian byte order.
///
/// The current position is advanced by 4.
///
/// # Examples
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\xA1\xA0\x09\x08 hello");
/// assert_eq!(0x0809A0A1, buf.get_u32_le());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_u32_le(&mut self) -> u32 {
buf_get_impl!(self, 4, LittleEndian::read_u32);
}
#[doc(hidden)]
#[deprecated(note="use get_i32_be or get_i32_le")]
fn get_i32<T: ByteOrder>(&mut self) -> i32 where Self: Sized {
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.
/// Gets a signed 32 bit integer from `self` in big-endian byte order.
///
/// The current position is advanced by 4.
///
/// # Examples
///
/// ```
/// use bytes::{Buf, BigEndian};
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x3F\x99\x99\x9A hello");
/// assert_eq!(1.2f32, buf.get_f32::<BigEndian>());
/// let mut buf = Cursor::new(b"\x08\x09\xA0\xA1 hello");
/// assert_eq!(0x0809A0A1, buf.get_i32_be());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_f32<T: ByteOrder>(&mut self) -> f32 {
let mut buf = [0; 4];
self.copy_to_slice(&mut buf);
T::read_f32(&buf)
fn get_i32_be(&mut self) -> i32 {
buf_get_impl!(self, 4, BigEndian::read_i32);
}
/// Gets an IEEE754 double-precision (8 bytes) floating point number from
/// `self` in the specified byte order.
/// Gets a signed 32 bit integer from `self` in little-endian byte order.
///
/// The current position is advanced by 4.
///
/// # Examples
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\xA1\xA0\x09\x08 hello");
/// assert_eq!(0x0809A0A1, buf.get_i32_le());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_i32_le(&mut self) -> i32 {
buf_get_impl!(self, 4, LittleEndian::read_i32);
}
#[doc(hidden)]
#[deprecated(note="use get_u64_be or get_u64_le")]
fn get_u64<T: ByteOrder>(&mut self) -> u64 where Self: Sized {
let mut buf = [0; 8];
self.copy_to_slice(&mut buf);
T::read_u64(&buf)
}
/// Gets an unsigned 64 bit integer from `self` in big-endian byte order.
///
/// The current position is advanced by 8.
///
/// # Examples
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x01\x02\x03\x04\x05\x06\x07\x08 hello");
/// assert_eq!(0x0102030405060708, buf.get_u64_be());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_u64_be(&mut self) -> u64 {
buf_get_impl!(self, 8, BigEndian::read_u64);
}
/// Gets an unsigned 64 bit integer from `self` in little-endian byte order.
///
/// The current position is advanced by 8.
///
/// # Examples
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x08\x07\x06\x05\x04\x03\x02\x01 hello");
/// assert_eq!(0x0102030405060708, buf.get_u64_le());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_u64_le(&mut self) -> u64 {
buf_get_impl!(self, 8, LittleEndian::read_u64);
}
#[doc(hidden)]
#[deprecated(note="use get_i64_be or get_i64_le")]
fn get_i64<T: ByteOrder>(&mut self) -> i64 where Self: Sized {
let mut buf = [0; 8];
self.copy_to_slice(&mut buf);
T::read_i64(&buf)
}
/// Gets a signed 64 bit integer from `self` in big-endian byte order.
///
/// The current position is advanced by 8.
///
/// # Examples
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x01\x02\x03\x04\x05\x06\x07\x08 hello");
/// assert_eq!(0x0102030405060708, buf.get_i64_be());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_i64_be(&mut self) -> i64 {
buf_get_impl!(self, 8, BigEndian::read_i64);
}
/// Gets a signed 64 bit integer from `self` in little-endian byte order.
///
/// The current position is advanced by 8.
///
/// # Examples
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x08\x07\x06\x05\x04\x03\x02\x01 hello");
/// assert_eq!(0x0102030405060708, buf.get_i64_le());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_i64_le(&mut self) -> i64 {
buf_get_impl!(self, 8, LittleEndian::read_i64);
}
#[doc(hidden)]
#[deprecated(note="use get_uint_be or get_uint_le")]
fn get_uint<T: ByteOrder>(&mut self, nbytes: usize) -> u64 where Self: Sized {
let mut buf = [0; 8];
self.copy_to_slice(&mut buf[..nbytes]);
T::read_uint(&buf[..nbytes], nbytes)
}
/// Gets an unsigned n-byte integer from `self` in big-endian byte order.
///
/// The current position is advanced by `nbytes`.
///
/// # Examples
///
/// ```
/// use bytes::{Buf, BigEndian};
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x3F\xF3\x33\x33\x33\x33\x33\x33 hello");
/// assert_eq!(1.2f64, buf.get_f64::<BigEndian>());
/// let mut buf = Cursor::new(b"\x01\x02\x03 hello");
/// assert_eq!(0x010203, buf.get_uint_be(3));
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_f64<T: ByteOrder>(&mut self) -> f64 {
fn get_uint_be(&mut self, nbytes: usize) -> u64 {
buf_get_impl!(self, 8, BigEndian::read_uint, nbytes);
}
/// Gets an unsigned n-byte integer from `self` in little-endian byte order.
///
/// The current position is advanced by `nbytes`.
///
/// # Examples
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x03\x02\x01 hello");
/// assert_eq!(0x010203, buf.get_uint_le(3));
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_uint_le(&mut self, nbytes: usize) -> u64 {
buf_get_impl!(self, 8, LittleEndian::read_uint, nbytes);
}
#[doc(hidden)]
#[deprecated(note="use get_int_be or get_int_le")]
fn get_int<T: ByteOrder>(&mut self, nbytes: usize) -> i64 where Self: Sized {
let mut buf = [0; 8];
self.copy_to_slice(&mut buf[..nbytes]);
T::read_int(&buf[..nbytes], nbytes)
}
/// Gets a signed n-byte integer from `self` in big-endian byte order.
///
/// The current position is advanced by `nbytes`.
///
/// # Examples
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x01\x02\x03 hello");
/// assert_eq!(0x010203, buf.get_int_be(3));
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_int_be(&mut self, nbytes: usize) -> i64 {
buf_get_impl!(self, 8, BigEndian::read_int, nbytes);
}
/// Gets a signed n-byte integer from `self` in little-endian byte order.
///
/// The current position is advanced by `nbytes`.
///
/// # Examples
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x03\x02\x01 hello");
/// assert_eq!(0x010203, buf.get_int_le(3));
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_int_le(&mut self, nbytes: usize) -> i64 {
buf_get_impl!(self, 8, LittleEndian::read_int, nbytes);
}
#[doc(hidden)]
#[deprecated(note="use get_f32_be or get_f32_le")]
fn get_f32<T: ByteOrder>(&mut self) -> f32 where Self: Sized {
let mut buf = [0; 4];
self.copy_to_slice(&mut buf);
T::read_f32(&buf)
}
/// Gets an IEEE754 single-precision (4 bytes) floating point number from
/// `self` in big-endian byte order.
///
/// The current position is advanced by 4.
///
/// # Examples
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x3F\x99\x99\x9A hello");
/// assert_eq!(1.2f32, buf.get_f32_be());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_f32_be(&mut self) -> f32 {
buf_get_impl!(self, 4, BigEndian::read_f32);
}
/// Gets an IEEE754 single-precision (4 bytes) floating point number from
/// `self` in little-endian byte order.
///
/// The current position is advanced by 4.
///
/// # Examples
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x9A\x99\x99\x3F hello");
/// assert_eq!(1.2f32, buf.get_f32_le());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_f32_le(&mut self) -> f32 {
buf_get_impl!(self, 4, LittleEndian::read_f32);
}
#[doc(hidden)]
#[deprecated(note="use get_f64_be or get_f64_le")]
fn get_f64<T: ByteOrder>(&mut self) -> f64 where Self: Sized {
let mut buf = [0; 8];
self.copy_to_slice(&mut buf);
T::read_f64(&buf)
}
/// Gets an IEEE754 double-precision (8 bytes) floating point number from
/// `self` in big-endian byte order.
///
/// The current position is advanced by 8.
///
/// # Examples
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x3F\xF3\x33\x33\x33\x33\x33\x33 hello");
/// assert_eq!(1.2f64, buf.get_f64_be());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_f64_be(&mut self) -> f64 {
buf_get_impl!(self, 8, BigEndian::read_f64);
}
/// Gets an IEEE754 double-precision (8 bytes) floating point number from
/// `self` in little-endian byte order.
///
/// The current position is advanced by 8.
///
/// # Examples
///
/// ```
/// use bytes::Buf;
/// use std::io::Cursor;
///
/// let mut buf = Cursor::new(b"\x33\x33\x33\x33\x33\x33\xF3\x3F hello");
/// assert_eq!(1.2f64, buf.get_f64_le());
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
fn get_f64_le(&mut self) -> f64 {
buf_get_impl!(self, 8, LittleEndian::read_f64);
}
/// Transforms a `Buf` into a concrete buffer.
///
/// `collect()` can operate on any value that implements `Buf`, and turn it
@@ -748,3 +1055,7 @@ impl Buf for Option<[u8; 1]> {
}
}
}
// The existance of this function makes the compiler catch if the Buf
// trait is "object-safe" or not.
fn _assert_trait_object(_b: &Buf) {}
+486 -156
View File
@@ -1,5 +1,5 @@
use super::{IntoBuf, Writer};
use byteorder::ByteOrder;
use byteorder::{LittleEndian, ByteOrder, BigEndian};
use iovec::IoVec;
use std::{cmp, io, ptr, usize};
@@ -59,7 +59,7 @@ pub trait BufMut {
/// further into the underlying buffer.
///
/// This function is unsafe because there is no guarantee that the bytes
/// being advanced to have been initialized.
/// being advanced past have been initialized.
///
/// # Examples
///
@@ -90,9 +90,9 @@ pub trait BufMut {
///
/// # 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()`.
/// 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);
@@ -153,8 +153,10 @@ pub trait BufMut {
///
/// # 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_mut` should
/// 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];
@@ -336,41 +338,25 @@ pub trait BufMut {
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) {
#[doc(hidden)]
#[deprecated(note="use put_u16_be or put_u16_le")]
fn put_u16<T: ByteOrder>(&mut self, n: u16) where Self: Sized {
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.
/// Writes an unsigned 16 bit integer to `self` in big-endian byte order.
///
/// The current position is advanced by 2.
///
/// # Examples
///
/// ```
/// use bytes::{BufMut, BigEndian};
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_i16::<BigEndian>(0x0809);
/// buf.put_u16_be(0x0809);
/// assert_eq!(buf, b"\x08\x09");
/// ```
///
@@ -378,47 +364,111 @@ pub trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_i16<T: ByteOrder>(&mut self, n: i16) {
fn put_u16_be(&mut self, n: u16) {
let mut buf = [0; 2];
BigEndian::write_u16(&mut buf, n);
self.put_slice(&buf)
}
/// Writes an unsigned 16 bit integer to `self` in little-endian byte order.
///
/// The current position is advanced by 2.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_u16_le(0x0809);
/// assert_eq!(buf, b"\x09\x08");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_u16_le(&mut self, n: u16) {
let mut buf = [0; 2];
LittleEndian::write_u16(&mut buf, n);
self.put_slice(&buf)
}
#[doc(hidden)]
#[deprecated(note="use put_i16_be or put_i16_le")]
fn put_i16<T: ByteOrder>(&mut self, n: i16) where Self: Sized {
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.
/// Writes a signed 16 bit integer to `self` in big-endian byte order.
///
/// The current position is advanced by 4.
/// The current position is advanced by 2.
///
/// # Examples
///
/// ```
/// use bytes::{BufMut, BigEndian};
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_u32::<BigEndian>(0x0809A0A1);
/// assert_eq!(buf, b"\x08\x09\xA0\xA1");
/// buf.put_i16_be(0x0809);
/// assert_eq!(buf, b"\x08\x09");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_u32<T: ByteOrder>(&mut self, n: u32) {
fn put_i16_be(&mut self, n: i16) {
let mut buf = [0; 2];
BigEndian::write_i16(&mut buf, n);
self.put_slice(&buf)
}
/// Writes a signed 16 bit integer to `self` in little-endian byte order.
///
/// The current position is advanced by 2.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_i16_le(0x0809);
/// assert_eq!(buf, b"\x09\x08");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_i16_le(&mut self, n: i16) {
let mut buf = [0; 2];
LittleEndian::write_i16(&mut buf, n);
self.put_slice(&buf)
}
#[doc(hidden)]
#[deprecated(note="use put_u32_be or put_u32_le")]
fn put_u32<T: ByteOrder>(&mut self, n: u32) where Self: Sized {
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.
/// Writes an unsigned 32 bit integer to `self` in big-endian byte order.
///
/// The current position is advanced by 4.
///
/// # Examples
///
/// ```
/// use bytes::{BufMut, BigEndian};
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_i32::<BigEndian>(0x0809A0A1);
/// buf.put_u32_be(0x0809A0A1);
/// assert_eq!(buf, b"\x08\x09\xA0\xA1");
/// ```
///
@@ -426,120 +476,336 @@ pub trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_i32<T: ByteOrder>(&mut self, n: i32) {
fn put_u32_be(&mut self, n: u32) {
let mut buf = [0; 4];
T::write_i32(&mut buf, n);
BigEndian::write_u32(&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.
/// Writes an unsigned 32 bit integer to `self` in little-endian byte order.
///
/// The current position is advanced by 4.
///
/// # Examples
///
/// ```
/// use bytes::{BufMut, BigEndian};
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_f32::<BigEndian>(1.2f32);
/// buf.put_u32_le(0x0809A0A1);
/// assert_eq!(buf, b"\xA1\xA0\x09\x08");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_u32_le(&mut self, n: u32) {
let mut buf = [0; 4];
LittleEndian::write_u32(&mut buf, n);
self.put_slice(&buf)
}
#[doc(hidden)]
#[deprecated(note="use put_i32_be or put_i32_le")]
fn put_i32<T: ByteOrder>(&mut self, n: i32) where Self: Sized {
let mut buf = [0; 4];
T::write_i32(&mut buf, n);
self.put_slice(&buf)
}
/// Writes a signed 32 bit integer to `self` in big-endian byte order.
///
/// The current position is advanced by 4.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_i32_be(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_be(&mut self, n: i32) {
let mut buf = [0; 4];
BigEndian::write_i32(&mut buf, n);
self.put_slice(&buf)
}
/// Writes a signed 32 bit integer to `self` in little-endian byte order.
///
/// The current position is advanced by 4.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_i32_le(0x0809A0A1);
/// assert_eq!(buf, b"\xA1\xA0\x09\x08");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_i32_le(&mut self, n: i32) {
let mut buf = [0; 4];
LittleEndian::write_i32(&mut buf, n);
self.put_slice(&buf)
}
#[doc(hidden)]
#[deprecated(note="use put_u64_be or put_u64_le")]
fn put_u64<T: ByteOrder>(&mut self, n: u64) where Self: Sized {
let mut buf = [0; 8];
T::write_u64(&mut buf, n);
self.put_slice(&buf)
}
/// Writes an unsigned 64 bit integer to `self` in the big-endian byte order.
///
/// The current position is advanced by 8.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_u64_be(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_be(&mut self, n: u64) {
let mut buf = [0; 8];
BigEndian::write_u64(&mut buf, n);
self.put_slice(&buf)
}
/// Writes an unsigned 64 bit integer to `self` in little-endian byte order.
///
/// The current position is advanced by 8.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_u64_le(0x0102030405060708);
/// assert_eq!(buf, b"\x08\x07\x06\x05\x04\x03\x02\x01");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_u64_le(&mut self, n: u64) {
let mut buf = [0; 8];
LittleEndian::write_u64(&mut buf, n);
self.put_slice(&buf)
}
#[doc(hidden)]
#[deprecated(note="use put_i64_be or put_i64_le")]
fn put_i64<T: ByteOrder>(&mut self, n: i64) where Self: Sized {
let mut buf = [0; 8];
T::write_i64(&mut buf, n);
self.put_slice(&buf)
}
/// Writes a signed 64 bit integer to `self` in the big-endian byte order.
///
/// The current position is advanced by 8.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_i64_be(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_be(&mut self, n: i64) {
let mut buf = [0; 8];
BigEndian::write_i64(&mut buf, n);
self.put_slice(&buf)
}
/// Writes a signed 64 bit integer to `self` in little-endian byte order.
///
/// The current position is advanced by 8.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_i64_le(0x0102030405060708);
/// assert_eq!(buf, b"\x08\x07\x06\x05\x04\x03\x02\x01");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_i64_le(&mut self, n: i64) {
let mut buf = [0; 8];
LittleEndian::write_i64(&mut buf, n);
self.put_slice(&buf)
}
#[doc(hidden)]
#[deprecated(note="use put_uint_be or put_uint_le")]
fn put_uint<T: ByteOrder>(&mut self, n: u64, nbytes: usize) where Self: Sized {
let mut buf = [0; 8];
T::write_uint(&mut buf, n, nbytes);
self.put_slice(&buf[0..nbytes])
}
/// Writes an unsigned n-byte integer to `self` in big-endian byte order.
///
/// The current position is advanced by `nbytes`.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_uint_be(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_be(&mut self, n: u64, nbytes: usize) {
let mut buf = [0; 8];
BigEndian::write_uint(&mut buf, n, nbytes);
self.put_slice(&buf[0..nbytes])
}
/// Writes an unsigned n-byte integer to `self` in the little-endian byte order.
///
/// The current position is advanced by `nbytes`.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_uint_le(0x010203, 3);
/// assert_eq!(buf, b"\x03\x02\x01");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_uint_le(&mut self, n: u64, nbytes: usize) {
let mut buf = [0; 8];
LittleEndian::write_uint(&mut buf, n, nbytes);
self.put_slice(&buf[0..nbytes])
}
#[doc(hidden)]
#[deprecated(note="use put_int_be or put_int_le")]
fn put_int<T: ByteOrder>(&mut self, n: i64, nbytes: usize) where Self: Sized {
let mut buf = [0; 8];
T::write_int(&mut buf, n, nbytes);
self.put_slice(&buf[0..nbytes])
}
/// Writes a signed n-byte integer to `self` in big-endian byte order.
///
/// The current position is advanced by `nbytes`.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_int_be(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_be(&mut self, n: i64, nbytes: usize) {
let mut buf = [0; 8];
BigEndian::write_int(&mut buf, n, nbytes);
self.put_slice(&buf[0..nbytes])
}
/// Writes a signed n-byte integer to `self` in little-endian byte order.
///
/// The current position is advanced by `nbytes`.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_int_le(0x010203, 3);
/// assert_eq!(buf, b"\x03\x02\x01");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_int_le(&mut self, n: i64, nbytes: usize) {
let mut buf = [0; 8];
LittleEndian::write_int(&mut buf, n, nbytes);
self.put_slice(&buf[0..nbytes])
}
#[doc(hidden)]
#[deprecated(note="use put_f32_be or put_f32_le")]
fn put_f32<T: ByteOrder>(&mut self, n: f32) where Self: Sized {
let mut buf = [0; 4];
T::write_f32(&mut buf, n);
self.put_slice(&buf)
}
/// Writes an IEEE754 single-precision (4 bytes) floating point number to
/// `self` in big-endian byte order.
///
/// The current position is advanced by 4.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_f32_be(1.2f32);
/// assert_eq!(buf, b"\x3F\x99\x99\x9A");
/// ```
///
@@ -547,24 +813,57 @@ pub trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_f32<T: ByteOrder>(&mut self, n: f32) {
fn put_f32_be(&mut self, n: f32) {
let mut buf = [0; 4];
T::write_f32(&mut buf, n);
BigEndian::write_f32(&mut buf, n);
self.put_slice(&buf)
}
/// Writes an IEEE754 single-precision (4 bytes) floating point number to
/// `self` in little-endian byte order.
///
/// The current position is advanced by 4.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_f32_le(1.2f32);
/// assert_eq!(buf, b"\x9A\x99\x99\x3F");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_f32_le(&mut self, n: f32) {
let mut buf = [0; 4];
LittleEndian::write_f32(&mut buf, n);
self.put_slice(&buf)
}
#[doc(hidden)]
#[deprecated(note="use put_f64_be or put_f64_le")]
fn put_f64<T: ByteOrder>(&mut self, n: f64) where Self: Sized {
let mut buf = [0; 8];
T::write_f64(&mut buf, n);
self.put_slice(&buf)
}
/// Writes an IEEE754 double-precision (8 bytes) floating point number to
/// `self` in the specified byte order.
/// `self` in big-endian byte order.
///
/// The current position is advanced by 8.
///
/// # Examples
///
/// ```
/// use bytes::{BufMut, BigEndian};
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_f64::<BigEndian>(1.2f64);
/// buf.put_f64_be(1.2f64);
/// assert_eq!(buf, b"\x3F\xF3\x33\x33\x33\x33\x33\x33");
/// ```
///
@@ -572,9 +871,34 @@ pub trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_f64<T: ByteOrder>(&mut self, n: f64) {
fn put_f64_be(&mut self, n: f64) {
let mut buf = [0; 8];
T::write_f64(&mut buf, n);
BigEndian::write_f64(&mut buf, n);
self.put_slice(&buf)
}
/// Writes an IEEE754 double-precision (8 bytes) floating point number to
/// `self` in little-endian byte order.
///
/// The current position is advanced by 8.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_f64_le(1.2f64);
/// assert_eq!(buf, b"\x33\x33\x33\x33\x33\x33\xF3\x3F");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_f64_le(&mut self, n: f64) {
let mut buf = [0; 8];
LittleEndian::write_f64(&mut buf, n);
self.put_slice(&buf)
}
@@ -699,23 +1023,25 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>> BufMut for io::Cursor<T> {
}
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 cap = self.capacity();
let len = self.len().checked_add(cnt)
.expect("overflow");
if len > cap {
// Reserve additional
self.reserve(cap - len);
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);
self.set_len(len + cnt);
}
#[inline]
unsafe fn bytes_mut(&mut self) -> &mut [u8] {
use std::slice;
@@ -730,3 +1056,7 @@ impl BufMut for Vec<u8> {
&mut slice::from_raw_parts_mut(ptr, cap)[len..]
}
}
// The existance of this function makes the compiler catch if the BufMut
// trait is "object-safe" or not.
fn _assert_trait_object(_b: &BufMut) {}
+2
View File
@@ -112,3 +112,5 @@ impl<T: Buf> Iterator for Iter<T> {
(rem, Some(rem))
}
}
impl<T: Buf> ExactSizeIterator for Iter<T> { }
+2 -1
View File
@@ -143,7 +143,8 @@ impl<T: Buf> Buf for Take<T> {
}
fn bytes(&self) -> &[u8] {
&self.inner.bytes()[..self.limit]
let bytes = self.inner.bytes();
&bytes[..cmp::min(bytes.len(), self.limit)]
}
fn advance(&mut self, cnt: usize) {
+787 -232
View File
File diff suppressed because it is too large Load Diff
+40
View File
@@ -0,0 +1,40 @@
use std::fmt;
/// Alternative implementation of `fmt::Debug` for byte slice.
///
/// Standard `Debug` implementation for `[u8]` is comma separated
/// list of numbers. Since large amount of byte strings are in fact
/// ASCII strings or contain a lot of ASCII strings (e. g. HTTP),
/// it is convenient to print strings as ASCII when possible.
///
/// This struct wraps `&[u8]` just to override `fmt::Debug`.
///
/// `BsDebug` is not a part of public API of bytes crate.
pub struct BsDebug<'a>(pub &'a [u8]);
impl<'a> fmt::Debug for BsDebug<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
try!(write!(fmt, "b\""));
for &c in self.0 {
// https://doc.rust-lang.org/reference.html#byte-escapes
if c == b'\n' {
try!(write!(fmt, "\\n"));
} else if c == b'\r' {
try!(write!(fmt, "\\r"));
} else if c == b'\t' {
try!(write!(fmt, "\\t"));
} else if c == b'\\' || c == b'"' {
try!(write!(fmt, "\\{}", c as char));
} else if c == b'\0' {
try!(write!(fmt, "\\0"));
// ASCII printable
} else if c >= 0x20 && c < 0x7f {
try!(write!(fmt, "{}", c as char));
} else {
try!(write!(fmt, "\\x{:02x}", c));
}
}
try!(write!(fmt, "\""));
Ok(())
}
}
+11 -4
View File
@@ -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,14 +62,14 @@
//! ## 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, missing_debug_implementations)]
#![doc(html_root_url = "https://docs.rs/bytes/0.4")]
#![doc(html_root_url = "https://docs.rs/bytes/0.4.8")]
extern crate byteorder;
extern crate iovec;
@@ -89,6 +89,13 @@ pub use buf::{
};
mod bytes;
mod debug;
pub use bytes::{Bytes, BytesMut};
#[deprecated]
pub use byteorder::{ByteOrder, BigEndian, LittleEndian};
// Optional Serde support
#[cfg(feature = "serde")]
#[doc(hidden)]
pub mod serde;
+82
View File
@@ -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);
+9 -4
View File
@@ -33,21 +33,26 @@ fn test_get_u8() {
#[test]
fn test_get_u16() {
let buf = b"\x21\x54zomg";
assert_eq!(0x2154, Cursor::new(buf).get_u16::<byteorder::BigEndian>());
assert_eq!(0x5421, Cursor::new(buf).get_u16::<byteorder::LittleEndian>());
assert_eq!(0x2154, Cursor::new(buf).get_u16_be());
assert_eq!(0x5421, Cursor::new(buf).get_u16_le());
}
#[test]
#[should_panic]
fn test_get_u16_buffer_underflow() {
let mut buf = Cursor::new(b"\x21");
buf.get_u16::<byteorder::BigEndian>();
buf.get_u16_be();
}
#[test]
fn test_bufs_vec() {
let buf = Cursor::new(b"hello world");
let mut dst: [&IoVec; 2] = Default::default();
let b1: &[u8] = &mut [0];
let b2: &[u8] = &mut [0];
let mut dst: [&IoVec; 2] =
[b1.into(), b2.into()];
assert_eq!(1, buf.bytes_vec(&mut dst[..]));
}
+13 -2
View File
@@ -41,14 +41,25 @@ fn test_put_u8() {
#[test]
fn test_put_u16() {
let mut buf = Vec::with_capacity(8);
buf.put_u16::<byteorder::BigEndian>(8532);
buf.put_u16_be(8532);
assert_eq!(b"\x21\x54", &buf[..]);
buf.clear();
buf.put_u16::<byteorder::LittleEndian>(8532);
buf.put_u16_le(8532);
assert_eq!(b"\x54\x21", &buf[..]);
}
#[test]
fn test_vec_advance_mut() {
// Regression test for carllerche/bytes#108.
let mut buf = Vec::with_capacity(8);
unsafe {
buf.advance_mut(12);
assert_eq!(buf.len(), 12);
assert!(buf.capacity() >= 12, "capacity: {}", buf.capacity());
}
}
#[test]
fn test_clone() {
let mut buf = BytesMut::with_capacity(100);
+388 -8
View File
@@ -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);
@@ -51,6 +51,28 @@ fn fmt() {
assert_eq!(a, b);
}
#[test]
fn fmt_write() {
use std::fmt::Write;
use std::iter::FromIterator;
let s = String::from_iter((0..10).map(|_| "abcdefg"));
let mut a = BytesMut::with_capacity(64);
write!(a, "{}", &s[..64]).unwrap();
assert_eq!(a, s[..64].as_bytes());
let mut b = BytesMut::with_capacity(64);
write!(b, "{}", &s[..32]).unwrap();
write!(b, "{}", &s[32..64]).unwrap();
assert_eq!(b, s[..64].as_bytes());
let mut c = BytesMut::with_capacity(64);
write!(c, "{}", s).unwrap_err();
assert!(c.is_empty());
}
#[test]
fn len() {
let a = Bytes::from(&b"abcdefg"[..]);
@@ -79,6 +101,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"[..]);
@@ -134,6 +165,50 @@ fn split_off_uninitialized() {
assert_eq!(other.capacity(), 896);
}
#[test]
fn split_off_to_loop() {
let s = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
for i in 0..(s.len() + 1) {
{
let mut bytes = Bytes::from(&s[..]);
let off = bytes.split_off(i);
assert_eq!(i, bytes.len());
let mut sum = Vec::new();
sum.extend(&bytes);
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
@@ -194,6 +269,28 @@ fn split_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"[..]);
@@ -236,7 +333,7 @@ fn reserve_convert() {
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);
}
@@ -253,16 +350,16 @@ fn reserve_growth() {
#[test]
fn reserve_allocates_at_least_original_capacity() {
let mut bytes = BytesMut::with_capacity(128);
let mut bytes = BytesMut::with_capacity(1024);
for i in 0..120 {
for i in 0..1020 {
bytes.put(i as u8);
}
let _other = bytes.take();
bytes.reserve(16);
assert_eq!(bytes.capacity(), 128);
assert_eq!(bytes.capacity(), 1024);
}
#[test]
@@ -281,6 +378,57 @@ fn reserve_max_original_capacity_value() {
assert_eq!(bytes.capacity(), 64 * 1024);
}
// Without either looking at the internals of the BytesMut or doing weird stuff
// with the memory allocator, there's no good way to automatically verify from
// within the program that this actually recycles memory. Instead, just exercise
// the code path to ensure that the results are correct.
#[test]
fn reserve_vec_recycling() {
let mut bytes = BytesMut::from(Vec::with_capacity(16));
assert_eq!(bytes.capacity(), 16);
bytes.put("0123456789012345");
bytes.advance(10);
assert_eq!(bytes.capacity(), 6);
bytes.reserve(8);
assert_eq!(bytes.capacity(), 16);
}
#[test]
fn reserve_in_arc_unique_does_not_overallocate() {
let mut bytes = BytesMut::with_capacity(1000);
bytes.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());
@@ -291,13 +439,90 @@ fn inline_storage() {
}
#[test]
fn extend() {
fn extend_mut() {
let mut bytes = BytesMut::with_capacity(0);
bytes.extend(LONG);
assert_eq!(*bytes, LONG[..]);
}
#[test]
fn extend_shr() {
let mut bytes = Bytes::new();
bytes.extend(LONG);
assert_eq!(*bytes, LONG[..]);
}
#[test]
fn extend_from_slice_mut() {
for &i in &[3, 34] {
let mut bytes = BytesMut::new();
bytes.extend_from_slice(&LONG[..i]);
bytes.extend_from_slice(&LONG[i..]);
assert_eq!(LONG[..], *bytes);
}
}
#[test]
fn extend_from_slice_shr() {
for &i in &[3, 34] {
let mut bytes = Bytes::new();
bytes.extend_from_slice(&LONG[..i]);
bytes.extend_from_slice(&LONG[i..]);
assert_eq!(LONG[..], *bytes);
}
}
#[test]
fn from_static() {
let mut a = Bytes::from_static(b"ab");
let b = a.split_off(1);
assert_eq!(a, b"a"[..]);
assert_eq!(b, b"b"[..]);
}
#[test]
fn advance_inline() {
let mut a = Bytes::from(&b"hello world"[..]);
a.advance(6);
assert_eq!(a, &b"world"[..]);
}
#[test]
fn advance_static() {
let mut a = Bytes::from_static(b"hello world");
a.advance(6);
assert_eq!(a, &b"world"[..]);
}
#[test]
fn advance_vec() {
let mut a = BytesMut::from(b"hello world boooo yah world zomg wat wat".to_vec());
a.advance(16);
assert_eq!(a, b"o yah world zomg wat wat"[..]);
a.advance(4);
assert_eq!(a, b"h world zomg wat wat"[..]);
// Reserve some space.
a.reserve(1024);
assert_eq!(a, b"h world zomg wat wat"[..]);
a.advance(6);
assert_eq!(a, b"d zomg wat wat"[..]);
}
#[test]
#[should_panic]
fn advance_past_len() {
let mut a = BytesMut::from(b"hello world".to_vec());
a.advance(20);
}
#[test]
// Only run these tests on little endian systems. CI uses qemu for testing
// little endian... and qemu doesn't really support threading all that well.
#[cfg(target_endian = "little")]
fn stress() {
// Tests promoting a buffer from a vec -> shared in a concurrent situation
use std::sync::{Arc, Barrier};
@@ -308,7 +533,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);
@@ -319,7 +544,8 @@ fn stress() {
joins.push(thread::spawn(move || {
c.wait();
let _buf = buf.clone();
let buf: Bytes = (*buf).clone();
drop(buf);
}));
}
@@ -330,3 +556,157 @@ fn stress() {
assert_eq!(*buf, data[..]);
}
}
#[test]
fn partial_eq_bytesmut() {
let bytes = Bytes::from(&b"The quick red fox"[..]);
let bytesmut = BytesMut::from(&b"The quick red fox"[..]);
assert!(bytes == bytesmut);
assert!(bytesmut == bytes);
let bytes2 = Bytes::from(&b"Jumped over the lazy brown dog"[..]);
assert!(bytes2 != bytesmut);
assert!(bytesmut != bytes2);
}
#[test]
fn unsplit_basic() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaabbbcccddd");
let splitted = buf.split_off(6);
assert_eq!(b"aaabbb", &buf[..]);
assert_eq!(b"cccddd", &splitted[..]);
buf.unsplit(splitted);
assert_eq!(b"aaabbbcccddd", &buf[..]);
}
#[test]
fn unsplit_empty_other() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaabbbcccddd");
// empty other
let other = BytesMut::new();
buf.unsplit(other);
assert_eq!(b"aaabbbcccddd", &buf[..]);
}
#[test]
fn unsplit_empty_self() {
// empty self
let mut buf = BytesMut::new();
let mut other = BytesMut::with_capacity(64);
other.extend_from_slice(b"aaabbbcccddd");
buf.unsplit(other);
assert_eq!(b"aaabbbcccddd", &buf[..]);
}
#[test]
fn unsplit_inline_arc() {
let mut buf = BytesMut::with_capacity(8); //inline
buf.extend_from_slice(b"aaaabbbb");
let mut buf2 = BytesMut::with_capacity(64);
buf2.extend_from_slice(b"ccccddddeeee");
buf2.split_off(8); //arc
buf.unsplit(buf2);
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
}
#[test]
fn unsplit_arc_inline() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbeeee");
buf.split_off(8); //arc
let mut buf2 = BytesMut::with_capacity(8); //inline
buf2.extend_from_slice(b"ccccdddd");
buf.unsplit(buf2);
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
}
#[test]
fn unsplit_both_inline() {
let mut buf = BytesMut::with_capacity(16); //inline
buf.extend_from_slice(b"aaaabbbbccccdddd");
let splitted = buf.split_off(8); // both inline
assert_eq!(b"aaaabbbb", &buf[..]);
assert_eq!(b"ccccdddd", &splitted[..]);
buf.unsplit(splitted);
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
}
#[test]
fn unsplit_arc_different() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbeeee");
buf.split_off(8); //arc
let mut buf2 = BytesMut::with_capacity(64);
buf2.extend_from_slice(b"ccccddddeeee");
buf2.split_off(8); //arc
buf.unsplit(buf2);
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
}
#[test]
fn unsplit_arc_non_contiguous() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbeeeeccccdddd");
let mut buf2 = buf.split_off(8); //arc
let buf3 = buf2.split_off(4); //arc
buf.unsplit(buf3);
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
}
#[test]
fn unsplit_two_split_offs() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbccccdddd");
let mut buf2 = buf.split_off(8); //arc
let buf3 = buf2.split_off(4); //arc
buf2.unsplit(buf3);
buf.unsplit(buf2);
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
}
#[test]
fn from_iter_no_size_hint() {
use std::iter;
let mut expect = vec![];
let actual: Bytes = iter::repeat(b'x')
.scan(100, |cnt, item| {
if *cnt >= 1 {
*cnt -= 1;
expect.push(item);
Some(item)
} else {
None
}
})
.collect();
assert_eq!(&actual[..], &expect[..]);
}
+53 -24
View File
@@ -53,41 +53,70 @@ fn vectored_read() {
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());
{
let b1: &[u8] = &mut [0];
let b2: &[u8] = &mut [0];
let b3: &[u8] = &mut [0];
let b4: &[u8] = &mut [0];
let mut iovecs: [&IoVec; 4] =
[b1.into(), b2.into(), b3.into(), b4.into()];
assert_eq!(2, buf.bytes_vec(&mut iovecs));
assert_eq!(iovecs[0][..], b"hello"[..]);
assert_eq!(iovecs[1][..], b"world"[..]);
assert_eq!(iovecs[2][..], b"\0"[..]);
assert_eq!(iovecs[3][..], b"\0"[..]);
}
buf.advance(2);
iovecs = Default::default();
{
let b1: &[u8] = &mut [0];
let b2: &[u8] = &mut [0];
let b3: &[u8] = &mut [0];
let b4: &[u8] = &mut [0];
let mut iovecs: [&IoVec; 4] =
[b1.into(), b2.into(), b3.into(), b4.into()];
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());
assert_eq!(2, buf.bytes_vec(&mut iovecs));
assert_eq!(iovecs[0][..], b"llo"[..]);
assert_eq!(iovecs[1][..], b"world"[..]);
assert_eq!(iovecs[2][..], b"\0"[..]);
assert_eq!(iovecs[3][..], b"\0"[..]);
}
buf.advance(3);
iovecs = Default::default();
{
let b1: &[u8] = &mut [0];
let b2: &[u8] = &mut [0];
let b3: &[u8] = &mut [0];
let b4: &[u8] = &mut [0];
let mut iovecs: [&IoVec; 4] =
[b1.into(), b2.into(), b3.into(), b4.into()];
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());
assert_eq!(1, buf.bytes_vec(&mut iovecs));
assert_eq!(iovecs[0][..], b"world"[..]);
assert_eq!(iovecs[1][..], b"\0"[..]);
assert_eq!(iovecs[2][..], b"\0"[..]);
assert_eq!(iovecs[3][..], b"\0"[..]);
}
buf.advance(3);
iovecs = Default::default();
{
let b1: &[u8] = &mut [0];
let b2: &[u8] = &mut [0];
let b3: &[u8] = &mut [0];
let b4: &[u8] = &mut [0];
let mut iovecs: [&IoVec; 4] =
[b1.into(), b2.into(), b3.into(), b4.into()];
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());
assert_eq!(1, buf.bytes_vec(&mut iovecs));
assert_eq!(iovecs[0][..], b"ld"[..]);
assert_eq!(iovecs[1][..], b"\0"[..]);
assert_eq!(iovecs[2][..], b"\0"[..]);
assert_eq!(iovecs[3][..], b"\0"[..]);
}
}
+35
View File
@@ -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)));
}
+22
View File
@@ -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);
}
+21
View File
@@ -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")]);
}
+13
View File
@@ -0,0 +1,13 @@
extern crate bytes;
use bytes::Buf;
use std::io::Cursor;
#[test]
fn long_take() {
// Tests that take with a size greater than the buffer length will not
// overrun the buffer. Regression test for #138.
let buf = Cursor::new(b"hello world").take(100);
assert_eq!(11, buf.remaining());
assert_eq!(b"hello world", buf.bytes());
}