Compare commits

...
96 Commits
Author SHA1 Message Date
Sean McArthur 98951ba26c v0.5.2 2019-11-27 12:59:28 -08:00
Steven FacklerandSean McArthur 171cffa505 Update README.md (#320) 2019-11-27 12:06:33 -08:00
Sean McArthurandCarl Lerche a642e1c075 Add accessors to Limit combinator (#325) 2019-11-26 18:08:39 -08:00
Steven FacklerandCarl Lerche 3cf91283f8 chore: prepare v0.5.1 release (#322) 2019-11-26 14:15:57 -08:00
Steven FacklerandCarl Lerche 1db67b4a87 doc: fix BytesMut growth documentation. (#321) 2019-11-25 11:40:40 -08:00
Carl LercheandGitHub b7c1f2a135 prepare v0.5.0 release (#319) 2019-11-25 11:19:30 -08:00
Sean McArthurandCarl Lerche cdd9fc09cd Export public the combinator types (#318) 2019-11-25 10:47:37 -08:00
Sean McArthurandCarl Lerche 44fb206148 add BufMutExt::limit (#309)
This type is the counterpart to BufExt::take. It limits how many bytes
some `BufMut` can actually be filled with.
2019-11-20 15:10:30 -08:00
Carl LercheandGitHub b3f86d8654 remove either feature (#315)
remove either feature
2019-11-20 12:59:44 -08:00
Carl LercheandGitHub 8135c1f606 implicitly grow BytesMut; add BufMutExt::chain_mut (#316)
This brings `BytesMut` in line with `Vec<u8>` behavior.

This also fixes an existing bug in BytesMut::bytes_mut that exposes
invalid slices. The bug was recently introduced and was only on master
and never released to `crates.io`.

In order to fix a test, `BufMutExt::chain_mut` is provided. Withou this,
it is not possible to chain two `&mut [u8]`.

Closes #170
2019-11-20 12:11:40 -08:00
Andrew Tunnell-JonesandCarl Lerche 59aea9e871 Make Bytes::from_static a const fn (#311)
Rust versions bumped to the minimum needed for const slice len.
2019-11-20 11:10:03 -08:00
Sean McArthurandGitHub 9a10addb44 Change loom tests to use cfg(loom) internally (#314) 2019-11-13 14:55:25 -08:00
Sean McArthurandGitHub b32f6298e2 Improve performance of BytesMut::reserve (#313)
Makes the short-circuit checks inline-able, and the moves the actual
reserving code to an inner function.
2019-11-12 14:52:02 -08:00
Sean McArthurandGitHub 856ed7c43d implement Buf for std::io::Cursor (#308) 2019-11-04 17:23:40 -08:00
Sean McArthurandGitHub 96268a80d4 Move "extra" methods to extension traits (#306) 2019-10-31 09:39:58 -07:00
Sean McArthurandGitHub 2ac72333fa Change BufMut methods that expose maybe-uninitialized bytes (#305)
- The return type of `BufMut::bytes_mut` is now
  `&mut [MaybeUninit<u8>]`.
- The argument type of `BufMut::bytes_vectored_mut` is now
  `&mut [bytes::buf::IoSliceMut]`.
- `bytes::buf::IoSliceMut` is a `repr(transparent)` wrapper around an
  `std::io::IoSliceMut`, but does not expose the inner bytes with a safe
  API, since they might be uninitialized.
- `BufMut::bytesMut` and `BufMut::bytes_vectored_mut` are no longer
  `unsafe fn`, since the types encapsulate the unsafety instead.
2019-10-24 14:40:45 -07:00
Sean McArthurandGitHub fe2183dc2f Add benchmarks for BytesMut vs Vec (#303) 2019-10-23 13:40:04 -07:00
Sean McArthurandCarl Lerche 491ebbf79a Remove Buf impl for &str (#301)
A `&str` cannot arbitrarily advance bytes, since it will panic if
advanced to the middle of a Unicode segment.
2019-10-16 11:28:50 -07:00
Sean McArthurandGitHub 43ac8e5494 Refactor Bytes to use an internal vtable (#298)
Bytes is a useful tool for managing multiple slices into the same region
of memory, and the other things it used to have been removed to reduce
complexity. The exact strategy for managing the multiple references is
no longer hard-coded, but instead backing by a customizable vtable.

- Removed ability to mutate the underlying memory from the `Bytes` type.
- Removed the "inline" (SBO) mechanism in `Bytes`. The reduces a large
  amount of complexity, and improves performance when accessing the
  slice of bytes, since a branch is no longer needed to check if the
  data is inline.
- Removed `Bytes` knowledge of `BytesMut` (`BytesMut` may grow that
  knowledge back at a future point.)
2019-10-16 09:53:36 -07:00
Taiki EndoandDouman ebe96021b0 Fix build fail with serde feature (#293)
Verify no-std build and all features build
2019-09-08 22:10:46 +02:00
Taiki EndoandDouman 97c1338833 Remove a patch for cross 2019-09-08 17:58:32 +02:00
Chris BeckandCarl Lerche c17e40115f Add no_std support, by adding an std feature (#281)
To make the library work as `no_std` we add an `std` feature which
is on by default. When it is off, we compile as `no_std` and make
parts of the API that require `std::io` conditional on the `std`
feature.
2019-09-05 14:00:23 -07:00
Taiki EndoandGitHub 73426dfaa3 Fix one use of MaybeUninit (#291) 2019-09-01 01:33:10 +09:00
Ralf JungandCarl Lerche 425432ba6c use raw ptr for racy load and add comment (#289) 2019-08-28 14:41:04 -07:00
DoumanandCarl Lerche 4f5ed82b3c Fix clippy (#285) 2019-08-27 14:19:44 -07:00
Douman ae9991f3ba Make From only for static slices to Bytes 2019-08-27 22:17:26 +02:00
DoumanandCarl Lerche b6cb346adf Remove IntoBuf/FromBuf (#288)
As consequence Buf::collect is removed as well, which is replaced with `Buf::into_bytes`. The advantage of `Buf::into_bytes` is that it can be optimized in cases where converting a `T: Buf` into a `Bytes` instance is efficient.
2019-08-27 13:09:43 -07:00
nanpuyueandDouman 79e4b2847f use mem::MaybeUninit instead of mem::uninitialized 2019-08-16 15:49:37 +02:00
nanpuyueandDouman b1c17169d9 impl LowerHex/UpperHex for Bytes/BytesMut 2019-08-16 15:49:37 +02:00
DoumanandCarl Lerche 234d814122 Remove byteorder dependency (#280) 2019-08-11 10:16:03 -07:00
Taiki EndoandCarl Lerche b5d4f87e7e Remove i128 feature (#276) 2019-07-30 11:19:46 -07:00
Carl LercheandGitHub e07a949665 Set up CI with Azure Pipelines (#275) 2019-07-30 10:29:00 -07:00
Taiki EndoandGitHub ae7d884582 Update Bytes to Rust 2018 (#274) 2019-07-26 05:01:22 +09:00
Taiki EndoandCarl Lerche ecdde1a996 Update travis config to test on stable (#273) 2019-07-24 08:25:03 -07:00
Bruce MitchenerandSean McArthur e25b75a28e Fix typos. 2019-07-16 11:18:49 -07:00
Bruce MitchenerandSean McArthur 9b5e33d6f0 Remove merge conflict marker. 2019-07-16 11:18:49 -07:00
Sean McArthur dea868a4b0 Replace iovec with std::io::IoSlice
- Renames `bytes_vec` to `bytes_vectored` and `bytes_vec_mut` to
  `bytes_vectored_mut`.
2019-06-11 11:58:43 -07:00
Sean McArthur ac4e8f2fc5 Use RangeBounds trait for Bytes::slice
- Removes `slice_to` and `slice_from`.
2019-06-10 09:39:27 -07:00
Taiki EndoandSean McArthur ed7c7b5c58 Replace try! macro with ? operator 2019-06-10 09:05:11 -07:00
Sean McArthur 09772c4e77 fix benches after cursor removal 2019-06-07 15:09:06 -07:00
Sean McArthurandCarl Lerche 47fdf06e34 Make serde module private (#262) 2019-06-07 12:31:44 -07:00
Sean McArthurandCarl Lerche 55aa530dc1 Remove io::Cursor, and implement Buf/BufMut for slices instead (#261) 2019-06-07 12:31:10 -07:00
YetAnotherMinionandSean McArthur d8134903de feat: remove impl IntoBuf for Cursor<Self>, impl Buf for Bytes, BytesMut, refactor iterators 2019-06-06 16:59:44 -07:00
Sean McArthur 654a11c84c bump CI minimum Rust to 1.27 for 'dyn' keyword 2019-06-06 14:29:35 -07:00
Sean McArthur 5759211ff8 Merge branch 'v0.4.x' into uplift-0.4-commits 2019-06-06 14:08:29 -07:00
Sean McArthurandCarl Lerche 60aceba2bb set publish to false, update meta links (#258) 2019-06-06 13:58:22 -07:00
Pavel StrakhovandCarl Lerche d43e283e5e Panic in BytesMut::split_to when out of bounds (#252) (#253) 2019-04-02 16:24:30 -07:00
南浦月andCarl Lerche e0e30f00a1 Fix a typo in CHANGELOG.md (#251) 2019-03-29 13:54:25 -07:00
Carl LercheandGitHub 4948b1053b Bump version to v0.4.12 (#250) 2019-03-06 12:42:20 -08:00
Michal 'vorner' VanerandCarl Lerche 0e8b440650 Implementation of Buf for VecDeque (#249) 2019-03-06 11:46:42 -08:00
Sangguk LeeandCarl Lerche e13d2a783e Use constants in bytes.rs test code (#247) 2019-02-27 10:41:11 -08:00
南浦月andCarl Lerche 55dfea8c18 Impl FromIterator<&'a u8> for BytesMut/Bytes (#244) 2019-01-30 11:05:15 -08:00
Dax HuibertsandCarl Lerche f3b363a385 Fix typo in bytes.rs (#243) 2019-01-28 10:06:28 -08:00
Ralf JungandCarl Lerche 42b669690a use raw ptr for potentially racy load (#240) 2018-12-21 11:07:20 -08:00
Ralf JungandCarl Lerche 9504447adc Be clear about Inner::kind being deliberate UB (#236) 2018-11-25 22:49:35 -08:00
Carl LercheandGitHub b3248c8807 Bump version to v0.4.11 (#235) 2018-11-17 14:33:25 -08:00
Ralf JungandCarl Lerche c6c5b8fb54 Use raw pointers for potentially racy loads (#233)
Shared references assert immutability, so any concurrent access would be UB
disregarding data race concerns.
2018-11-17 07:51:50 -08:00
Michal 'vorner' VanerandCarl Lerche 7c3085aaec The Reader can implement BufReader naturally (#232)
There's no reason the user should be forced to wrap it in BufReader in
case the trait is needed, because the Reader has all the bits for
supporting it naturally.
2018-11-17 07:51:41 -08:00
Michal 'vorner' VanerandCarl Lerche e64a123d00 Bring more attention to short reads/slices on Buff/BuffMut (#231)
The property the Buff and BuffMut can return shorter slice is quite an
important detail. Nevertheless, while it is mentioned in the
documentation, the wording makes it relatively easy to overlook. This
tries to bring more attention to it.
2018-11-17 07:51:28 -08:00
Carl LercheandGitHub e5304410a4 Whitelist false positive std (#234) 2018-11-17 07:27:00 -08:00
Carl LercheandGitHub 456221d165 Bump version to v0.4.10 (#227) 2018-09-04 13:31:26 -07:00
Carl LercheandGitHub f09c51c34e White list allocation (#226) 2018-09-03 13:36:13 -07:00
Carl LercheandGitHub ad35fbef03 implement Buf and BufMut for Either (#225) 2018-09-03 10:23:00 -07:00
Federico Mena QuinteroandCarl Lerche 79f05591c9 Add a subslice function for Bytes (#198) (#208)
This lets us take Bytes and a &[u8] slice that is contained in it, and
create a new Bytes that corresponds to that subset slice.

Closes #198
2018-09-01 19:57:31 -07:00
Carl LercheandGitHub ed244d3b54 Bump version to v0.4.9 (#220) 2018-07-22 19:30:41 -07:00
Carl Lerche dc961c3e78 Merge branch 'v0.4.x' 2018-07-12 20:19:56 -07:00
Sean McArthurandCarl Lerche 890812af1b inline Bytes::len and Bytes::is_empty (#211) 2018-07-12 20:17:27 -07:00
Rafael Ávila de EspíndolaandCarl Lerche 052648c3f5 Implement IntoBuf for mut slices. (#214)
With this if foo is a mutable slice, it is possible to do

foo.into_buf().put_u32_le(42);

Before this patch into_buf would create a Cursor<&'a [u8]> and it
would not be possible to write into it.
2018-07-12 20:16:08 -07:00
RomanandCarl Lerche 042aa9023b Fix cargo doc error on nightly caused by broken link to footnote (#218) 2018-07-12 20:15:53 -07:00
Carl Lerche f4100841f8 Merge branch 'v0.4.x' 2018-07-12 20:11:51 -07:00
Sean McArthurandCarl Lerche cdfd25f314 inline Bytes::len and Bytes::is_empty (#211) 2018-07-12 19:05:35 -07:00
Geoffry SongandCarl Lerche 1ba5266bd9 Put type names in backticks. (#212)
I noticed that the bare `[u8]` made rustdoc nightly unhappy.
2018-07-12 19:05:02 -07:00
Rafael Ávila de EspíndolaandCarl Lerche 83f68a013e Implement IntoBuf for mut slices. (#214)
With this if foo is a mutable slice, it is possible to do

foo.into_buf().put_u32_le(42);

Before this patch into_buf would create a Cursor<&'a [u8]> and it
would not be possible to write into it.
2018-07-12 19:03:47 -07:00
RomanandCarl Lerche 63211d8c82 Fix cargo doc error on nightly caused by broken link to footnote (#218) 2018-07-05 10:13:01 -07:00
Sean McArthurandCarl Lerche 886dda0962 Optimize Inner::shallow_clone (#217)
- Clones when the kind is INLINE or STATIC are sped up by over double.
- Clones when the kind is ARC are spec up by about 1/3.
2018-07-03 15:21:26 -07:00
luben karavelovandCarl Lerche 6414efe83b Fix documentation (#219) 2018-07-02 12:10:16 -07:00
Ashley MannixandCarl Lerche 7785cde587 add support for 128bit numbers (#209) 2018-06-18 17:37:51 -07:00
Carl Lerche d98f49e67b Merge branch 'v0.4.x' 2018-06-18 12:52:00 -07:00
Carl LercheandGitHub a6b9844296 Clarify license as MIT (#216)
The intent of the license was to dual license MIT & Apache 2.0. However,
the messaging was copy / pasted from rust-lang.

Clarify the license as exclusively MIT.

Fixes #215
2018-06-18 12:49:34 -07:00
Carl Lerche 8d5b46cd10 Merge branch 'v0.4.x' 2018-05-25 16:56:31 -07:00
Carl LercheandGitHub 3557bafa5c Filter out tsan warnings in test harness (#205) 2018-05-25 15:32:39 -07:00
Carl Lerche c87739bb55 Merge branch 'v0.4.x' 2018-05-25 14:15:00 -07:00
Noah ZentzisandCarl Lerche 2d95683bd5 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 14:50:31 -07:00
Carl Lerche d656d37180 Merge branch 'v0.4.x' 2018-04-27 10:42:00 -07:00
kohensuandCarl Lerche e444722098 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:07:27 -07:00
kohensuandCarl Lerche d561006290 Add a bench for Buf::get_*() (#194) 2018-04-27 09:53:57 -07:00
Anthony RamineandCarl Lerche 2c27ddaf7e Introduce Bytes::to_mut (#188) 2018-03-12 09:51:10 -07:00
Alan SomersandCarl Lerche ae1b45495b impl BorrowMut for BytesMut (#185) 2018-03-12 09:46:16 -07:00
Carl Lerche ebe522731f Fix copy_to_slice to use correct increment var
This patch fixes the `copy_to_slice` function, rectifying the logic.
However, the incorrect code does not result in incorrect behavior as the
only case `cnt != src.len()` is during the final iteration, and since
`src.len()` is greater than `cnt` in that case, `off` will be
incremented by too much, but this will still trigger the `off <
dst.len()` condition.

The only danger is `src.len()` could cause an overflow.
2018-03-12 09:39:33 -07:00
Carl Lerche bd4630a321 Merge remote-tracking branch 'origin/v0.4.x' 2018-03-12 09:34:35 -07:00
Sean McArthurandCarl Lerche 025d53342e Remove ByteOrder generic methods from Buf and BufMut (#187)
* make Buf and BufMut usable as trait objects

- 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.

* remove deprecated ByteOrder methods

Removes the `_be` suffix from all methods, implying that the default
people should use is network endian.
2018-03-12 09:27:09 -07:00
Alan SomersandCarl Lerche ff7c0a1d90 Bytes::unsplit (#182)
Add `Bytes::unsplit`, analogous to `BytesMut::unsplit`.
2018-02-26 09:19:20 -08:00
Carl Lerche 4b68ef407f Merge remote-tracking branch 'origin/v0.4.x' 2018-01-29 10:19:05 -08:00
Carl Lerche 355a662976 Bump version 2018-01-29 09:40:45 -08:00
Carl LercheandGitHub 3d169f1f34 Update iovec dependency (#179)
Update to match master version of IoVec (0.2.0?), using
IoVec/IoVecMut instead of &IoVec and &mut IoVec.
2018-01-25 22:02:21 -08:00
Alan SomersandCarl Lerche c316c2433d Optionally disable inlining (#176)
Just document how `from(Vec<u8>)` can be used to disable inlining.
2018-01-14 21:53:07 -08:00
51 changed files with 4344 additions and 4388 deletions
-85
View File
@@ -1,85 +0,0 @@
---
dist: trusty
language: rust
services: docker
sudo: required
rust: stable
env:
global:
- CRATE_NAME=bytes
# Default job
- TARGET=x86_64-unknown-linux-gnu
- secure: "f17G5kb6uAQlAG9+GknFFYAmngGBqy9h+3FtNbp3mXTI0FOLltz00Ul5kGPysE4eagypm/dWOuvBkNjN01jhE6fCbekmInEsobIuanatrk6TvXT6caJqykxhPJC2cUoq8pKnMqEOuucEqPPUH6Qy6Hz4/2cRu5JV22Uv9dtS29Q="
matrix:
include:
# Run build on oldest supported rust version. Do not change the rust
# version without a Github issue first.
#
# This job will also build and deploy the docs to gh-pages.
- env: TARGET=x86_64-unknown-linux-gnu
rust: 1.15.0
after_success:
- |
pip install 'travis-cargo<0.2' --user &&
export PATH=$HOME/.local/bin:$PATH
- travis-cargo doc
- travis-cargo doc-upload
# Run tests on some extra platforms
- env: TARGET=i686-unknown-linux-gnu
- env: TARGET=armv7-unknown-linux-gnueabihf
- 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
install:
- sh ci/install.sh
- source ~/.cargo/env || true
script:
- bash ci/script.sh
after_script: set +e
before_deploy:
- sh ci/before_deploy.sh
cache: cargo
before_cache:
# Travis can't cache files that are not readable by "others"
- chmod -R a+r $HOME/.cargo
notifications:
email:
on_success: never
+65
View File
@@ -1,3 +1,68 @@
# 0.5.2 (November 27, 2019)
### Added
- `Limit` methods `into_inner`, `get_ref`, `get_mut`, `limit`, and `set_limit` (#325).
# 0.5.1 (November 25, 2019)
### Fix
- Growth documentation for `BytesMut` (#321)
# 0.5.0 (November 25, 2019)
### Fix
- Potential overflow in `copy_to_slice`
### Changed
- Increased minimum supported Rust version to 1.39.
- `Bytes` is now a "trait object", allowing for custom allocation strategies (#298)
- `BytesMut` implicitly grows internal storage. `remaining_mut()` returns
`usize::MAX` (#316).
- `BufMut::bytes_mut` returns `&mut [MaybeUninit<u8>]` to reflect the unknown
initialization state (#305).
- `Buf` / `BufMut` implementations for `&[u8]` and `&mut [u8]`
respectively (#261).
- Move `Buf` / `BufMut` "extra" functions to an extension trait (#306).
- `BufMutExt::limit` (#309).
- `Bytes::slice` takes a `RangeBounds` argument (#265).
- `Bytes::from_static` is now a `const fn` (#311).
- A multitude of smaller performance optimizations.
### Added
- `no_std` support (#281).
- `get_*`, `put_*`, `get_*_le`, and `put_*le` accessors for handling byte order.
- `BorrowMut` implementation for `BytesMut` (#185).
### Removed
- `IntoBuf` (#288).
- `Buf` implementation for `&str` (#301).
- `byteorder` dependency (#280).
- `iovec` dependency, use `std::IoSlice` instead (#263).
- optional `either` dependency (#315).
- optional `i128` feature -- now available on stable. (#276).
# 0.4.12 (March 6, 2019)
### Added
- Implement `FromIterator<&'a u8>` for `BytesMut`/`Bytes` (#244).
- Implement `Buf` for `VecDeque` (#249).
# 0.4.11 (November 17, 2018)
* Use raw pointers for potentially racy loads (#233).
* Implement `BufRead` for `buf::Reader` (#232).
* Documentation tweaks (#234).
# 0.4.10 (September 4, 2018)
* impl `Buf` and `BufMut` for `Either` (#225).
* Add `Bytes::slice_ref` (#208).
# 0.4.9 (July 12, 2018)
* Add 128 bit number support behind a feature flag (#209).
* Implement `IntoBuf` for `&mut [u8]`
# 0.4.8 (May 25, 2018)
* Fix panic in `BytesMut` `FromIterator` implementation.
+20 -19
View File
@@ -1,28 +1,29 @@
[package]
name = "bytes"
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"
homepage = "https://github.com/carllerche/bytes"
repository = "https://github.com/carllerche/bytes"
readme = "README.md"
keywords = ["buffers", "zero-copy", "io"]
exclude = [
".gitignore",
".travis.yml",
"deploy.sh",
"bench/**/*",
"test/**/*"
]
name = "bytes"
# When releasing to crates.io:
# - Update html_root_url.
# - Update CHANGELOG.md.
# - Update doc URL.
# - Create "v0.5.x" git tag.
version = "0.5.2"
license = "MIT"
authors = ["Carl Lerche <[email protected]>"]
description = "Types and traits for working with bytes"
documentation = "https://docs.rs/bytes"
repository = "https://github.com/tokio-rs/bytes"
readme = "README.md"
keywords = ["buffers", "zero-copy", "io"]
categories = ["network-programming", "data-structures"]
edition = "2018"
[features]
default = ["std"]
std = []
[dependencies]
byteorder = "1.0.0"
iovec = "0.1"
serde = { version = "1.0", optional = true }
[dev-dependencies]
loom = "0.2.10"
serde_test = "1.0"
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2017 Carl Lerche
Copyright (c) 2018 Carl Lerche
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
-201
View File
@@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2017 Carl Lerche
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+18 -12
View File
@@ -2,10 +2,15 @@
A utility library for working with bytes.
[![Crates.io](https://img.shields.io/crates/v/bytes.svg?maxAge=2592000)](https://crates.io/crates/bytes)
[![Build Status](https://travis-ci.org/carllerche/bytes.svg?branch=master)](https://travis-ci.org/carllerche/bytes)
[![Crates.io][crates-badge]][crates-url]
[![Build Status][azure-badge]][azure-url]
[Documentation](https://carllerche.github.io/bytes/bytes/index.html)
[crates-badge]: https://img.shields.io/crates/v/bytes.svg
[crates-url]: https://crates.io/crates/bytes
[azure-badge]: https://dev.azure.com/tokio-rs/bytes/_apis/build/status/tokio-rs.bytes?branchName=master
[azure-url]: https://dev.azure.com/tokio-rs/bytes/_build/latest?definitionId=3&branchName=master
[Documentation](https://docs.rs/bytes)
## Usage
@@ -13,14 +18,12 @@ To use `bytes`, first add this to your `Cargo.toml`:
```toml
[dependencies]
bytes = "0.4"
bytes = "0.5"
```
Next, add this to your crate:
```rust
extern crate bytes;
use bytes::{Bytes, BytesMut, Buf, BufMut};
```
@@ -30,13 +33,16 @@ Serde support is optional and disabled by default. To enable use the feature `se
```toml
[dependencies]
bytes = { version = "0.4", features = ["serde"] }
bytes = { version = "0.5", features = ["serde"] }
```
# License
## License
`bytes` is primarily distributed under the terms of both the MIT license and the
Apache License (Version 2.0), with portions covered by various BSD-like
licenses.
This project is licensed under the [MIT license](LICENSE).
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in `bytes` by you, shall be licensed as MIT, without any additional
terms or conditions.
See LICENSE-APACHE, and LICENSE-MIT for details.
+68
View File
@@ -0,0 +1,68 @@
trigger: ["master"]
pr: ["master"]
jobs:
# Check formatting
# - template: ci/azure-rustfmt.yml
# parameters:
# name: rustfmt
# Apply clippy lints
# - template: ci/azure-clippy.yml
# parameters:
# name: clippy
# This represents the minimum Rust version supported by
# Bytes. Updating this should be done in a dedicated PR.
#
# Tests are not run as tests may require newer versions of
# rust.
- template: ci/azure-test-stable.yml
parameters:
name: minrust
rust_version: 1.39.0
cmd: check
# Stable
- template: ci/azure-test-stable.yml
parameters:
name: stable
cross: true
features:
- serde
# Nightly
- template: ci/azure-test-stable.yml
parameters:
name: nightly
# Pin nightly to avoid being impacted by breakage
rust_version: nightly-2019-09-25
benches: true
# Run tests on some extra platforms
- template: ci/azure-cross-compile.yml
parameters:
name: cross
# Sanitizers
- template: ci/azure-tsan.yml
parameters:
name: tsan
rust_version: nightly
# Loom
- template: ci/azure-loom.yml
parameters:
name: loom
rust_version: stable
- template: ci/azure-deploy-docs.yml
parameters:
dependsOn:
# - rustfmt
# - clippy
- stable
- nightly
- minrust
- cross
+187
View File
@@ -0,0 +1,187 @@
#![feature(test)]
#![deny(warnings, rust_2018_idioms)]
extern crate test;
use test::Bencher;
use bytes::Buf;
/// Dummy Buf implementation
struct TestBuf {
buf: &'static [u8],
readlens: &'static [usize],
init_pos: usize,
pos: usize,
readlen_pos: usize,
readlen: usize,
}
impl TestBuf {
fn new(buf: &'static [u8], readlens: &'static [usize], init_pos: usize) -> TestBuf {
let mut buf = TestBuf {
buf,
readlens,
init_pos,
pos: 0,
readlen_pos: 0,
readlen: 0,
};
buf.reset();
buf
}
fn reset(&mut self) {
self.pos = self.init_pos;
self.readlen_pos = 0;
self.next_readlen();
}
/// Compute the length of the next read :
/// - use the next value specified in readlens (capped by remaining) if any
/// - else the remaining
fn next_readlen(&mut self) {
self.readlen = self.buf.len() - self.pos;
if let Some(readlen) = self.readlens.get(self.readlen_pos) {
self.readlen = std::cmp::min(self.readlen, *readlen);
self.readlen_pos += 1;
}
}
}
impl Buf for TestBuf {
fn remaining(&self) -> usize {
return self.buf.len() - self.pos;
}
fn advance(&mut self, cnt: usize) {
self.pos += cnt;
assert!(self.pos <= self.buf.len());
self.next_readlen();
}
fn bytes(&self) -> &[u8] {
if self.readlen == 0 {
Default::default()
} else {
&self.buf[self.pos..self.pos + self.readlen]
}
}
}
/// Dummy Buf implementation
/// version with methods forced to not be inlined (to simulate costly calls)
struct TestBufC {
inner: TestBuf,
}
impl TestBufC {
fn new(buf: &'static [u8], readlens: &'static [usize], init_pos: usize) -> TestBufC {
TestBufC {
inner: TestBuf::new(buf, readlens, init_pos),
}
}
fn reset(&mut self) {
self.inner.reset()
}
}
impl Buf for TestBufC {
#[inline(never)]
fn remaining(&self) -> usize {
self.inner.remaining()
}
#[inline(never)]
fn advance(&mut self, cnt: usize) {
self.inner.advance(cnt)
}
#[inline(never)]
fn bytes(&self) -> &[u8] {
self.inner.bytes()
}
}
macro_rules! bench {
($fname:ident, testbuf $testbuf:ident $readlens:expr, $method:ident $(,$arg:expr)*) => (
#[bench]
fn $fname(b: &mut Bencher) {
let mut bufs = [
$testbuf::new(&[1u8; 8+0], $readlens, 0),
$testbuf::new(&[1u8; 8+1], $readlens, 1),
$testbuf::new(&[1u8; 8+2], $readlens, 2),
$testbuf::new(&[1u8; 8+3], $readlens, 3),
$testbuf::new(&[1u8; 8+4], $readlens, 4),
$testbuf::new(&[1u8; 8+5], $readlens, 5),
$testbuf::new(&[1u8; 8+6], $readlens, 6),
$testbuf::new(&[1u8; 8+7], $readlens, 7),
];
b.iter(|| {
for i in 0..8 {
bufs[i].reset();
let buf: &mut dyn Buf = &mut bufs[i]; // type erasure
test::black_box(buf.$method($($arg,)*));
}
})
}
);
($fname:ident, slice, $method:ident $(,$arg:expr)*) => (
#[bench]
fn $fname(b: &mut Bencher) {
// buf must be long enough for one read of 8 bytes starting at pos 7
let arr = [1u8; 8+7];
b.iter(|| {
for i in 0..8 {
let mut buf = &arr[i..];
let buf = &mut buf as &mut dyn Buf; // type erasure
test::black_box(buf.$method($($arg,)*));
}
})
}
);
($fname:ident, option) => (
#[bench]
fn $fname(b: &mut Bencher) {
let data = [1u8; 1];
b.iter(|| {
for _ in 0..8 {
let mut buf = Some(data);
let buf = &mut buf as &mut dyn Buf; // type erasure
test::black_box(buf.get_u8());
}
})
}
);
}
macro_rules! bench_group {
($method:ident $(,$arg:expr)*) => (
bench!(slice, slice, $method $(,$arg)*);
bench!(tbuf_1, testbuf TestBuf &[], $method $(,$arg)*);
bench!(tbuf_1_costly, testbuf TestBufC &[], $method $(,$arg)*);
bench!(tbuf_2, testbuf TestBuf &[1], $method $(,$arg)*);
bench!(tbuf_2_costly, testbuf TestBufC &[1], $method $(,$arg)*);
// bench!(tbuf_onebyone, testbuf TestBuf &[1,1,1,1,1,1,1,1], $method $(,$arg)*);
// bench!(tbuf_onebyone_costly, testbuf TestBufC &[1,1,1,1,1,1,1,1], $method $(,$arg)*);
);
}
mod get_u8 {
use super::*;
bench_group!(get_u8);
bench!(option, option);
}
mod get_u16 {
use super::*;
bench_group!(get_u16);
}
mod get_u32 {
use super::*;
bench_group!(get_u32);
}
mod get_u64 {
use super::*;
bench_group!(get_u64);
}
mod get_f32 {
use super::*;
bench_group!(get_f32);
}
mod get_f64 {
use super::*;
bench_group!(get_f64);
}
mod get_uint24 {
use super::*;
bench_group!(get_uint, 3);
}
+84 -183
View File
@@ -1,31 +1,107 @@
#![feature(test)]
#![deny(warnings, rust_2018_idioms)]
extern crate bytes;
extern crate test;
use test::Bencher;
use bytes::{Bytes, BytesMut, BufMut};
use bytes::Bytes;
#[bench]
fn alloc_small(b: &mut Bencher) {
fn deref_unique(b: &mut Bencher) {
let buf = Bytes::from(vec![0; 1024]);
b.iter(|| {
for _ in 0..1024 {
test::black_box(BytesMut::with_capacity(12));
test::black_box(&buf[..]);
}
})
}
#[bench]
fn alloc_mid(b: &mut Bencher) {
fn deref_shared(b: &mut Bencher) {
let buf = Bytes::from(vec![0; 1024]);
let _b2 = buf.clone();
b.iter(|| {
test::black_box(BytesMut::with_capacity(128));
for _ in 0..1024 {
test::black_box(&buf[..]);
}
})
}
#[bench]
fn alloc_big(b: &mut Bencher) {
fn deref_static(b: &mut Bencher) {
let buf = Bytes::from_static(b"hello world");
b.iter(|| {
test::black_box(BytesMut::with_capacity(4096));
for _ in 0..1024 {
test::black_box(&buf[..]);
}
})
}
#[bench]
fn clone_static(b: &mut Bencher) {
let bytes = Bytes::from_static("hello world 1234567890 and have a good byte 0987654321".as_bytes());
b.iter(|| {
for _ in 0..1024 {
test::black_box(&bytes.clone());
}
})
}
#[bench]
fn clone_shared(b: &mut Bencher) {
let bytes = Bytes::from(b"hello world 1234567890 and have a good byte 0987654321".to_vec());
b.iter(|| {
for _ in 0..1024 {
test::black_box(&bytes.clone());
}
})
}
#[bench]
fn clone_arc_vec(b: &mut Bencher) {
use std::sync::Arc;
let bytes = Arc::new(b"hello world 1234567890 and have a good byte 0987654321".to_vec());
b.iter(|| {
for _ in 0..1024 {
test::black_box(&bytes.clone());
}
})
}
#[bench]
fn from_long_slice(b: &mut Bencher) {
let data = [0u8; 128];
b.bytes = data.len() as u64;
b.iter(|| {
let buf = Bytes::copy_from_slice(&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));
}
})
}
@@ -40,178 +116,3 @@ fn split_off_and_drop(b: &mut Bencher) {
}
})
}
#[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));
}
})
}
+249
View File
@@ -0,0 +1,249 @@
#![feature(test)]
#![deny(warnings, rust_2018_idioms)]
extern crate test;
use test::Bencher;
use bytes::{BufMut, BytesMut};
#[bench]
fn alloc_small(b: &mut Bencher) {
b.iter(|| {
for _ in 0..1024 {
test::black_box(BytesMut::with_capacity(12));
}
})
}
#[bench]
fn alloc_mid(b: &mut Bencher) {
b.iter(|| {
test::black_box(BytesMut::with_capacity(128));
})
}
#[bench]
fn alloc_big(b: &mut Bencher) {
b.iter(|| {
test::black_box(BytesMut::with_capacity(4096));
})
}
#[bench]
fn deref_unique(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(4096);
buf.put(&[0u8; 1024][..]);
b.iter(|| {
for _ in 0..1024 {
test::black_box(&buf[..]);
}
})
}
#[bench]
fn deref_unique_unroll(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(4096);
buf.put(&[0u8; 1024][..]);
b.iter(|| {
for _ in 0..128 {
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
test::black_box(&buf[..]);
}
})
}
#[bench]
fn deref_shared(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(4096);
buf.put(&[0u8; 1024][..]);
let _b2 = buf.split_off(1024);
b.iter(|| {
for _ in 0..1024 {
test::black_box(&buf[..]);
}
})
}
#[bench]
fn deref_two(b: &mut Bencher) {
let mut buf1 = BytesMut::with_capacity(8);
buf1.put(&[0u8; 8][..]);
let mut buf2 = BytesMut::with_capacity(4096);
buf2.put(&[0u8; 1024][..]);
b.iter(|| {
for _ in 0..512 {
test::black_box(&buf1[..]);
test::black_box(&buf2[..]);
}
})
}
#[bench]
fn clone_frozen(b: &mut Bencher) {
let bytes = BytesMut::from(&b"hello world 1234567890 and have a good byte 0987654321"[..]).split().freeze();
b.iter(|| {
for _ in 0..1024 {
test::black_box(&bytes.clone());
}
})
}
#[bench]
fn alloc_write_split_to_mid(b: &mut Bencher) {
b.iter(|| {
let mut buf = BytesMut::with_capacity(128);
buf.put_slice(&[0u8; 64]);
test::black_box(buf.split_to(64));
})
}
#[bench]
fn drain_write_drain(b: &mut Bencher) {
let data = [0u8; 128];
b.iter(|| {
let mut buf = BytesMut::with_capacity(1024);
let mut parts = Vec::with_capacity(8);
for _ in 0..8 {
buf.put(&data[..]);
parts.push(buf.split_to(128));
}
test::black_box(parts);
})
}
#[bench]
fn fmt_write(b: &mut Bencher) {
use std::fmt::Write;
let mut buf = BytesMut::with_capacity(128);
let s = "foo bar baz quux lorem ipsum dolor et";
b.bytes = s.len() as u64;
b.iter(|| {
let _ = write!(buf, "{}", s);
test::black_box(&buf);
unsafe { buf.set_len(0); }
})
}
#[bench]
fn bytes_mut_extend(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(256);
let data = [33u8; 32];
b.bytes = data.len() as u64 * 4;
b.iter(|| {
for _ in 0..4 {
buf.extend(&data);
}
test::black_box(&buf);
unsafe { buf.set_len(0); }
});
}
// BufMut for BytesMut vs Vec<u8>
#[bench]
fn put_slice_bytes_mut(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(256);
let data = [33u8; 32];
b.bytes = data.len() as u64 * 4;
b.iter(|| {
for _ in 0..4 {
buf.put_slice(&data);
}
test::black_box(&buf);
unsafe { buf.set_len(0); }
});
}
#[bench]
fn put_u8_bytes_mut(b: &mut Bencher) {
let mut buf = BytesMut::with_capacity(256);
let cnt = 128;
b.bytes = cnt as u64;
b.iter(|| {
for _ in 0..cnt {
buf.put_u8(b'x');
}
test::black_box(&buf);
unsafe { buf.set_len(0); }
});
}
#[bench]
fn put_slice_vec(b: &mut Bencher) {
let mut buf = Vec::<u8>::with_capacity(256);
let data = [33u8; 32];
b.bytes = data.len() as u64 * 4;
b.iter(|| {
for _ in 0..4 {
buf.put_slice(&data);
}
test::black_box(&buf);
unsafe { buf.set_len(0); }
});
}
#[bench]
fn put_u8_vec(b: &mut Bencher) {
let mut buf = Vec::<u8>::with_capacity(256);
let cnt = 128;
b.bytes = cnt as u64;
b.iter(|| {
for _ in 0..cnt {
buf.put_u8(b'x');
}
test::black_box(&buf);
unsafe { buf.set_len(0); }
});
}
#[bench]
fn put_slice_vec_extend(b: &mut Bencher) {
let mut buf = Vec::<u8>::with_capacity(256);
let data = [33u8; 32];
b.bytes = data.len() as u64 * 4;
b.iter(|| {
for _ in 0..4 {
buf.extend_from_slice(&data);
}
test::black_box(&buf);
unsafe { buf.set_len(0); }
});
}
#[bench]
fn put_u8_vec_push(b: &mut Bencher) {
let mut buf = Vec::<u8>::with_capacity(256);
let cnt = 128;
b.bytes = cnt as u64;
b.iter(|| {
for _ in 0..cnt {
buf.push(b'x');
}
test::black_box(&buf);
unsafe { buf.set_len(0); }
});
}
+46
View File
@@ -0,0 +1,46 @@
parameters:
cmd: build
rust_version: stable
jobs:
- job: ${{ parameters.name }}
displayName: Cross
strategy:
matrix:
i686:
vmImage: ubuntu-16.04
target: i686-unknown-linux-gnu
armv7:
vmImage: ubuntu-16.04
target: armv7-unknown-linux-gnueabihf
powerpc:
vmImage: ubuntu-16.04
target: powerpc-unknown-linux-gnu
powerpc64:
vmImage: ubuntu-16.04
target: powerpc64-unknown-linux-gnu
wasm:
vmImage: ubuntu-16.04
target: wasm32-unknown-unknown
pool:
vmImage: $(vmImage)
steps:
- template: azure-install-rust.yml
parameters:
rust_version: ${{parameters.rust_version}}
- script: cargo install cross
displayName: Install cross
condition: not(eq(variables['target'], 'wasm32-unknown-unknown'))
- script: cross ${{ parameters.cmd }} --target $(target)
displayName: cross ${{ parameters.cmd }} --target $(target)
condition: not(eq(variables['target'], 'wasm32-unknown-unknown'))
# WASM support
- script: |
rustup target add $(target)
cargo build --target $(target)
displayName: cargo build --target $(target)
condition: eq(variables['target'], 'wasm32-unknown-unknown')
+39
View File
@@ -0,0 +1,39 @@
parameters:
dependsOn: []
jobs:
- job: documentation
displayName: 'Deploy API Documentation'
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
pool:
vmImage: 'Ubuntu 16.04'
dependsOn:
- ${{ parameters.dependsOn }}
steps:
- template: azure-install-rust.yml
parameters:
rust_version: stable
- script: |
cargo doc --no-deps
cp -R target/doc '$(Build.BinariesDirectory)'
displayName: 'Generate Documentation'
- script: |
set -e
git --version
ls -la
git init
git config user.name 'Deployment Bot (from Azure Pipelines)'
git config user.email '[email protected]'
git config --global credential.helper 'store --file ~/.my-credentials'
printf "protocol=https\nhost=github.com\nusername=carllerche\npassword=%s\n\n" "$GITHUB_TOKEN" | git credential-store --file ~/.my-credentials store
git remote add origin https://github.com/tokio-rs/bytes
git checkout -b gh-pages
git add .
git commit -m 'Deploy Bytes API documentation'
git push -f origin gh-pages
env:
GITHUB_TOKEN: $(githubPersonalToken)
workingDirectory: '$(Build.BinariesDirectory)'
displayName: 'Deploy Documentation'
+33
View File
@@ -0,0 +1,33 @@
steps:
# Linux and macOS.
- script: |
set -e
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
export PATH=$PATH:$HOME/.cargo/bin
rustup toolchain install $RUSTUP_TOOLCHAIN
rustup default $RUSTUP_TOOLCHAIN
echo "##vso[task.setvariable variable=PATH;]$PATH:$HOME/.cargo/bin"
env:
RUSTUP_TOOLCHAIN: ${{parameters.rust_version}}
displayName: "Install rust (*nix)"
condition: not(eq(variables['Agent.OS'], 'Windows_NT'))
# Windows.
- script: |
curl -sSf -o rustup-init.exe https://win.rustup.rs
rustup-init.exe -y --default-toolchain none
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
rustup toolchain install %RUSTUP_TOOLCHAIN%
rustup default %RUSTUP_TOOLCHAIN%
echo "##vso[task.setvariable variable=PATH;]%PATH%;%USERPROFILE%\.cargo\bin"
env:
RUSTUP_TOOLCHAIN: ${{parameters.rust_version}}
displayName: "Install rust (windows)"
condition: eq(variables['Agent.OS'], 'Windows_NT')
# All platforms.
- script: |
rustup toolchain list
rustc -Vv
cargo -V
displayName: Query rust and cargo versions
+15
View File
@@ -0,0 +1,15 @@
jobs:
- job: ${{parameters.name}}
displayName: Loom tests
pool:
vmImage: ubuntu-16.04
steps:
- template: azure-install-rust.yml
parameters:
rust_version: ${{parameters.rust_version}}
- script: RUSTFLAGS="--cfg loom" cargo test --lib
displayName: RUSTFLAGS="--cfg loom" cargo test --lib
+50
View File
@@ -0,0 +1,50 @@
parameters:
cmd: test
rust_version: stable
features: []
jobs:
- job: ${{ parameters.name }}
displayName: ${{ parameters.displayName }}
strategy:
matrix:
Linux:
vmImage: ubuntu-16.04
${{ if parameters.cross }}:
MacOS:
vmImage: macOS-10.13
Windows:
vmImage: vs2017-win2016
pool:
vmImage: $(vmImage)
steps:
- template: azure-install-rust.yml
parameters:
rust_version: ${{parameters.rust_version}}
# Run with default crate features
- script: cargo ${{ parameters.cmd }}
displayName: cargo ${{ parameters.cmd }}
# Run with each specified feature
- ${{ each feature in parameters.features }}:
- script: cargo ${{ parameters.cmd }} --features ${{ feature }}
displayName: cargo ${{ parameters.cmd }} --features ${{ feature }}
- ${{ if eq(parameters.cmd, 'test') }}:
- script: cargo doc --no-deps
displayName: cargo doc --no-deps
- ${{ if parameters.benches }}:
- script: cargo check --benches
displayName: Check benchmarks
# Run with all features
- script: cargo ${{ parameters.cmd }} --all-features
displayName: cargo ${{ parameters.cmd }} --all-features
# Run with no default features
- script: cargo check --no-default-features
displayName: cargo check --no-default-features
+26
View File
@@ -0,0 +1,26 @@
jobs:
- job: ${{ parameters.name }}
displayName: TSAN
pool:
vmImage: ubuntu-16.04
steps:
- template: azure-install-rust.yml
parameters:
rust_version: ${{ parameters.rust_version }}
- script: |
set -e
export RUST_TEST_THREADS=1
export ASAN_OPTIONS="detect_odr_violation=0 detect_leaks=0"
export TSAN_OPTIONS="suppressions=`pwd`/ci/tsan"
# Run address sanitizer
RUSTFLAGS="-Z sanitizer=address" \
cargo test --target x86_64-unknown-linux-gnu --test test_bytes --test test_buf --test test_buf_mut
# Run thread sanitizer
RUSTFLAGS="-Z sanitizer=thread" \
cargo test --target x86_64-unknown-linux-gnu --test test_bytes --test test_buf --test test_buf_mut
displayName: TSAN / MSAN
-23
View File
@@ -1,23 +0,0 @@
# This script takes care of packaging the build artifacts that will go in the
# release zipfile
$SRC_DIR = $PWD.Path
$STAGE = [System.Guid]::NewGuid().ToString()
Set-Location $ENV:Temp
New-Item -Type Directory -Name $STAGE
Set-Location $STAGE
$ZIP = "$SRC_DIR\$($Env:CRATE_NAME)-$($Env:APPVEYOR_REPO_TAG_NAME)-$($Env:TARGET).zip"
# TODO Update this to package the right artifacts
Copy-Item "$SRC_DIR\target\$($Env:TARGET)\release\hello.exe" '.\'
7z a "$ZIP" *
Push-AppveyorArtifact "$ZIP"
Remove-Item *.* -Force
Set-Location ..
Remove-Item $STAGE
Set-Location $SRC_DIR
-33
View File
@@ -1,33 +0,0 @@
# This script takes care of building your crate and packaging it for release
set -ex
main() {
local src=$(pwd) \
stage=
case $TRAVIS_OS_NAME in
linux)
stage=$(mktemp -d)
;;
osx)
stage=$(mktemp -d -t tmp)
;;
esac
test -f Cargo.lock || cargo generate-lockfile
# TODO Update this to build the artifacts that matter to you
cross rustc --bin hello --target $TARGET --release -- -C lto
# TODO Update this to package the right artifacts
cp target/$TARGET/release/hello $stage/
cd $stage
tar czf $src/$CRATE_NAME-$TRAVIS_TAG-$TARGET.tar.gz *
cd $src
rm -rf $stage
}
main
-31
View File
@@ -1,31 +0,0 @@
set -ex
main() {
curl https://sh.rustup.rs -sSf | \
sh -s -- -y --default-toolchain $TRAVIS_RUST_VERSION
local target=
if [ $TRAVIS_OS_NAME = linux ]; then
target=x86_64-unknown-linux-gnu
sort=sort
else
target=x86_64-apple-darwin
sort=gsort # for `sort --sort-version`, from brew's coreutils.
fi
# This fetches latest stable release
local tag=$(git ls-remote --tags --refs --exit-code https://github.com/japaric/cross \
| cut -d/ -f3 \
| grep -E '^v[0-9.]+$' \
| $sort --version-sort \
| tail -n1)
echo cross version: $tag
curl -LSfs https://japaric.github.io/trust/install.sh | \
sh -s -- \
--force \
--git japaric/cross \
--tag $tag \
--target $target
}
main
-18
View File
@@ -1,18 +0,0 @@
# This script takes care of testing your crate
set -ex
main() {
cross build --target $TARGET $EXTRA_ARGS
if [ ! -z $DISABLE_TESTS ]; then
return
fi
cross test --target $TARGET $EXTRA_ARGS
}
# we don't run the "test phase" when doing deploys
if [ -z $TRAVIS_TAG ]; then
main
fi
+6 -3
View File
@@ -9,6 +9,9 @@ race:arc*Weak*drop
# rust runtime logic.
race:std*mpsc_queue
# Some test runtime races. Allocation should be race free
race:alloc::alloc
# Not sure why this is warning, but it is in the test harness and not the library.
race:TestEvent*clone
race:test::run_tests_console::*closure
@@ -16,6 +19,6 @@ 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
# This ignores a false positive caused by `thread::park()`/`thread::unpark()`.
# See: https://github.com/rust-lang/rust/pull/54806#issuecomment-436193353
race:pthread_cond_destroy
File diff suppressed because it is too large Load Diff
+238 -288
View File
@@ -1,8 +1,9 @@
use super::{IntoBuf, Writer};
use byteorder::{LittleEndian, ByteOrder, BigEndian};
use iovec::IoVec;
use core::{cmp, mem::{self, MaybeUninit}, ptr, usize};
use std::{cmp, io, ptr, usize};
#[cfg(feature = "std")]
use std::fmt;
use alloc::{vec::Vec, boxed::Box};
/// A trait for values that provide sequential write access to bytes.
///
@@ -20,7 +21,7 @@ use std::{cmp, io, ptr, usize};
///
/// let mut buf = vec![];
///
/// buf.put("hello world");
/// buf.put(&b"hello world"[..]);
///
/// assert_eq!(buf, b"hello world");
/// ```
@@ -35,15 +36,14 @@ pub trait BufMut {
///
/// ```
/// use bytes::BufMut;
/// use std::io::Cursor;
///
/// let mut dst = [0; 10];
/// let mut buf = Cursor::new(&mut dst[..]);
/// let mut buf = &mut dst[..];
///
/// assert_eq!(10, buf.remaining_mut());
/// buf.put("hello");
/// let original_remaining = buf.remaining_mut();
/// buf.put(&b"hello"[..]);
///
/// assert_eq!(5, buf.remaining_mut());
/// assert_eq!(original_remaining - 5, buf.remaining_mut());
/// ```
///
/// # Implementer notes
@@ -69,13 +69,15 @@ pub trait BufMut {
/// let mut buf = Vec::with_capacity(16);
///
/// unsafe {
/// buf.bytes_mut()[0] = b'h';
/// buf.bytes_mut()[1] = b'e';
/// // MaybeUninit::as_mut_ptr
/// buf.bytes_mut()[0].as_mut_ptr().write(b'h');
/// buf.bytes_mut()[1].as_mut_ptr().write(b'e');
///
/// buf.advance_mut(2);
///
/// buf.bytes_mut()[0] = b'l';
/// buf.bytes_mut()[1..3].copy_from_slice(b"lo");
/// buf.bytes_mut()[0].as_mut_ptr().write(b'l');
/// buf.bytes_mut()[1].as_mut_ptr().write(b'l');
/// buf.bytes_mut()[2].as_mut_ptr().write(b'o');
///
/// buf.advance_mut(3);
/// }
@@ -105,14 +107,13 @@ pub trait BufMut {
///
/// ```
/// use bytes::BufMut;
/// use std::io::Cursor;
///
/// let mut dst = [0; 5];
/// let mut buf = Cursor::new(&mut dst);
/// let mut buf = &mut dst[..];
///
/// assert!(buf.has_remaining_mut());
///
/// buf.put("hello");
/// buf.put(&b"hello"[..]);
///
/// assert!(!buf.has_remaining_mut());
/// ```
@@ -121,7 +122,8 @@ pub trait BufMut {
}
/// Returns a mutable slice starting at the current BufMut position and of
/// length between 0 and `BufMut::remaining_mut()`.
/// length between 0 and `BufMut::remaining_mut()`. Note that this *can* be shorter than the
/// whole remainder of the buffer (this allows non-continuous implementation).
///
/// This is a lower level function. Most operations are done with other
/// functions.
@@ -136,13 +138,15 @@ pub trait BufMut {
/// let mut buf = Vec::with_capacity(16);
///
/// unsafe {
/// buf.bytes_mut()[0] = b'h';
/// buf.bytes_mut()[1] = b'e';
/// // MaybeUninit::as_mut_ptr
/// buf.bytes_mut()[0].as_mut_ptr().write(b'h');
/// buf.bytes_mut()[1].as_mut_ptr().write(b'e');
///
/// buf.advance_mut(2);
///
/// buf.bytes_mut()[0] = b'l';
/// buf.bytes_mut()[1..3].copy_from_slice(b"lo");
/// buf.bytes_mut()[0].as_mut_ptr().write(b'l');
/// buf.bytes_mut()[1].as_mut_ptr().write(b'l');
/// buf.bytes_mut()[2].as_mut_ptr().write(b'o');
///
/// buf.advance_mut(3);
/// }
@@ -158,20 +162,20 @@ pub trait BufMut {
/// `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];
fn bytes_mut(&mut self) -> &mut [MaybeUninit<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`
/// If the `BufMut` is backed by disjoint slices of bytes, `bytes_vectored_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
/// mutable `IoSliceMut` 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
/// the slices **will not** be modified. If `bytes_vectored_mut` does not fill every
/// entry in `dst`, then `dst` is guaranteed to contain all remaining slices
/// in `self.
///
@@ -181,20 +185,21 @@ 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_vec_mut` must
/// i.e., `BufMut::remaining_mut` returns 0, calls to `bytes_vectored_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 {
#[cfg(feature = "std")]
fn bytes_vectored_mut<'a>(&'a mut self, dst: &mut [IoSliceMut<'a>]) -> usize {
if dst.is_empty() {
return 0;
}
if self.has_remaining_mut() {
dst[0] = self.bytes_mut().into();
dst[0] = IoSliceMut::from(self.bytes_mut());
1
} else {
0
@@ -211,9 +216,9 @@ pub trait BufMut {
///
/// let mut buf = vec![];
///
/// buf.put(b'h');
/// buf.put_u8(b'h');
/// buf.put(&b"ello"[..]);
/// buf.put(" world");
/// buf.put(&b" world"[..]);
///
/// assert_eq!(buf, b"hello world");
/// ```
@@ -221,11 +226,7 @@ pub trait BufMut {
/// # 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();
fn put<T: super::Buf>(&mut self, mut src: T) where Self: Sized {
assert!(self.remaining_mut() >= src.remaining());
while src.has_remaining() {
@@ -238,7 +239,7 @@ pub trait BufMut {
ptr::copy_nonoverlapping(
s.as_ptr(),
d.as_mut_ptr(),
d.as_mut_ptr() as *mut u8,
l);
}
@@ -254,12 +255,11 @@ pub trait BufMut {
///
/// ```
/// use bytes::BufMut;
/// use std::io::Cursor;
///
/// let mut dst = [0; 6];
///
/// {
/// let mut buf = Cursor::new(&mut dst);
/// let mut buf = &mut dst[..];
/// buf.put_slice(b"hello");
///
/// assert_eq!(1, buf.remaining_mut());
@@ -270,7 +270,7 @@ pub trait BufMut {
fn put_slice(&mut self, src: &[u8]) {
let mut off = 0;
assert!(self.remaining_mut() >= src.len(), "buffer overflow");
assert!(self.remaining_mut() >= src.len(), "buffer overflow; remaining = {}; src = {}", self.remaining_mut(), src.len());
while off < src.len() {
let cnt;
@@ -281,7 +281,7 @@ pub trait BufMut {
ptr::copy_nonoverlapping(
src[off..].as_ptr(),
dst.as_mut_ptr(),
dst.as_mut_ptr() as *mut u8,
cnt);
off += cnt;
@@ -338,14 +338,6 @@ pub trait BufMut {
self.put_slice(&src)
}
#[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 an unsigned 16 bit integer to `self` in big-endian byte order.
///
/// The current position is advanced by 2.
@@ -356,7 +348,7 @@ pub trait BufMut {
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_u16_be(0x0809);
/// buf.put_u16(0x0809);
/// assert_eq!(buf, b"\x08\x09");
/// ```
///
@@ -364,10 +356,8 @@ pub trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_u16_be(&mut self, n: u16) {
let mut buf = [0; 2];
BigEndian::write_u16(&mut buf, n);
self.put_slice(&buf)
fn put_u16(&mut self, n: u16) {
self.put_slice(&n.to_be_bytes())
}
/// Writes an unsigned 16 bit integer to `self` in little-endian byte order.
@@ -389,17 +379,7 @@ pub trait BufMut {
/// 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)
self.put_slice(&n.to_le_bytes())
}
/// Writes a signed 16 bit integer to `self` in big-endian byte order.
@@ -412,7 +392,7 @@ pub trait BufMut {
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_i16_be(0x0809);
/// buf.put_i16(0x0809);
/// assert_eq!(buf, b"\x08\x09");
/// ```
///
@@ -420,10 +400,8 @@ pub trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_i16_be(&mut self, n: i16) {
let mut buf = [0; 2];
BigEndian::write_i16(&mut buf, n);
self.put_slice(&buf)
fn put_i16(&mut self, n: i16) {
self.put_slice(&n.to_be_bytes())
}
/// Writes a signed 16 bit integer to `self` in little-endian byte order.
@@ -445,17 +423,7 @@ pub trait BufMut {
/// 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)
self.put_slice(&n.to_le_bytes())
}
/// Writes an unsigned 32 bit integer to `self` in big-endian byte order.
@@ -468,7 +436,7 @@ pub trait BufMut {
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_u32_be(0x0809A0A1);
/// buf.put_u32(0x0809A0A1);
/// assert_eq!(buf, b"\x08\x09\xA0\xA1");
/// ```
///
@@ -476,10 +444,8 @@ pub trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_u32_be(&mut self, n: u32) {
let mut buf = [0; 4];
BigEndian::write_u32(&mut buf, n);
self.put_slice(&buf)
fn put_u32(&mut self, n: u32) {
self.put_slice(&n.to_be_bytes())
}
/// Writes an unsigned 32 bit integer to `self` in little-endian byte order.
@@ -501,17 +467,7 @@ pub trait BufMut {
/// 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)
self.put_slice(&n.to_le_bytes())
}
/// Writes a signed 32 bit integer to `self` in big-endian byte order.
@@ -524,7 +480,7 @@ pub trait BufMut {
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_i32_be(0x0809A0A1);
/// buf.put_i32(0x0809A0A1);
/// assert_eq!(buf, b"\x08\x09\xA0\xA1");
/// ```
///
@@ -532,10 +488,8 @@ pub trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_i32_be(&mut self, n: i32) {
let mut buf = [0; 4];
BigEndian::write_i32(&mut buf, n);
self.put_slice(&buf)
fn put_i32(&mut self, n: i32) {
self.put_slice(&n.to_be_bytes())
}
/// Writes a signed 32 bit integer to `self` in little-endian byte order.
@@ -557,17 +511,7 @@ pub trait BufMut {
/// 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)
self.put_slice(&n.to_le_bytes())
}
/// Writes an unsigned 64 bit integer to `self` in the big-endian byte order.
@@ -580,7 +524,7 @@ pub trait BufMut {
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_u64_be(0x0102030405060708);
/// buf.put_u64(0x0102030405060708);
/// assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08");
/// ```
///
@@ -588,10 +532,8 @@ pub trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_u64_be(&mut self, n: u64) {
let mut buf = [0; 8];
BigEndian::write_u64(&mut buf, n);
self.put_slice(&buf)
fn put_u64(&mut self, n: u64) {
self.put_slice(&n.to_be_bytes())
}
/// Writes an unsigned 64 bit integer to `self` in little-endian byte order.
@@ -613,17 +555,7 @@ pub trait BufMut {
/// 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)
self.put_slice(&n.to_le_bytes())
}
/// Writes a signed 64 bit integer to `self` in the big-endian byte order.
@@ -636,7 +568,7 @@ pub trait BufMut {
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_i64_be(0x0102030405060708);
/// buf.put_i64(0x0102030405060708);
/// assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08");
/// ```
///
@@ -644,10 +576,8 @@ pub trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_i64_be(&mut self, n: i64) {
let mut buf = [0; 8];
BigEndian::write_i64(&mut buf, n);
self.put_slice(&buf)
fn put_i64(&mut self, n: i64) {
self.put_slice(&n.to_be_bytes())
}
/// Writes a signed 64 bit integer to `self` in little-endian byte order.
@@ -669,17 +599,95 @@ pub trait BufMut {
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_i64_le(&mut self, n: i64) {
let mut buf = [0; 8];
LittleEndian::write_i64(&mut buf, n);
self.put_slice(&buf)
self.put_slice(&n.to_le_bytes())
}
#[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 128 bit integer to `self` in the big-endian byte order.
///
/// The current position is advanced by 16.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_u128(0x01020304050607080910111213141516);
/// assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_u128(&mut self, n: u128) {
self.put_slice(&n.to_be_bytes())
}
/// Writes an unsigned 128 bit integer to `self` in little-endian byte order.
///
/// The current position is advanced by 16.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_u128_le(0x01020304050607080910111213141516);
/// assert_eq!(buf, b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_u128_le(&mut self, n: u128) {
self.put_slice(&n.to_le_bytes())
}
/// Writes a signed 128 bit integer to `self` in the big-endian byte order.
///
/// The current position is advanced by 16.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_i128(0x01020304050607080910111213141516);
/// assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_i128(&mut self, n: i128) {
self.put_slice(&n.to_be_bytes())
}
/// Writes a signed 128 bit integer to `self` in little-endian byte order.
///
/// The current position is advanced by 16.
///
/// # Examples
///
/// ```
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_i128_le(0x01020304050607080910111213141516);
/// assert_eq!(buf, b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01");
/// ```
///
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_i128_le(&mut self, n: i128) {
self.put_slice(&n.to_le_bytes())
}
/// Writes an unsigned n-byte integer to `self` in big-endian byte order.
@@ -692,7 +700,7 @@ pub trait BufMut {
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_uint_be(0x010203, 3);
/// buf.put_uint(0x010203, 3);
/// assert_eq!(buf, b"\x01\x02\x03");
/// ```
///
@@ -700,10 +708,8 @@ pub trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_uint_be(&mut self, n: u64, nbytes: usize) {
let mut buf = [0; 8];
BigEndian::write_uint(&mut buf, n, nbytes);
self.put_slice(&buf[0..nbytes])
fn put_uint(&mut self, n: u64, nbytes: usize) {
self.put_slice(&n.to_be_bytes()[mem::size_of_val(&n) - nbytes..]);
}
/// Writes an unsigned n-byte integer to `self` in the little-endian byte order.
@@ -725,17 +731,7 @@ pub trait BufMut {
/// 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])
self.put_slice(&n.to_le_bytes()[0..nbytes]);
}
/// Writes a signed n-byte integer to `self` in big-endian byte order.
@@ -748,7 +744,7 @@ pub trait BufMut {
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_int_be(0x010203, 3);
/// buf.put_int(0x010203, 3);
/// assert_eq!(buf, b"\x01\x02\x03");
/// ```
///
@@ -756,10 +752,8 @@ pub trait BufMut {
///
/// 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])
fn put_int(&mut self, n: i64, nbytes: usize) {
self.put_slice(&n.to_be_bytes()[mem::size_of_val(&n) - nbytes..]);
}
/// Writes a signed n-byte integer to `self` in little-endian byte order.
@@ -781,17 +775,7 @@ pub trait BufMut {
/// 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)
self.put_slice(&n.to_le_bytes()[0..nbytes]);
}
/// Writes an IEEE754 single-precision (4 bytes) floating point number to
@@ -805,7 +789,7 @@ pub trait BufMut {
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_f32_be(1.2f32);
/// buf.put_f32(1.2f32);
/// assert_eq!(buf, b"\x3F\x99\x99\x9A");
/// ```
///
@@ -813,10 +797,8 @@ pub trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_f32_be(&mut self, n: f32) {
let mut buf = [0; 4];
BigEndian::write_f32(&mut buf, n);
self.put_slice(&buf)
fn put_f32(&mut self, n: f32) {
self.put_u32(n.to_bits());
}
/// Writes an IEEE754 single-precision (4 bytes) floating point number to
@@ -839,17 +821,7 @@ pub trait BufMut {
/// 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)
self.put_u32_le(n.to_bits());
}
/// Writes an IEEE754 double-precision (8 bytes) floating point number to
@@ -863,7 +835,7 @@ pub trait BufMut {
/// use bytes::BufMut;
///
/// let mut buf = vec![];
/// buf.put_f64_be(1.2f64);
/// buf.put_f64(1.2f64);
/// assert_eq!(buf, b"\x3F\xF3\x33\x33\x33\x33\x33\x33");
/// ```
///
@@ -871,10 +843,8 @@ pub trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_f64_be(&mut self, n: f64) {
let mut buf = [0; 8];
BigEndian::write_f64(&mut buf, n);
self.put_slice(&buf)
fn put_f64(&mut self, n: f64) {
self.put_u64(n.to_bits());
}
/// Writes an IEEE754 double-precision (8 bytes) floating point number to
@@ -897,78 +867,22 @@ pub trait BufMut {
/// 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)
}
/// 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)
self.put_u64_le(n.to_bits());
}
}
impl<'a, T: BufMut + ?Sized> BufMut for &'a mut T {
impl<T: BufMut + ?Sized> BufMut for &mut T {
fn remaining_mut(&self) -> usize {
(**self).remaining_mut()
}
unsafe fn bytes_mut(&mut self) -> &mut [u8] {
fn bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
(**self).bytes_mut()
}
unsafe fn bytes_vec_mut<'b>(&'b mut self, dst: &mut [&'b mut IoVec]) -> usize {
(**self).bytes_vec_mut(dst)
#[cfg(feature = "std")]
fn bytes_vectored_mut<'b>(&'b mut self, dst: &mut [IoSliceMut<'b>]) -> usize {
(**self).bytes_vectored_mut(dst)
}
unsafe fn advance_mut(&mut self, cnt: usize) {
@@ -981,12 +895,13 @@ impl<T: BufMut + ?Sized> BufMut for Box<T> {
(**self).remaining_mut()
}
unsafe fn bytes_mut(&mut self) -> &mut [u8] {
fn bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
(**self).bytes_mut()
}
unsafe fn bytes_vec_mut<'b>(&'b mut self, dst: &mut [&'b mut IoVec]) -> usize {
(**self).bytes_vec_mut(dst)
#[cfg(feature = "std")]
fn bytes_vectored_mut<'b>(&'b mut self, dst: &mut [IoSliceMut<'b>]) -> usize {
(**self).bytes_vectored_mut(dst)
}
unsafe fn advance_mut(&mut self, cnt: usize) {
@@ -994,31 +909,23 @@ impl<T: BufMut + ?Sized> BufMut for Box<T> {
}
}
impl<T: AsMut<[u8]> + AsRef<[u8]>> BufMut for io::Cursor<T> {
impl BufMut for &mut [u8] {
#[inline]
fn remaining_mut(&self) -> usize {
use Buf;
self.remaining()
self.len()
}
/// Advance the internal cursor of the BufMut
#[inline]
fn bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
// MaybeUninit is repr(transparent), so safe to transmute
unsafe { mem::transmute(&mut **self) }
}
#[inline]
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..]
// Lifetime dance taken from `impl Write for &mut [u8]`.
let (_, b) = core::mem::replace(self, &mut []).split_at_mut(cnt);
*self = b;
}
}
@@ -1042,8 +949,8 @@ impl BufMut for Vec<u8> {
}
#[inline]
unsafe fn bytes_mut(&mut self) -> &mut [u8] {
use std::slice;
fn bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
use core::slice;
if self.capacity() == self.len() {
self.reserve(64); // Grow the vec
@@ -1052,11 +959,54 @@ impl BufMut for Vec<u8> {
let cap = self.capacity();
let len = self.len();
let ptr = self.as_mut_ptr();
&mut slice::from_raw_parts_mut(ptr, cap)[len..]
let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
unsafe {
&mut slice::from_raw_parts_mut(ptr, cap)[len..]
}
}
}
// The existance of this function makes the compiler catch if the BufMut
// The existence of this function makes the compiler catch if the BufMut
// trait is "object-safe" or not.
fn _assert_trait_object(_b: &BufMut) {}
fn _assert_trait_object(_b: &dyn BufMut) {}
// ===== impl IoSliceMut =====
/// A buffer type used for `readv`.
///
/// This is a wrapper around an `std::io::IoSliceMut`, but does not expose
/// the inner bytes in a safe API, as they may point at uninitialized memory.
///
/// This is `repr(transparent)` of the `std::io::IoSliceMut`, so it is valid to
/// transmute them. However, as the memory might be uninitialized, care must be
/// taken to not *read* the internal bytes, only *write* to them.
#[repr(transparent)]
#[cfg(feature = "std")]
pub struct IoSliceMut<'a>(std::io::IoSliceMut<'a>);
#[cfg(feature = "std")]
impl fmt::Debug for IoSliceMut<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("IoSliceMut")
.field("len", &self.0.len())
.finish()
}
}
#[cfg(feature = "std")]
impl<'a> From<&'a mut [u8]> for IoSliceMut<'a> {
fn from(buf: &'a mut [u8]) -> IoSliceMut<'a> {
IoSliceMut(std::io::IoSliceMut::new(buf))
}
}
#[cfg(feature = "std")]
impl<'a> From<&'a mut [MaybeUninit<u8>]> for IoSliceMut<'a> {
fn from(buf: &'a mut [MaybeUninit<u8>]) -> IoSliceMut<'a> {
IoSliceMut(std::io::IoSliceMut::new(unsafe {
// We don't look at the contents, and `std::io::IoSliceMut`
// doesn't either.
mem::transmute::<&'a mut [MaybeUninit<u8>], &'a mut [u8]>(buf)
}))
}
}
+64 -56
View File
@@ -1,10 +1,17 @@
use {Buf, BufMut};
use iovec::IoVec;
use crate::{Buf, BufMut};
use crate::buf::IntoIter;
use core::mem::MaybeUninit;
#[cfg(feature = "std")]
use std::io::{IoSlice};
#[cfg(feature = "std")]
use crate::buf::IoSliceMut;
/// A `Chain` sequences two buffers.
///
/// `Chain` is an adapter that links two underlying buffers and provides a
/// continous view across both buffers. It is able to sequence either immutable
/// continuous view across both buffers. It is able to sequence either immutable
/// buffers ([`Buf`] values) or mutable buffers ([`BufMut`] values).
///
/// This struct is generally created by calling [`Buf::chain`]. Please see that
@@ -13,13 +20,12 @@ use iovec::IoVec;
/// # Examples
///
/// ```
/// use bytes::{Bytes, Buf, IntoBuf};
/// use bytes::buf::Chain;
/// use bytes::{Bytes, Buf, buf::BufExt};
///
/// let buf = Bytes::from(&b"hello "[..]).into_buf()
/// .chain(Bytes::from(&b"world"[..]));
/// let mut buf = (&b"hello "[..])
/// .chain(&b"world"[..]);
///
/// let full: Bytes = buf.collect();
/// let full: Bytes = buf.to_bytes();
/// assert_eq!(full[..], b"hello world"[..]);
/// ```
///
@@ -34,23 +40,10 @@ pub struct Chain<T, 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,
a,
b,
}
}
@@ -59,12 +52,12 @@ impl<T, U> Chain<T, U> {
/// # Examples
///
/// ```
/// use bytes::{Bytes, Buf, IntoBuf};
/// use bytes::buf::BufExt;
///
/// let buf = Bytes::from(&b"hello"[..]).into_buf()
/// .chain(Bytes::from(&b"world"[..]));
/// let buf = (&b"hello"[..])
/// .chain(&b"world"[..]);
///
/// assert_eq!(buf.first_ref().get_ref()[..], b"hello"[..]);
/// assert_eq!(buf.first_ref()[..], b"hello"[..]);
/// ```
pub fn first_ref(&self) -> &T {
&self.a
@@ -75,15 +68,15 @@ impl<T, U> Chain<T, U> {
/// # Examples
///
/// ```
/// use bytes::{Bytes, Buf, IntoBuf};
/// use bytes::{Buf, buf::BufExt};
///
/// let mut buf = Bytes::from(&b"hello "[..]).into_buf()
/// .chain(Bytes::from(&b"world"[..]));
/// let mut buf = (&b"hello"[..])
/// .chain(&b"world"[..]);
///
/// buf.first_mut().set_position(1);
/// buf.first_mut().advance(1);
///
/// let full: Bytes = buf.collect();
/// assert_eq!(full[..], b"ello world"[..]);
/// let full = buf.to_bytes();
/// assert_eq!(full, b"elloworld"[..]);
/// ```
pub fn first_mut(&mut self) -> &mut T {
&mut self.a
@@ -94,12 +87,12 @@ impl<T, U> Chain<T, U> {
/// # Examples
///
/// ```
/// use bytes::{Bytes, Buf, IntoBuf};
/// use bytes::buf::BufExt;
///
/// let buf = Bytes::from(&b"hello"[..]).into_buf()
/// .chain(Bytes::from(&b"world"[..]));
/// let buf = (&b"hello"[..])
/// .chain(&b"world"[..]);
///
/// assert_eq!(buf.last_ref().get_ref()[..], b"world"[..]);
/// assert_eq!(buf.last_ref()[..], b"world"[..]);
/// ```
pub fn last_ref(&self) -> &U {
&self.b
@@ -110,15 +103,15 @@ impl<T, U> Chain<T, U> {
/// # Examples
///
/// ```
/// use bytes::{Bytes, Buf, IntoBuf};
/// use bytes::{Buf, buf::BufExt};
///
/// let mut buf = Bytes::from(&b"hello "[..]).into_buf()
/// .chain(Bytes::from(&b"world"[..]));
/// let mut buf = (&b"hello "[..])
/// .chain(&b"world"[..]);
///
/// buf.last_mut().set_position(1);
/// buf.last_mut().advance(1);
///
/// let full: Bytes = buf.collect();
/// assert_eq!(full[..], b"hello orld"[..]);
/// let full = buf.to_bytes();
/// assert_eq!(full, b"hello orld"[..]);
/// ```
pub fn last_mut(&mut self) -> &mut U {
&mut self.b
@@ -129,14 +122,14 @@ impl<T, U> Chain<T, U> {
/// # Examples
///
/// ```
/// use bytes::{Bytes, Buf, IntoBuf};
/// use bytes::buf::BufExt;
///
/// let buf = Bytes::from(&b"hello"[..]).into_buf()
/// .chain(Bytes::from(&b"world"[..]));
/// let chain = (&b"hello"[..])
/// .chain(&b"world"[..]);
///
/// let (first, last) = buf.into_inner();
/// assert_eq!(first.get_ref()[..], b"hello"[..]);
/// assert_eq!(last.get_ref()[..], b"world"[..]);
/// let (first, last) = chain.into_inner();
/// assert_eq!(first[..], b"hello"[..]);
/// assert_eq!(last[..], b"world"[..]);
/// ```
pub fn into_inner(self) -> (T, U) {
(self.a, self.b)
@@ -177,9 +170,10 @@ impl<T, U> Buf for Chain<T, U>
self.b.advance(cnt);
}
fn bytes_vec<'a>(&'a self, dst: &mut [&'a IoVec]) -> usize {
let mut n = self.a.bytes_vec(dst);
n += self.b.bytes_vec(&mut dst[n..]);
#[cfg(feature = "std")]
fn bytes_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize {
let mut n = self.a.bytes_vectored(dst);
n += self.b.bytes_vectored(&mut dst[n..]);
n
}
}
@@ -192,7 +186,7 @@ impl<T, U> BufMut for Chain<T, U>
self.a.remaining_mut() + self.b.remaining_mut()
}
unsafe fn bytes_mut(&mut self) -> &mut [u8] {
fn bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
if self.a.has_remaining_mut() {
self.a.bytes_mut()
} else {
@@ -218,9 +212,23 @@ impl<T, U> BufMut for Chain<T, U>
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..]);
#[cfg(feature = "std")]
fn bytes_vectored_mut<'a>(&'a mut self, dst: &mut [IoSliceMut<'a>]) -> usize {
let mut n = self.a.bytes_vectored_mut(dst);
n += self.b.bytes_vectored_mut(&mut dst[n..]);
n
}
}
impl<T, U> IntoIterator for Chain<T, U>
where
T: Buf,
U: Buf,
{
type Item = u8;
type IntoIter = IntoIter<Chain<T, U>>;
fn into_iter(self) -> Self::IntoIter {
IntoIter::new(self)
}
}
+77
View File
@@ -0,0 +1,77 @@
use crate::BufMut;
use core::{cmp, mem::MaybeUninit};
/// A `BufMut` adapter which limits the amount of bytes that can be written
/// to an underlying buffer.
#[derive(Debug)]
pub struct Limit<T> {
inner: T,
limit: usize,
}
pub(super) fn new<T>(inner: T, limit: usize) -> Limit<T> {
Limit {
inner,
limit,
}
}
impl<T> Limit<T> {
/// Consumes this `Limit`, returning the underlying value.
pub fn into_inner(self) -> T {
self.inner
}
/// Gets a reference to the underlying `BufMut`.
///
/// It is inadvisable to directly write to the underlying `BufMut`.
pub fn get_ref(&self) -> &T {
&self.inner
}
/// Gets a mutable reference to the underlying `BufMut`.
///
/// It is inadvisable to directly write to the underlying `BufMut`.
pub fn get_mut(&mut self) -> &mut T {
&mut self.inner
}
/// Returns the maximum number of bytes that can be written
///
/// # Note
///
/// If the inner `BufMut` has fewer bytes than indicated by this method then
/// that is the actual number of available bytes.
pub fn limit(&self) -> usize {
self.limit
}
/// Sets the maximum number of bytes that can be written.
///
/// # Note
///
/// If the inner `BufMut` has fewer bytes than `lim` then that is the actual
/// number of available bytes.
pub fn set_limit(&mut self, lim: usize) {
self.limit = lim
}
}
impl<T: BufMut> BufMut for Limit<T> {
fn remaining_mut(&self) -> usize {
cmp::min(self.inner.remaining_mut(), self.limit)
}
fn bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
let bytes = self.inner.bytes_mut();
let end = cmp::min(bytes.len(), self.limit);
&mut bytes[..end]
}
unsafe fn advance_mut(&mut self, cnt: usize) {
assert!(cnt <= self.limit);
self.inner.advance_mut(cnt);
self.limit -= cnt;
}
}
+176
View File
@@ -0,0 +1,176 @@
//! Extra utilities for `Buf` and `BufMut` types.
use super::{Buf, BufMut};
mod chain;
mod limit;
#[cfg(feature = "std")]
mod reader;
mod take;
#[cfg(feature = "std")]
mod writer;
pub use self::limit::Limit;
pub use self::take::Take;
pub use self::chain::Chain;
#[cfg(feature = "std")]
pub use self::{reader::Reader, writer::Writer};
/// Extra methods for implementations of `Buf`.
pub trait BufExt: Buf {
/// 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, buf::BufExt};
///
/// let mut buf = b"hello world"[..].take(5);
/// let mut dst = vec![];
///
/// dst.put(&mut buf);
/// assert_eq!(dst, b"hello");
///
/// let mut buf = buf.into_inner();
/// dst.clear();
/// dst.put(&mut buf);
/// assert_eq!(dst, b" world");
/// ```
fn take(self, limit: usize) -> Take<Self>
where Self: Sized
{
take::new(self, limit)
}
/// Creates an adaptor which will chain this buffer with another.
///
/// The returned `Buf` instance will first consume all bytes from `self`.
/// Afterwards the output is equivalent to the output of next.
///
/// # Examples
///
/// ```
/// use bytes::{Buf, buf::BufExt};
///
/// let mut chain = b"hello "[..].chain(&b"world"[..]);
///
/// let full = chain.to_bytes();
/// assert_eq!(full.bytes(), b"hello world");
/// ```
fn chain<U: Buf>(self, next: U) -> Chain<Self, U>
where Self: Sized
{
Chain::new(self, next)
}
/// Creates an adaptor which implements the `Read` trait for `self`.
///
/// This function returns a new value which implements `Read` by adapting
/// the `Read` trait functions to the `Buf` trait functions. Given that
/// `Buf` operations are infallible, none of the `Read` functions will
/// return with `Err`.
///
/// # Examples
///
/// ```
/// use bytes::{Buf, Bytes, buf::BufExt};
/// use std::io::Read;
///
/// let buf = Bytes::from("hello world");
///
/// let mut reader = buf.reader();
/// let mut dst = [0; 1024];
///
/// let num = reader.read(&mut dst).unwrap();
///
/// assert_eq!(11, num);
/// assert_eq!(&dst[..11], &b"hello world"[..]);
/// ```
#[cfg(feature = "std")]
fn reader(self) -> Reader<Self> where Self: Sized {
reader::new(self)
}
}
impl<B: Buf + ?Sized> BufExt for B {}
/// Extra methods for implementations of `BufMut`.
pub trait BufMutExt: BufMut {
/// Creates an adaptor which can write at most `limit` bytes to `self`.
///
/// # Examples
///
/// ```
/// use bytes::{BufMut, buf::BufMutExt};
///
/// let arr = &mut [0u8; 128][..];
/// assert_eq!(arr.remaining_mut(), 128);
///
/// let dst = arr.limit(10);
/// assert_eq!(dst.remaining_mut(), 10);
/// ```
fn limit(self, limit: usize) -> Limit<Self>
where Self: Sized
{
limit::new(self, limit)
}
/// 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, buf::BufMutExt};
/// 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"[..]);
/// ```
#[cfg(feature = "std")]
fn writer(self) -> Writer<Self> where Self: Sized {
writer::new(self)
}
/// Creates an adapter which will chain this buffer with another.
///
/// The returned `BufMut` instance will first write to all bytes from
/// `self`. Afterwards, it will write to `next`.
///
/// # Examples
///
/// ```
/// use bytes::{BufMut, buf::BufMutExt};
///
/// let mut a = [0u8; 5];
/// let mut b = [0u8; 6];
///
/// let mut chain = (&mut a[..]).chain_mut(&mut b[..]);
///
/// chain.put_slice(b"hello world");
///
/// assert_eq!(&a[..], b"hello");
/// assert_eq!(&b[..], b" world");
/// ```
fn chain_mut<U: BufMut>(self, next: U) -> Chain<Self, U>
where Self: Sized
{
Chain::new(self, next)
}
}
impl<B: BufMut + ?Sized> BufMutExt for B {}
+17 -24
View File
@@ -1,4 +1,4 @@
use {Buf};
use crate::{Buf};
use std::{cmp, io};
@@ -13,7 +13,7 @@ pub struct Reader<B> {
}
pub fn new<B>(buf: B) -> Reader<B> {
Reader { buf: buf }
Reader { buf }
}
impl<B: Buf> Reader<B> {
@@ -24,12 +24,11 @@ impl<B: Buf> Reader<B> {
/// # Examples
///
/// ```rust
/// use bytes::Buf;
/// use std::io::{self, Cursor};
/// use bytes::buf::BufExt;
///
/// let mut buf = Cursor::new(b"hello world").reader();
/// let mut buf = b"hello world".reader();
///
/// assert_eq!(0, buf.get_ref().position());
/// assert_eq!(b"hello world", buf.get_ref());
/// ```
pub fn get_ref(&self) -> &B {
&self.buf
@@ -38,21 +37,6 @@ impl<B: Buf> Reader<B> {
/// 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
}
@@ -62,10 +46,10 @@ impl<B: Buf> Reader<B> {
/// # Examples
///
/// ```rust
/// use bytes::Buf;
/// use std::io::{self, Cursor};
/// use bytes::{Buf, buf::BufExt};
/// use std::io;
///
/// let mut buf = Cursor::new(b"hello world").reader();
/// let mut buf = b"hello world".reader();
/// let mut dst = vec![];
///
/// io::copy(&mut buf, &mut dst).unwrap();
@@ -86,3 +70,12 @@ impl<B: Buf + Sized> io::Read for Reader<B> {
Ok(len)
}
}
impl<B: Buf + Sized> io::BufRead for Reader<B> {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
Ok(self.buf.bytes())
}
fn consume(&mut self, amt: usize) {
self.buf.advance(amt)
}
}
+16 -21
View File
@@ -1,6 +1,6 @@
use {Buf};
use crate::Buf;
use std::cmp;
use core::cmp;
/// A `Buf` adapter which limits the bytes read from an underlying buffer.
///
@@ -14,8 +14,8 @@ pub struct Take<T> {
pub fn new<T>(inner: T, limit: usize) -> Take<T> {
Take {
inner: inner,
limit: limit,
inner,
limit,
}
}
@@ -25,10 +25,9 @@ impl<T> Take<T> {
/// # Examples
///
/// ```rust
/// use bytes::{Buf, BufMut};
/// use std::io::Cursor;
/// use bytes::buf::{Buf, BufMut, BufExt};
///
/// let mut buf = Cursor::new(b"hello world").take(2);
/// let mut buf = b"hello world".take(2);
/// let mut dst = vec![];
///
/// dst.put(&mut buf);
@@ -51,12 +50,11 @@ impl<T> Take<T> {
/// # Examples
///
/// ```rust
/// use bytes::{Buf, BufMut};
/// use std::io::Cursor;
/// use bytes::{Buf, buf::BufExt};
///
/// let mut buf = Cursor::new(b"hello world").take(2);
/// let mut buf = b"hello world".take(2);
///
/// assert_eq!(0, buf.get_ref().position());
/// assert_eq!(11, buf.get_ref().remaining());
/// ```
pub fn get_ref(&self) -> &T {
&self.inner
@@ -69,13 +67,12 @@ impl<T> Take<T> {
/// # Examples
///
/// ```rust
/// use bytes::{Buf, BufMut};
/// use std::io::Cursor;
/// use bytes::{Buf, BufMut, buf::BufExt};
///
/// let mut buf = Cursor::new(b"hello world").take(2);
/// let mut buf = b"hello world".take(2);
/// let mut dst = vec![];
///
/// buf.get_mut().set_position(2);
/// buf.get_mut().advance(2);
///
/// dst.put(&mut buf);
/// assert_eq!(*dst, b"ll"[..]);
@@ -94,10 +91,9 @@ impl<T> Take<T> {
/// # Examples
///
/// ```rust
/// use bytes::Buf;
/// use std::io::Cursor;
/// use bytes::{Buf, buf::BufExt};
///
/// let mut buf = Cursor::new(b"hello world").take(2);
/// let mut buf = b"hello world".take(2);
///
/// assert_eq!(2, buf.limit());
/// assert_eq!(b'h', buf.get_u8());
@@ -117,10 +113,9 @@ impl<T> Take<T> {
/// # Examples
///
/// ```rust
/// use bytes::{Buf, BufMut};
/// use std::io::Cursor;
/// use bytes::{Buf, BufMut, buf::BufExt};
///
/// let mut buf = Cursor::new(b"hello world").take(2);
/// let mut buf = b"hello world".take(2);
/// let mut dst = vec![];
///
/// dst.put(&mut buf);
+7 -7
View File
@@ -1,4 +1,4 @@
use BufMut;
use crate::BufMut;
use std::{cmp, io};
@@ -13,7 +13,7 @@ pub struct Writer<B> {
}
pub fn new<B>(buf: B) -> Writer<B> {
Writer { buf: buf }
Writer { buf }
}
impl<B: BufMut> Writer<B> {
@@ -24,7 +24,7 @@ impl<B: BufMut> Writer<B> {
/// # Examples
///
/// ```rust
/// use bytes::BufMut;
/// use bytes::buf::BufMutExt;
///
/// let mut buf = Vec::with_capacity(1024).writer();
///
@@ -41,7 +41,7 @@ impl<B: BufMut> Writer<B> {
/// # Examples
///
/// ```rust
/// use bytes::BufMut;
/// use bytes::buf::BufMutExt;
///
/// let mut buf = vec![].writer();
///
@@ -58,11 +58,11 @@ impl<B: BufMut> Writer<B> {
/// # Examples
///
/// ```rust
/// use bytes::BufMut;
/// use std::io::{self, Cursor};
/// use bytes::buf::BufMutExt;
/// use std::io;
///
/// let mut buf = vec![].writer();
/// let mut src = Cursor::new(b"hello world");
/// let mut src = &b"hello world"[..];
///
/// io::copy(&mut src, &mut buf).unwrap();
///
-117
View File
@@ -1,117 +0,0 @@
use {Buf, BufMut, IntoBuf, Bytes, BytesMut};
/// Conversion from a [`Buf`]
///
/// Implementing `FromBuf` for a type defines how it is created from a buffer.
/// This is common for types which represent byte storage of some kind.
///
/// [`FromBuf::from_buf`] is rarely called explicitly, and it is instead used
/// through [`Buf::collect`]. See [`Buf::collect`] documentation for more examples.
///
/// See also [`IntoBuf`].
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use bytes::{Bytes, IntoBuf};
/// use bytes::buf::FromBuf;
///
/// let buf = Bytes::from(&b"hello world"[..]).into_buf();
/// let vec = Vec::from_buf(buf);
///
/// assert_eq!(vec, &b"hello world"[..]);
/// ```
///
/// Using [`Buf::collect`] to implicitly use `FromBuf`:
///
/// ```
/// use bytes::{Buf, Bytes, IntoBuf};
///
/// let buf = Bytes::from(&b"hello world"[..]).into_buf();
/// let vec: Vec<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
}
}
-138
View File
@@ -1,138 +0,0 @@
use super::{Buf};
use std::io;
/// Conversion into a `Buf`
///
/// An `IntoBuf` implementation defines how to convert a value into a `Buf`.
/// This is common for types that represent byte storage of some kind. `IntoBuf`
/// may be implemented directly for types or on references for those types.
///
/// # Examples
///
/// ```
/// use bytes::{Buf, IntoBuf, BigEndian};
///
/// let bytes = b"\x00\x01hello world";
/// let mut buf = bytes.into_buf();
///
/// assert_eq!(1, buf.get_u16::<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])
}
}
+40 -23
View File
@@ -1,4 +1,4 @@
use Buf;
use crate::Buf;
/// Iterator over the bytes contained by the buffer.
///
@@ -9,10 +9,10 @@ use Buf;
/// Basic usage:
///
/// ```
/// use bytes::{Buf, IntoBuf, Bytes};
/// use bytes::{Buf, Bytes};
///
/// let buf = Bytes::from(&b"abc"[..]).into_buf();
/// let mut iter = buf.iter();
/// let buf = Bytes::from(&b"abc"[..]);
/// let mut iter = buf.into_iter();
///
/// assert_eq!(iter.next(), Some(b'a'));
/// assert_eq!(iter.next(), Some(b'b'));
@@ -23,20 +23,39 @@ use Buf;
/// [`iter`]: trait.Buf.html#method.iter
/// [`Buf`]: trait.Buf.html
#[derive(Debug)]
pub struct Iter<T> {
pub struct IntoIter<T> {
inner: T,
}
impl<T> Iter<T> {
/// Consumes this `Iter`, returning the underlying value.
impl<T> IntoIter<T> {
/// Creates an iterator over the bytes contained by the buffer.
///
/// # Examples
///
/// ```
/// use bytes::{Buf, Bytes};
/// use bytes::buf::IntoIter;
///
/// let buf = Bytes::from_static(b"abc");
/// let mut iter = IntoIter::new(buf);
///
/// assert_eq!(iter.next(), Some(b'a'));
/// assert_eq!(iter.next(), Some(b'b'));
/// assert_eq!(iter.next(), Some(b'c'));
/// assert_eq!(iter.next(), None);
/// ```
pub fn new(inner: T) -> IntoIter<T> {
IntoIter { inner }
}
/// Consumes this `IntoIter`, returning the underlying value.
///
/// # Examples
///
/// ```rust
/// use bytes::{Buf, IntoBuf, Bytes};
/// use bytes::{Buf, Bytes};
///
/// let buf = Bytes::from(&b"abc"[..]).into_buf();
/// let mut iter = buf.iter();
/// let buf = Bytes::from(&b"abc"[..]);
/// let mut iter = buf.into_iter();
///
/// assert_eq!(iter.next(), Some(b'a'));
///
@@ -54,10 +73,10 @@ impl<T> Iter<T> {
/// # Examples
///
/// ```rust
/// use bytes::{Buf, IntoBuf, Bytes};
/// use bytes::{Buf, Bytes};
///
/// let buf = Bytes::from(&b"abc"[..]).into_buf();
/// let mut iter = buf.iter();
/// let buf = Bytes::from(&b"abc"[..]);
/// let mut iter = buf.into_iter();
///
/// assert_eq!(iter.next(), Some(b'a'));
///
@@ -74,27 +93,24 @@ impl<T> Iter<T> {
/// # Examples
///
/// ```rust
/// use bytes::{Buf, IntoBuf, BytesMut};
/// use bytes::{Buf, BytesMut};
///
/// let buf = BytesMut::from(&b"abc"[..]).into_buf();
/// let mut iter = buf.iter();
/// let buf = BytesMut::from(&b"abc"[..]);
/// let mut iter = buf.into_iter();
///
/// assert_eq!(iter.next(), Some(b'a'));
///
/// iter.get_mut().set_position(0);
/// iter.get_mut().advance(1);
///
/// assert_eq!(iter.next(), Some(b'a'));
/// assert_eq!(iter.next(), Some(b'c'));
/// ```
pub fn get_mut(&mut self) -> &mut T {
&mut self.inner
}
}
pub fn new<T>(inner: T) -> Iter<T> {
Iter { inner: inner }
}
impl<T: Buf> Iterator for Iter<T> {
impl<T: Buf> Iterator for IntoIter<T> {
type Item = u8;
fn next(&mut self) -> Option<u8> {
@@ -104,6 +120,7 @@ impl<T: Buf> Iterator for Iter<T> {
let b = self.inner.bytes()[0];
self.inner.advance(1);
Some(b)
}
@@ -113,4 +130,4 @@ impl<T: Buf> Iterator for Iter<T> {
}
}
impl<T: Buf> ExactSizeIterator for Iter<T> { }
impl<T: Buf> ExactSizeIterator for IntoIter<T> { }
+9 -15
View File
@@ -16,22 +16,16 @@
//! [`Buf`]: trait.Buf.html
//! [`BufMut`]: trait.BufMut.html
mod buf;
mod buf_impl;
mod buf_mut;
mod from_buf;
mod chain;
mod into_buf;
pub mod ext;
mod iter;
mod reader;
mod take;
mod writer;
mod vec_deque;
pub use self::buf::Buf;
pub use self::buf_impl::Buf;
pub use self::buf_mut::BufMut;
pub use self::from_buf::FromBuf;
pub use self::chain::Chain;
pub use self::into_buf::IntoBuf;
pub use self::iter::Iter;
pub use self::reader::Reader;
pub use self::take::Take;
pub use self::writer::Writer;
pub use self::ext::{BufExt, BufMutExt};
#[cfg(feature = "std")]
pub use self::buf_mut::IoSliceMut;
pub use self::iter::IntoIter;
+22
View File
@@ -0,0 +1,22 @@
use alloc::collections::VecDeque;
use super::Buf;
impl Buf for VecDeque<u8> {
fn remaining(&self) -> usize {
self.len()
}
fn bytes(&self) -> &[u8] {
let (s1, s2) = self.as_slices();
if s1.is_empty() {
s2
} else {
s1
}
}
fn advance(&mut self, cnt: usize) {
self.drain(..cnt);
}
}
+483 -2363
View File
File diff suppressed because it is too large Load Diff
+1464
View File
File diff suppressed because it is too large Load Diff
+12 -12
View File
@@ -1,4 +1,4 @@
use std::fmt;
use core::fmt;
/// Alternative implementation of `fmt::Debug` for byte slice.
///
@@ -12,29 +12,29 @@ use std::fmt;
/// `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\""));
impl fmt::Debug for BsDebug<'_> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(fmt, "b\"")?;
for &c in self.0 {
// https://doc.rust-lang.org/reference.html#byte-escapes
if c == b'\n' {
try!(write!(fmt, "\\n"));
write!(fmt, "\\n")?;
} else if c == b'\r' {
try!(write!(fmt, "\\r"));
write!(fmt, "\\r")?;
} else if c == b'\t' {
try!(write!(fmt, "\\t"));
write!(fmt, "\\t")?;
} else if c == b'\\' || c == b'"' {
try!(write!(fmt, "\\{}", c as char));
write!(fmt, "\\{}", c as char)?;
} else if c == b'\0' {
try!(write!(fmt, "\\0"));
write!(fmt, "\\0")?;
// ASCII printable
} else if c >= 0x20 && c < 0x7f {
try!(write!(fmt, "{}", c as char));
write!(fmt, "{}", c as char)?;
} else {
try!(write!(fmt, "\\x{:02x}", c));
write!(fmt, "\\x{:02x}", c)?;
}
}
try!(write!(fmt, "\""));
write!(fmt, "\"")?;
Ok(())
}
}
+37
View File
@@ -0,0 +1,37 @@
use crate::{Bytes, BytesMut};
use core::fmt::{Formatter, LowerHex, Result, UpperHex};
struct BytesRef<'a>(&'a [u8]);
impl<'a> LowerHex for BytesRef<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
for b in self.0 {
write!(f, "{:02x}", b)?;
}
Ok(())
}
}
impl<'a> UpperHex for BytesRef<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
for b in self.0 {
write!(f, "{:02X}", b)?;
}
Ok(())
}
}
macro_rules! hex_impl {
($tr:ident, $ty:ty) => {
impl $tr for $ty {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
$tr::fmt(&BytesRef(self.as_ref()), f)
}
}
};
}
hex_impl!(LowerHex, Bytes);
hex_impl!(LowerHex, BytesMut);
hex_impl!(UpperHex, Bytes);
hex_impl!(UpperHex, BytesMut);
+43 -26
View File
@@ -1,3 +1,7 @@
#![deny(warnings, missing_docs, missing_debug_implementations, rust_2018_idioms)]
#![doc(html_root_url = "https://docs.rs/bytes/0.5.2")]
#![no_std]
//! Provides abstractions for working with bytes.
//!
//! The `bytes` crate provides an efficient byte buffer structure
@@ -9,7 +13,7 @@
//!
//! # `Bytes`
//!
//! `Bytes` is an efficient container for storing and operating on continguous
//! `Bytes` is an efficient container for storing and operating on contiguous
//! slices of memory. It is intended for use primarily in networking code, but
//! could have applications elsewhere as well.
//!
@@ -18,23 +22,23 @@
//! using a reference count to track when the memory is no longer needed and can
//! be freed.
//!
//! A `Bytes` handle can be created directly from an existing byte store (such as &[u8]
//! or Vec<u8>), but usually a `BytesMut` is used first and written to. For
//! A `Bytes` handle can be created directly from an existing byte store (such as `&[u8]`
//! or `Vec<u8>`), but usually a `BytesMut` is used first and written to. For
//! example:
//!
//! ```rust
//! use bytes::{BytesMut, BufMut, BigEndian};
//! use bytes::{BytesMut, BufMut};
//!
//! let mut buf = BytesMut::with_capacity(1024);
//! buf.put(&b"hello world"[..]);
//! buf.put_u16::<BigEndian>(1234);
//! buf.put_u16(1234);
//!
//! let a = buf.take();
//! let a = buf.split();
//! assert_eq!(a, b"hello world\x04\xD2"[..]);
//!
//! buf.put(&b"goodbye world"[..]);
//!
//! let b = buf.take();
//! let b = buf.split();
//! assert_eq!(b, b"goodbye world"[..]);
//!
//! assert_eq!(buf.capacity(), 998);
@@ -68,34 +72,47 @@
//! 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.8")]
extern crate byteorder;
extern crate iovec;
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
pub mod buf;
pub use buf::{
pub use crate::buf::{
Buf,
BufMut,
IntoBuf,
};
#[deprecated(since = "0.4.1", note = "moved to `buf` module")]
#[doc(hidden)]
pub use buf::{
Reader,
Writer,
Take,
};
mod bytes_mut;
mod bytes;
mod debug;
pub use bytes::{Bytes, BytesMut};
#[deprecated]
pub use byteorder::{ByteOrder, BigEndian, LittleEndian};
mod hex;
mod loom;
pub use crate::bytes_mut::BytesMut;
pub use crate::bytes::Bytes;
// Optional Serde support
#[cfg(feature = "serde")]
#[doc(hidden)]
pub mod serde;
mod serde;
#[inline(never)]
#[cold]
fn abort() -> ! {
#[cfg(feature = "std")]
{
std::process::abort();
}
#[cfg(not(feature = "std"))]
{
struct Abort;
impl Drop for Abort {
fn drop(&mut self) {
panic!();
}
}
let _a = Abort;
panic!("abort");
}
}
+9
View File
@@ -0,0 +1,9 @@
#[cfg(not(all(test, loom)))]
pub(crate) mod sync {
pub(crate) mod atomic {
pub(crate) use core::sync::atomic::{fence, AtomicPtr, AtomicUsize, Ordering};
}
}
#[cfg(all(test, loom))]
pub(crate) use ::loom::sync;
+15 -15
View File
@@ -1,11 +1,11 @@
extern crate serde;
use std::{cmp, fmt};
use self::serde::{Serialize, Serializer, Deserialize, Deserializer, de};
use alloc::string::String;
use alloc::vec::Vec;
use core::{cmp, fmt};
use serde::{Serialize, Serializer, Deserialize, Deserializer, de};
use super::{Bytes, BytesMut};
macro_rules! serde_impl {
($ty:ident, $visitor_ty:ident) => (
($ty:ident, $visitor_ty:ident, $from_slice:ident, $from_vec:ident) => (
impl Serialize for $ty {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -20,7 +20,7 @@ macro_rules! serde_impl {
impl<'de> de::Visitor<'de> for $visitor_ty {
type Value = $ty;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("byte array")
}
@@ -29,41 +29,41 @@ macro_rules! serde_impl {
where V: de::SeqAccess<'de>
{
let len = cmp::min(seq.size_hint().unwrap_or(0), 4096);
let mut values = Vec::with_capacity(len);
let mut values: Vec<u8> = Vec::with_capacity(len);
while let Some(value) = try!(seq.next_element()) {
while let Some(value) = seq.next_element()? {
values.push(value);
}
Ok(values.into())
Ok($ty::$from_vec(values))
}
#[inline]
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where E: de::Error
{
Ok($ty::from(v))
Ok($ty::$from_slice(v))
}
#[inline]
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where E: de::Error
{
Ok($ty::from(v))
Ok($ty::$from_vec(v))
}
#[inline]
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where E: de::Error
{
Ok($ty::from(v))
Ok($ty::$from_slice(v.as_bytes()))
}
#[inline]
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where E: de::Error
{
Ok($ty::from(v))
Ok($ty::$from_vec(v.into_bytes()))
}
}
@@ -78,5 +78,5 @@ macro_rules! serde_impl {
);
}
serde_impl!(Bytes, BytesVisitor);
serde_impl!(BytesMut, BytesMutVisitor);
serde_impl!(Bytes, BytesVisitor, copy_from_slice, from);
serde_impl!(BytesMut, BytesMutVisitor, from, from_vec);
+31 -18
View File
@@ -1,14 +1,11 @@
extern crate bytes;
extern crate byteorder;
extern crate iovec;
#![deny(warnings, rust_2018_idioms)]
use bytes::Buf;
use iovec::IoVec;
use std::io::Cursor;
use std::io::IoSlice;
#[test]
fn test_fresh_cursor_vec() {
let mut buf = Cursor::new(b"hello".to_vec());
let mut buf = &b"hello"[..];
assert_eq!(buf.remaining(), 5);
assert_eq!(buf.bytes(), b"hello");
@@ -26,33 +23,49 @@ fn test_fresh_cursor_vec() {
#[test]
fn test_get_u8() {
let mut buf = Cursor::new(b"\x21zomg");
let mut buf = &b"\x21zomg"[..];
assert_eq!(0x21, buf.get_u8());
}
#[test]
fn test_get_u16() {
let buf = b"\x21\x54zomg";
assert_eq!(0x2154, Cursor::new(buf).get_u16_be());
assert_eq!(0x5421, Cursor::new(buf).get_u16_le());
let mut buf = &b"\x21\x54zomg"[..];
assert_eq!(0x2154, buf.get_u16());
let mut buf = &b"\x21\x54zomg"[..];
assert_eq!(0x5421, buf.get_u16_le());
}
#[test]
#[should_panic]
fn test_get_u16_buffer_underflow() {
let mut buf = Cursor::new(b"\x21");
buf.get_u16_be();
let mut buf = &b"\x21"[..];
buf.get_u16();
}
#[test]
fn test_bufs_vec() {
let buf = Cursor::new(b"hello world");
let buf = &b"hello world"[..];
let b1: &[u8] = &mut [0];
let b2: &[u8] = &mut [0];
let b1: &[u8] = &mut [];
let b2: &[u8] = &mut [];
let mut dst: [&IoVec; 2] =
[b1.into(), b2.into()];
let mut dst = [IoSlice::new(b1), IoSlice::new(b2)];
assert_eq!(1, buf.bytes_vec(&mut dst[..]));
assert_eq!(1, buf.bytes_vectored(&mut dst[..]));
}
#[test]
fn test_vec_deque() {
use std::collections::VecDeque;
let mut buffer: VecDeque<u8> = VecDeque::new();
buffer.extend(b"hello world");
assert_eq!(11, buffer.remaining());
assert_eq!(b"hello world", buffer.bytes());
buffer.advance(6);
assert_eq!(b"world", buffer.bytes());
buffer.extend(b" piece");
let mut out = [0; 11];
buffer.copy_to_slice(&mut out);
assert_eq!(b"world piece", &out[..]);
}
+23 -17
View File
@@ -1,9 +1,6 @@
extern crate bytes;
extern crate byteorder;
extern crate iovec;
#![deny(warnings, rust_2018_idioms)]
use bytes::{BufMut, BytesMut};
use iovec::IoVec;
use bytes::{buf::IoSliceMut, BufMut, BytesMut};
use std::usize;
use std::fmt::Write;
@@ -13,9 +10,7 @@ fn test_vec_as_mut_buf() {
assert_eq!(buf.remaining_mut(), usize::MAX);
unsafe {
assert!(buf.bytes_mut().len() >= 64);
}
assert!(buf.bytes_mut().len() >= 64);
buf.put(&b"zomg"[..]);
@@ -34,14 +29,14 @@ fn test_vec_as_mut_buf() {
#[test]
fn test_put_u8() {
let mut buf = Vec::with_capacity(8);
buf.put::<u8>(33);
buf.put_u8(33);
assert_eq!(b"\x21", &buf[..]);
}
#[test]
fn test_put_u16() {
let mut buf = Vec::with_capacity(8);
buf.put_u16_be(8532);
buf.put_u16(8532);
assert_eq!(b"\x21\x54", &buf[..]);
buf.clear();
@@ -66,18 +61,29 @@ fn test_clone() {
buf.write_str("this is a test").unwrap();
let buf2 = buf.clone();
buf.write_str(" of our emergecy broadcast system").unwrap();
buf.write_str(" of our emergency broadcast system").unwrap();
assert!(buf != buf2);
}
#[test]
fn test_bufs_vec_mut() {
use std::mem;
let b1: &mut [u8] = &mut [];
let b2: &mut [u8] = &mut [];
let mut dst = [IoSliceMut::from(b1), IoSliceMut::from(b2)];
let mut buf = BytesMut::from(&b"hello world"[..]);
// with no capacity
let mut buf = BytesMut::new();
assert_eq!(buf.capacity(), 0);
assert_eq!(1, buf.bytes_vectored_mut(&mut dst[..]));
unsafe {
let mut dst: [&mut IoVec; 2] = mem::zeroed();
assert_eq!(1, buf.bytes_vec_mut(&mut dst[..]));
}
// with capacity
let mut buf = BytesMut::with_capacity(64);
assert_eq!(1, buf.bytes_vectored_mut(&mut dst[..]));
}
#[test]
fn test_mut_slice() {
let mut v = vec![0, 0, 0, 0];
let mut s = &mut v[..];
s.put_u32(42);
}
+294 -151
View File
@@ -1,15 +1,12 @@
extern crate bytes;
#![deny(warnings, rust_2018_idioms)]
use bytes::{Bytes, BytesMut, BufMut};
use bytes::{Bytes, BytesMut, Buf, BufMut};
use std::usize;
const LONG: &'static [u8] = b"mary had a little lamb, little lamb, little lamb";
const SHORT: &'static [u8] = b"hello world";
fn inline_cap() -> usize {
use std::mem;
4 * mem::size_of::<usize>() - 1
}
fn is_sync<T: Sync>() {}
fn is_send<T: Send>() {}
@@ -21,6 +18,35 @@ fn test_bounds() {
is_send::<BytesMut>();
}
#[test]
fn test_layout() {
use std::mem;
assert_eq!(
mem::size_of::<Bytes>(),
mem::size_of::<usize>() * 4,
"Bytes size should be 4 words",
);
assert_eq!(
mem::size_of::<BytesMut>(),
mem::size_of::<usize>() * 4,
"BytesMut should be 4 words",
);
assert_eq!(
mem::size_of::<Bytes>(),
mem::size_of::<Option<Bytes>>(),
"Bytes should be same size as Option<Bytes>",
);
assert_eq!(
mem::size_of::<BytesMut>(),
mem::size_of::<Option<BytesMut>>(),
"BytesMut should be same size as Option<BytesMut>",
);
}
#[test]
fn from_slice() {
let a = Bytes::from(&b"abcdefgh"[..]);
@@ -69,8 +95,8 @@ fn fmt_write() {
let mut c = BytesMut::with_capacity(64);
write!(c, "{}", s).unwrap_err();
assert!(c.is_empty());
write!(c, "{}", s).unwrap();
assert_eq!(c, s[..].as_bytes());
}
#[test]
@@ -98,22 +124,22 @@ fn index() {
fn slice() {
let a = Bytes::from(&b"hello world"[..]);
let b = a.slice(3, 5);
let b = a.slice(3..5);
assert_eq!(b, b"lo"[..]);
let b = a.slice(0, 0);
let b = a.slice(0..0);
assert_eq!(b, b""[..]);
let b = a.slice(3, 3);
let b = a.slice(3..3);
assert_eq!(b, b""[..]);
let b = a.slice(a.len(), a.len());
let b = a.slice(a.len()..a.len());
assert_eq!(b, b""[..]);
let b = a.slice_to(5);
let b = a.slice(..5);
assert_eq!(b, b"hello"[..]);
let b = a.slice_from(3);
let b = a.slice(3..);
assert_eq!(b, b"lo world"[..]);
}
@@ -121,14 +147,14 @@ fn slice() {
#[should_panic]
fn slice_oob_1() {
let a = Bytes::from(&b"hello world"[..]);
a.slice(5, inline_cap() + 1);
a.slice(5..44);
}
#[test]
#[should_panic]
fn slice_oob_2() {
let a = Bytes::from(&b"hello world"[..]);
a.slice(inline_cap() + 1, inline_cap() + 5);
a.slice(44..49);
}
#[test]
@@ -150,7 +176,7 @@ fn split_off() {
#[should_panic]
fn split_off_oob() {
let mut hello = Bytes::from(&b"helloworld"[..]);
hello.split_off(inline_cap() + 1);
hello.split_off(44);
}
#[test]
@@ -175,8 +201,8 @@ fn split_off_to_loop() {
let off = bytes.split_off(i);
assert_eq!(i, bytes.len());
let mut sum = Vec::new();
sum.extend(&bytes);
sum.extend(&off);
sum.extend(bytes.iter());
sum.extend(off.iter());
assert_eq!(&s[..], &sum[..]);
}
{
@@ -193,8 +219,8 @@ fn split_off_to_loop() {
let off = bytes.split_to(i);
assert_eq!(i, off.len());
let mut sum = Vec::new();
sum.extend(&off);
sum.extend(&bytes);
sum.extend(off.iter());
sum.extend(bytes.iter());
assert_eq!(&s[..], &sum[..]);
}
{
@@ -211,21 +237,21 @@ fn split_off_to_loop() {
#[test]
fn split_to_1() {
// Inline
let mut a = Bytes::from(SHORT);
// Static
let mut a = Bytes::from_static(SHORT);
let b = a.split_to(4);
assert_eq!(SHORT[4..], a);
assert_eq!(SHORT[..4], b);
// Allocated
let mut a = Bytes::from(LONG);
let mut a = Bytes::copy_from_slice(LONG);
let b = a.split_to(4);
assert_eq!(LONG[4..], a);
assert_eq!(LONG[..4], b);
let mut a = Bytes::from(LONG);
let mut a = Bytes::copy_from_slice(LONG);
let b = a.split_to(30);
assert_eq!(LONG[30..], a);
@@ -247,26 +273,21 @@ fn split_to_2() {
#[should_panic]
fn split_to_oob() {
let mut hello = Bytes::from(&b"helloworld"[..]);
hello.split_to(inline_cap() + 1);
hello.split_to(33);
}
#[test]
#[should_panic]
fn split_to_oob_mut() {
let mut hello = BytesMut::from(&b"helloworld"[..]);
hello.split_to(inline_cap() + 1);
hello.split_to(33);
}
#[test]
#[should_panic]
fn split_to_uninitialized() {
let mut bytes = BytesMut::with_capacity(1024);
let other = bytes.split_to(128);
assert_eq!(bytes.len(), 0);
assert_eq!(bytes.capacity(), 896);
assert_eq!(other.len(), 0);
assert_eq!(other.capacity(), 128);
let _other = bytes.split_to(128);
}
#[test]
@@ -291,6 +312,24 @@ fn split_off_to_at_gt_len() {
}).is_err());
}
#[test]
fn freeze_clone_shared() {
let s = &b"abcdefgh"[..];
let b = BytesMut::from(s).split().freeze();
assert_eq!(b, s);
let c = b.clone();
assert_eq!(c, s);
}
#[test]
fn freeze_clone_unique() {
let s = &b"abcdefgh"[..];
let b = BytesMut::from(s).freeze();
assert_eq!(b, s);
let c = b.clone();
assert_eq!(c, s);
}
#[test]
fn fns_defined_for_bytes_mut() {
let mut bytes = BytesMut::from(&b"hello world"[..]);
@@ -299,30 +338,12 @@ fn fns_defined_for_bytes_mut() {
bytes.as_mut_ptr();
// Iterator
let v: Vec<u8> = bytes.iter().map(|b| *b).collect();
let v: Vec<u8> = bytes.as_ref().iter().cloned().collect();
assert_eq!(&v[..], bytes);
}
#[test]
fn reserve_convert() {
// Inline -> Vec
let mut bytes = BytesMut::with_capacity(8);
bytes.put("hello");
bytes.reserve(40);
assert_eq!(bytes.capacity(), 45);
assert_eq!(bytes, "hello");
// Inline -> Inline
let mut bytes = BytesMut::with_capacity(inline_cap());
bytes.put("abcdefghijkl");
let a = bytes.split_to(10);
bytes.reserve(inline_cap() - 3);
assert_eq!(inline_cap(), bytes.capacity());
assert_eq!(bytes, "kl");
assert_eq!(a, "abcdefghij");
// Vec -> Vec
let mut bytes = BytesMut::from(LONG);
bytes.reserve(64);
@@ -341,8 +362,8 @@ fn reserve_convert() {
#[test]
fn reserve_growth() {
let mut bytes = BytesMut::with_capacity(64);
bytes.put("hello world");
let _ = bytes.take();
bytes.put("hello world".as_bytes());
let _ = bytes.split();
bytes.reserve(65);
assert_eq!(bytes.capacity(), 128);
@@ -353,10 +374,10 @@ fn reserve_allocates_at_least_original_capacity() {
let mut bytes = BytesMut::with_capacity(1024);
for i in 0..1020 {
bytes.put(i as u8);
bytes.put_u8(i as u8);
}
let _other = bytes.take();
let _other = bytes.split();
bytes.reserve(16);
assert_eq!(bytes.capacity(), 1024);
@@ -369,34 +390,33 @@ fn reserve_max_original_capacity_value() {
let mut bytes = BytesMut::with_capacity(SIZE);
for _ in 0..SIZE {
bytes.put(0u8);
bytes.put_u8(0u8);
}
let _other = bytes.take();
let _other = bytes.split();
bytes.reserve(16);
assert_eq!(bytes.capacity(), 64 * 1024);
}
// Without either looking at the internals of the BytesMut or doing weird stuff
// with the memory allocator, there's no good way to automatically verify from
// within the program that this actually recycles memory. Instead, just exercise
// the code path to ensure that the results are correct.
#[test]
fn reserve_vec_recycling() {
let mut bytes = BytesMut::from(Vec::with_capacity(16));
let mut bytes = BytesMut::with_capacity(16);
assert_eq!(bytes.capacity(), 16);
bytes.put("0123456789012345");
let addr = bytes.as_ptr() as usize;
bytes.put("0123456789012345".as_bytes());
assert_eq!(bytes.as_ptr() as usize, addr);
bytes.advance(10);
assert_eq!(bytes.capacity(), 6);
bytes.reserve(8);
assert_eq!(bytes.capacity(), 16);
assert_eq!(bytes.as_ptr() as usize, addr);
}
#[test]
fn reserve_in_arc_unique_does_not_overallocate() {
let mut bytes = BytesMut::with_capacity(1000);
bytes.take();
bytes.split();
// now bytes is Arc and refcount == 1
@@ -408,7 +428,7 @@ fn reserve_in_arc_unique_does_not_overallocate() {
#[test]
fn reserve_in_arc_unique_doubles() {
let mut bytes = BytesMut::with_capacity(1000);
bytes.take();
bytes.split();
// now bytes is Arc and refcount == 1
@@ -420,7 +440,7 @@ fn reserve_in_arc_unique_doubles() {
#[test]
fn reserve_in_arc_nonunique_does_not_overallocate() {
let mut bytes = BytesMut::with_capacity(1000);
let _copy = bytes.take();
let _copy = bytes.split();
// now bytes is Arc and refcount == 2
@@ -429,15 +449,6 @@ fn reserve_in_arc_nonunique_does_not_overallocate() {
assert_eq!(2001, bytes.capacity());
}
#[test]
fn inline_storage() {
let mut bytes = BytesMut::with_capacity(inline_cap());
let zero = [0u8; 64];
bytes.put(&zero[0..inline_cap()]);
assert_eq!(*bytes, zero[0..inline_cap()]);
}
#[test]
fn extend_mut() {
let mut bytes = BytesMut::with_capacity(0);
@@ -445,13 +456,6 @@ fn extend_mut() {
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] {
@@ -463,13 +467,13 @@ fn extend_from_slice_mut() {
}
#[test]
fn extend_from_slice_shr() {
for &i in &[3, 34] {
let mut bytes = Bytes::new();
bytes.extend_from_slice(&LONG[..i]);
bytes.extend_from_slice(&LONG[i..]);
assert_eq!(LONG[..], *bytes);
}
fn extend_mut_without_size_hint() {
let mut bytes = BytesMut::with_capacity(0);
let mut long_iter = LONG.iter();
// Use iter::from_fn since it doesn't know a size_hint
bytes.extend(std::iter::from_fn(|| long_iter.next()));
assert_eq!(*bytes, LONG[..]);
}
#[test]
@@ -481,13 +485,6 @@ fn from_static() {
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");
@@ -497,7 +494,20 @@ fn advance_static() {
#[test]
fn advance_vec() {
let mut a = BytesMut::from(b"hello world boooo yah world zomg wat wat".to_vec());
let mut a = Bytes::from(b"hello world boooo yah world zomg wat wat".to_vec());
a.advance(16);
assert_eq!(a, b"o yah world zomg wat wat"[..]);
a.advance(4);
assert_eq!(a, b"h world zomg wat wat"[..]);
a.advance(6);
assert_eq!(a, b"d zomg wat wat"[..]);
}
#[test]
fn advance_bytes_mut() {
let mut a = BytesMut::from("hello world boooo yah world zomg wat wat");
a.advance(16);
assert_eq!(a, b"o yah world zomg wat wat"[..]);
@@ -515,7 +525,7 @@ fn advance_vec() {
#[test]
#[should_panic]
fn advance_past_len() {
let mut a = BytesMut::from(b"hello world".to_vec());
let mut a = BytesMut::from("hello world");
a.advance(20);
}
@@ -533,7 +543,7 @@ fn stress() {
for i in 0..ITERS {
let data = [i as u8; 256];
let buf = Arc::new(Bytes::from(&data[..]));
let buf = Arc::new(Bytes::copy_from_slice(&data[..]));
let barrier = Arc::new(Barrier::new(THREADS));
let mut joins = Vec::with_capacity(THREADS);
@@ -568,8 +578,99 @@ fn partial_eq_bytesmut() {
assert!(bytesmut != bytes2);
}
/*
#[test]
fn unsplit_basic() {
fn bytes_unsplit_basic() {
let buf = Bytes::from(&b"aaabbbcccddd"[..]);
let splitted = buf.split_off(6);
assert_eq!(b"aaabbb", &buf[..]);
assert_eq!(b"cccddd", &splitted[..]);
buf.unsplit(splitted);
assert_eq!(b"aaabbbcccddd", &buf[..]);
}
#[test]
fn bytes_unsplit_empty_other() {
let buf = Bytes::from(&b"aaabbbcccddd"[..]);
// empty other
let other = Bytes::new();
buf.unsplit(other);
assert_eq!(b"aaabbbcccddd", &buf[..]);
}
#[test]
fn bytes_unsplit_empty_self() {
// empty self
let mut buf = Bytes::new();
let mut other = Bytes::with_capacity(64);
other.extend_from_slice(b"aaabbbcccddd");
buf.unsplit(other);
assert_eq!(b"aaabbbcccddd", &buf[..]);
}
#[test]
fn bytes_unsplit_arc_different() {
let mut buf = Bytes::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbeeee");
buf.split_off(8); //arc
let mut buf2 = Bytes::with_capacity(64);
buf2.extend_from_slice(b"ccccddddeeee");
buf2.split_off(8); //arc
buf.unsplit(buf2);
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
}
#[test]
fn bytes_unsplit_arc_non_contiguous() {
let mut buf = Bytes::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbeeeeccccdddd");
let mut buf2 = buf.split_off(8); //arc
let buf3 = buf2.split_off(4); //arc
buf.unsplit(buf3);
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
}
#[test]
fn bytes_unsplit_two_split_offs() {
let mut buf = Bytes::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbccccdddd");
let mut buf2 = buf.split_off(8); //arc
let buf3 = buf2.split_off(4); //arc
buf2.unsplit(buf3);
buf.unsplit(buf2);
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
}
#[test]
fn bytes_unsplit_overlapping_references() {
let mut buf = Bytes::with_capacity(64);
buf.extend_from_slice(b"abcdefghijklmnopqrstuvwxyz");
let mut buf0010 = buf.slice(0..10);
let buf1020 = buf.slice(10..20);
let buf0515 = buf.slice(5..15);
buf0010.unsplit(buf1020);
assert_eq!(b"abcdefghijklmnopqrst", &buf0010[..]);
assert_eq!(b"fghijklmno", &buf0515[..]);
}
*/
#[test]
fn bytes_mut_unsplit_basic() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaabbbcccddd");
@@ -582,7 +683,7 @@ fn unsplit_basic() {
}
#[test]
fn unsplit_empty_other() {
fn bytes_mut_unsplit_empty_other() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaabbbcccddd");
@@ -594,7 +695,7 @@ fn unsplit_empty_other() {
}
#[test]
fn unsplit_empty_self() {
fn bytes_mut_unsplit_empty_self() {
// empty self
let mut buf = BytesMut::new();
@@ -606,50 +707,7 @@ fn unsplit_empty_self() {
}
#[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() {
fn bytes_mut_unsplit_arc_different() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbeeee");
@@ -665,7 +723,7 @@ fn unsplit_arc_different() {
}
#[test]
fn unsplit_arc_non_contiguous() {
fn bytes_mut_unsplit_arc_non_contiguous() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbeeeeccccdddd");
@@ -678,7 +736,7 @@ fn unsplit_arc_non_contiguous() {
}
#[test]
fn unsplit_two_split_offs() {
fn bytes_mut_unsplit_two_split_offs() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbccccdddd");
@@ -710,3 +768,88 @@ fn from_iter_no_size_hint() {
assert_eq!(&actual[..], &expect[..]);
}
fn test_slice_ref(bytes: &Bytes, start: usize, end: usize, expected: &[u8]) {
let slice = &(bytes.as_ref()[start..end]);
let sub = bytes.slice_ref(&slice);
assert_eq!(&sub[..], expected);
}
#[test]
fn slice_ref_works() {
let bytes = Bytes::from(&b"012345678"[..]);
test_slice_ref(&bytes, 0, 0, b"");
test_slice_ref(&bytes, 0, 3, b"012");
test_slice_ref(&bytes, 2, 6, b"2345");
test_slice_ref(&bytes, 7, 9, b"78");
test_slice_ref(&bytes, 9, 9, b"");
}
#[test]
fn slice_ref_empty() {
let bytes = Bytes::from(&b""[..]);
let slice = &(bytes.as_ref()[0..0]);
let sub = bytes.slice_ref(&slice);
assert_eq!(&sub[..], b"");
}
#[test]
#[should_panic]
fn slice_ref_catches_not_a_subset() {
let bytes = Bytes::from(&b"012345678"[..]);
let slice = &b"012345"[0..4];
bytes.slice_ref(slice);
}
#[test]
#[should_panic]
fn slice_ref_catches_not_an_empty_subset() {
let bytes = Bytes::from(&b"012345678"[..]);
let slice = &b""[0..0];
bytes.slice_ref(slice);
}
#[test]
#[should_panic]
fn empty_slice_ref_catches_not_an_empty_subset() {
let bytes = Bytes::copy_from_slice(&b""[..]);
let slice = &b""[0..0];
bytes.slice_ref(slice);
}
#[test]
fn bytes_buf_mut_advance() {
let mut bytes = BytesMut::with_capacity(1024);
unsafe {
let ptr = bytes.bytes_mut().as_ptr();
assert_eq!(1024, bytes.bytes_mut().len());
bytes.advance_mut(10);
let next = bytes.bytes_mut().as_ptr();
assert_eq!(1024 - 10, bytes.bytes_mut().len());
assert_eq!(ptr.offset(10), next);
// advance to the end
bytes.advance_mut(1024 - 10);
// The buffer size is doubled
assert_eq!(1024, bytes.bytes_mut().len());
}
}
#[test]
#[should_panic]
fn bytes_reserve_overflow() {
let mut bytes = BytesMut::with_capacity(1024);
bytes.put_slice(b"hello world");
bytes.reserve(usize::MAX);
}
+71 -60
View File
@@ -1,36 +1,31 @@
extern crate bytes;
extern crate iovec;
#![deny(warnings, rust_2018_idioms)]
use bytes::{Buf, BufMut, Bytes, BytesMut};
use bytes::buf::Chain;
use iovec::IoVec;
use std::io::Cursor;
use bytes::{Buf, BufMut, Bytes};
use bytes::buf::{BufExt, BufMutExt};
use std::io::IoSlice;
#[test]
fn collect_two_bufs() {
let a = Cursor::new(Bytes::from(&b"hello"[..]));
let b = Cursor::new(Bytes::from(&b"world"[..]));
let a = Bytes::from(&b"hello"[..]);
let b = Bytes::from(&b"world"[..]);
let res: Vec<u8> = a.chain(b).collect();
let res = a.chain(b).to_bytes();
assert_eq!(res, &b"helloworld"[..]);
}
#[test]
fn writing_chained() {
let mut a = BytesMut::with_capacity(64);
let mut b = BytesMut::with_capacity(64);
let mut a = [0u8; 64];
let mut b = [0u8; 64];
{
let mut buf = Chain::new(&mut a, &mut b);
let mut buf = (&mut a[..]).chain_mut(&mut b[..]);
for i in 0..128 {
buf.put(i as u8);
for i in 0u8..128 {
buf.put_u8(i);
}
}
assert_eq!(64, a.len());
assert_eq!(64, b.len());
for i in 0..64 {
let expect = i as u8;
assert_eq!(expect, a[i]);
@@ -40,83 +35,99 @@ fn writing_chained() {
#[test]
fn iterating_two_bufs() {
let a = Cursor::new(Bytes::from(&b"hello"[..]));
let b = Cursor::new(Bytes::from(&b"world"[..]));
let a = Bytes::from(&b"hello"[..]);
let b = Bytes::from(&b"world"[..]);
let res: Vec<u8> = a.chain(b).iter().collect();
let res: Vec<u8> = a.chain(b).into_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 a = Bytes::from(&b"hello"[..]);
let b = Bytes::from(&b"world"[..]);
let mut buf = a.chain(b);
{
let b1: &[u8] = &mut [0];
let b2: &[u8] = &mut [0];
let b3: &[u8] = &mut [0];
let b4: &[u8] = &mut [0];
let mut iovecs: [&IoVec; 4] =
[b1.into(), b2.into(), b3.into(), b4.into()];
let b1: &[u8] = &mut [];
let b2: &[u8] = &mut [];
let b3: &[u8] = &mut [];
let b4: &[u8] = &mut [];
let mut iovecs = [
IoSlice::new(b1),
IoSlice::new(b2),
IoSlice::new(b3),
IoSlice::new(b4),
];
assert_eq!(2, buf.bytes_vec(&mut iovecs));
assert_eq!(2, buf.bytes_vectored(&mut iovecs));
assert_eq!(iovecs[0][..], b"hello"[..]);
assert_eq!(iovecs[1][..], b"world"[..]);
assert_eq!(iovecs[2][..], b"\0"[..]);
assert_eq!(iovecs[3][..], b"\0"[..]);
assert_eq!(iovecs[2][..], b""[..]);
assert_eq!(iovecs[3][..], b""[..]);
}
buf.advance(2);
{
let b1: &[u8] = &mut [0];
let b2: &[u8] = &mut [0];
let b3: &[u8] = &mut [0];
let b4: &[u8] = &mut [0];
let mut iovecs: [&IoVec; 4] =
[b1.into(), b2.into(), b3.into(), b4.into()];
let b1: &[u8] = &mut [];
let b2: &[u8] = &mut [];
let b3: &[u8] = &mut [];
let b4: &[u8] = &mut [];
let mut iovecs = [
IoSlice::new(b1),
IoSlice::new(b2),
IoSlice::new(b3),
IoSlice::new(b4),
];
assert_eq!(2, buf.bytes_vec(&mut iovecs));
assert_eq!(2, buf.bytes_vectored(&mut iovecs));
assert_eq!(iovecs[0][..], b"llo"[..]);
assert_eq!(iovecs[1][..], b"world"[..]);
assert_eq!(iovecs[2][..], b"\0"[..]);
assert_eq!(iovecs[3][..], b"\0"[..]);
assert_eq!(iovecs[2][..], b""[..]);
assert_eq!(iovecs[3][..], b""[..]);
}
buf.advance(3);
{
let b1: &[u8] = &mut [0];
let b2: &[u8] = &mut [0];
let b3: &[u8] = &mut [0];
let b4: &[u8] = &mut [0];
let mut iovecs: [&IoVec; 4] =
[b1.into(), b2.into(), b3.into(), b4.into()];
let b1: &[u8] = &mut [];
let b2: &[u8] = &mut [];
let b3: &[u8] = &mut [];
let b4: &[u8] = &mut [];
let mut iovecs = [
IoSlice::new(b1),
IoSlice::new(b2),
IoSlice::new(b3),
IoSlice::new(b4),
];
assert_eq!(1, buf.bytes_vec(&mut iovecs));
assert_eq!(1, buf.bytes_vectored(&mut iovecs));
assert_eq!(iovecs[0][..], b"world"[..]);
assert_eq!(iovecs[1][..], b"\0"[..]);
assert_eq!(iovecs[2][..], b"\0"[..]);
assert_eq!(iovecs[3][..], b"\0"[..]);
assert_eq!(iovecs[1][..], b""[..]);
assert_eq!(iovecs[2][..], b""[..]);
assert_eq!(iovecs[3][..], b""[..]);
}
buf.advance(3);
{
let b1: &[u8] = &mut [0];
let b2: &[u8] = &mut [0];
let b3: &[u8] = &mut [0];
let b4: &[u8] = &mut [0];
let mut iovecs: [&IoVec; 4] =
[b1.into(), b2.into(), b3.into(), b4.into()];
let b1: &[u8] = &mut [];
let b2: &[u8] = &mut [];
let b3: &[u8] = &mut [];
let b4: &[u8] = &mut [];
let mut iovecs = [
IoSlice::new(b1),
IoSlice::new(b2),
IoSlice::new(b3),
IoSlice::new(b4),
];
assert_eq!(1, buf.bytes_vec(&mut iovecs));
assert_eq!(1, buf.bytes_vectored(&mut iovecs));
assert_eq!(iovecs[0][..], b"ld"[..]);
assert_eq!(iovecs[1][..], b"\0"[..]);
assert_eq!(iovecs[2][..], b"\0"[..]);
assert_eq!(iovecs[3][..], b"\0"[..]);
assert_eq!(iovecs[1][..], b""[..]);
assert_eq!(iovecs[2][..], b""[..]);
assert_eq!(iovecs[3][..], b""[..]);
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
extern crate bytes;
#![deny(warnings, rust_2018_idioms)]
use bytes::Bytes;
-34
View File
@@ -1,34 +0,0 @@
extern crate bytes;
use bytes::{Buf, Bytes, BytesMut};
use std::io::Cursor;
const LONG: &'static [u8] = b"mary had a little lamb, little lamb, little lamb";
const SHORT: &'static [u8] = b"hello world";
#[test]
fn collect_to_vec() {
let buf: Vec<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);
}
+4 -4
View File
@@ -1,10 +1,10 @@
extern crate bytes;
#![deny(warnings, rust_2018_idioms)]
use bytes::{Buf, IntoBuf, Bytes};
use bytes::Bytes;
#[test]
fn iter_len() {
let buf = Bytes::from(&b"hello world"[..]).into_buf();
let buf = Bytes::from_static(b"hello world");
let iter = buf.iter();
assert_eq!(iter.size_hint(), (11, Some(11)));
@@ -14,7 +14,7 @@ fn iter_len() {
#[test]
fn empty_iter_len() {
let buf = Bytes::from(&b""[..]).into_buf();
let buf = Bytes::from_static(b"");
let iter = buf.iter();
assert_eq!(iter.size_hint(), (0, Some(0)));
+28
View File
@@ -0,0 +1,28 @@
#![deny(warnings, rust_2018_idioms)]
use std::io::{BufRead, Read};
use bytes::buf::{BufExt};
#[test]
fn read() {
let buf1 = &b"hello "[..];
let buf2 = &b"world"[..];
let buf = BufExt::chain(buf1, buf2); // Disambiguate with Read::chain
let mut buffer = Vec::new();
buf.reader().read_to_end(&mut buffer).unwrap();
assert_eq!(b"hello world", &buffer[..]);
}
#[test]
fn buf_read() {
let buf1 = &b"hell"[..];
let buf2 = &b"o\nworld"[..];
let mut reader = BufExt::chain(buf1, buf2).reader();
let mut line = String::new();
reader.read_line(&mut line).unwrap();
assert_eq!("hello\n", &line);
line.clear();
reader.read_line(&mut line).unwrap();
assert_eq!("world", &line);
}
+1 -2
View File
@@ -1,7 +1,6 @@
#![cfg(feature = "serde")]
#![deny(warnings, rust_2018_idioms)]
extern crate bytes;
extern crate serde_test;
use serde_test::{Token, assert_tokens};
#[test]
+4 -5
View File
@@ -1,13 +1,12 @@
extern crate bytes;
#![deny(warnings, rust_2018_idioms)]
use bytes::Buf;
use std::io::Cursor;
use bytes::buf::{Buf, BufExt};
#[test]
fn long_take() {
// Tests that take with a size greater than the buffer length will not
// Tests that get a take with a size greater than the buffer length will not
// overrun the buffer. Regression test for #138.
let buf = Cursor::new(b"hello world").take(100);
let buf = b"hello world".take(100);
assert_eq!(11, buf.remaining());
assert_eq!(b"hello world", buf.bytes());
}