<Arc<T>>::make_mut returns a &mut T, such an API is doable for Bytes too
and thus we should reserve Bytes::make_mut for that.
Furthermore, it would be helpful to use From<Bytes> as a trait bound
in some cases with other traits such as Hyper's body trait, where Hyper
gives you Bytes values.
Finally, making it impl From<Bytes> for BytesMut means the API is more
easily discoverable as it appears on both Bytes and BytesMut.
Follow up to https://github.com/tokio-rs/bytes/pull/689
* If `at == self.len()`, we already know `at <= self.len()`.
* If `at == 0`, we already know `at <= self.len()`.
When we freeze a BytesMut, we turn it into a Vec, and then convert that
to a Bytes. Currently, this happen using Vec::into_boxed_slice, which
reallocates to a slice of the same length as the Vev if the length and
the capacity are not equal. This can pose a performance problem if the
Vec is large or if this happens many times in a loop.
Instead, let's compare the length and capacity, and if they're the same,
continue to handle this using into_boxed_slice. Otherwise, since we
have a type of vtable which can handle a separate capacity, the shared
vtable, let's turn our Vec into that kind of Bytes. While this does not
avoid allocation altogether, it performs a fixed size allocation and
avoids any need to memcpy.
Previously, this code produced a &mut[u8] and a Box<[u8]> to the shared
allocation upon cloning it. If the underlying allocation were actually
shared, such as through a &[u8] from the Deref impl, creating either of
these types incorrectly asserted uniqueness of the allocation.
This fixes the example in #522, but Miri still does not pass on this
test suite with -Zmiri-tag-raw-pointers because Miri does not currently
understand int to pointer casts.
I find this diagram very helpful, but a little hard to distinguish
between the boxes and the lines that connect them. This commit redraws
the boxes with line drawing characters so that the boxes appear a
little more solid, and stand out from the other lines.
The `bytes()` / `bytes_mut()` name implies the method returns the full
set of bytes represented by `Buf`/`BufMut`. To rectify this, the methods
are renamed to `chunk()` and `chunk_mut()` to reflect the partial nature
of the returned byte slice.
`bytes_vectored()` is renamed `chunks_vectored()`.
Closes#447
This method replaces `Buf::to_bytes()`, providing a method that copies a
subset of the remaining buffer into a `Bytes` value. As this is strictly
more flexible, `to_bytes()` is removed.
Fixes: #129, #398
The previous description focussed a lot on the `Arc` based implementation
of `Bytes`. Given the vtable based implemetation, this is however not the
only valid implementation. This changes the description a bit in order
to de-emaphasize the `Arc` part, and to describe that other implementations
are possible.
This should also be necessary if the vtable gets public.
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