Use case:
```
let bytes: Bytes = ...
let subbytes = bytes.slice(a..b); // where a == b
let slice = &subbytes[..];
let slice_bytes = bytes.slice_ref(slice);
```
Last line should not panic, because `slice` object is derived from
the original `Bytes` object.
Before this commit it panics, because `Bytes::slice` returns a fresh
`Bytes` object when `begin == end`.
"Promotable" `Bytes` object is constructed from disassembling a
boxed slice object, not a vec.
Thus we should reassemble data into a boxed slice, not into a vec.
Although, it does not create any problems in practice (`Box<[u8]>`
is allocated exactly the same way as `Vec<u8>`), technically it is
a violation of `Vec::from_raw_parts` spec which says that a pointer
"needs to have been previously allocated via `String`/`Vec<T>`".
This separates the `SharedVtable` into 3:
- `PromotableEvenVtable`: The original `SharedVtable`, which will
promote the `Vec` to `Shared` on the first clone, and is selected when
the `Vec`'s pointer has the LSB unset.
- `PromotableOddVtable`: Similar to the `PromotableEvenVtable`, but
selected when the `Vec`'s pointer has the LSB set. This vtable differs
in the masking used when reconstructing the `Vec`.
- `SharedVtable`: This no longer checks if its current kind is `VEC` or
`ARC`, and is only created by the "promotable" vtables.
This also adds a test using an "odd" global allocator that purposefully
bumps all pointers with alignment of 1.
Closes#343
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
- 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.
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.)
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.
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.