Struct Bytes

struct Bytes { ... }

A cheaply cloneable and sliceable chunk of contiguous memory.

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.

Bytes values facilitate zero-copy network programming by allowing multiple Bytes objects to point to the same underlying memory.

Bytes does not have a single implementation. It is an interface, whose exact behavior is implemented through dynamic dispatch in several underlying implementations of Bytes.

All Bytes implementations must fulfill the following requirements:

use bytes::Bytes;

let mut mem = Bytes::from("Hello world");
let a = mem.slice(0..5);

assert_eq!(a, "Hello");

let b = mem.split_to(6);

assert_eq!(mem, "world");
assert_eq!(b, "Hello ");

Memory layout

The Bytes struct itself is fairly small, limited to 4 usize fields used to track information about which segment of the underlying memory the Bytes handle has access to.

Bytes keeps both a pointer to the shared state containing the full memory slice and a pointer to the start of the region visible by the handle. Bytes also tracks the length of its view into the memory.

Sharing

Bytes contains a vtable, which allows implementations of Bytes to define how sharing/cloning is implemented in detail. When Bytes::clone() is called, Bytes will call the vtable function for cloning the backing storage in order to share it behind multiple Bytes instances.

For Bytes implementations which refer to constant memory (e.g. created via Bytes::from_static()) the cloning implementation will be a no-op.

For Bytes implementations which point to a reference counted shared storage (e.g. an Arc<[u8]>), sharing will be implemented by increasing the reference count.

Due to this mechanism, multiple Bytes instances may point to the same shared memory region. Each Bytes instance can point to different sections within that memory region, and Bytes instances may or may not have overlapping views into the memory.

The following diagram visualizes a scenario where 2 Bytes instances make use of an Arc-based backing storage, and provide access to different views:


   Arc ptrs                   ┌─────────┐
   ________________________ / │ Bytes 2 │
  /                           └─────────┘
 /          ┌───────────┐     |         |
|_________/ │  Bytes 1  │     |         |
|           └───────────┘     |         |
|           |           | ___/ data     | tail
|      data |      tail |/              |
v           v           v               v
┌─────┬─────┬───────────┬───────────────┬─────┐
│ Arc │     │           │               │     │
└─────┴─────┴───────────┴───────────────┴─────┘

Implementations

impl Bytes

const fn new() -> Self

Creates a new empty Bytes.

This will not allocate and the returned Bytes handle will be empty.

Examples

use bytes::Bytes;

let b = Bytes::new();
assert_eq!(&b[..], b"");
const fn from_static(bytes: &'static [u8]) -> Self

Creates a new Bytes from a static slice.

The returned Bytes will point directly to the static slice. There is no allocating or copying.

Examples

use bytes::Bytes;

let b = Bytes::from_static(b"hello");
assert_eq!(&b[..], b"hello");
fn from_owner<T>(owner: T) -> Self
where
    T: AsRef<[u8]> + Send + 'static

Create [Bytes] with a buffer whose lifetime is controlled via an explicit owner.

A common use case is to zero-copy construct from mapped memory.

# struct File;
#
# impl File {
#     pub fn open(_: &str) -> Result<Self, ()> {
#         Ok(Self)
#     }
# }
#
# mod memmap2 {
#     pub struct Mmap;
#
#     impl Mmap {
#         pub unsafe fn map(_file: &super::File) -> Result<Self, ()> {
#             Ok(Self)
#         }
#     }
#
#     impl AsRef<[u8]> for Mmap {
#         fn as_ref(&self) -> &[u8] {
#             b"buf"
#         }
#     }
# }
use bytes::Bytes;
use memmap2::Mmap;

# fn main() -> Result<(), ()> {
let file = File::open("upload_bundle.tar.gz")?;
let mmap = unsafe { Mmap::map(&file) }?;
let b = Bytes::from_owner(mmap);
# Ok(())
# }

The owner will be transferred to the constructed [Bytes] object, which will ensure it is dropped once all remaining clones of the constructed object are dropped. The owner will then be responsible for dropping the specified region of memory as part of its [Drop] implementation.

Note that converting [Bytes] constructed from an owner into a [BytesMut] will always create a deep copy of the buffer into newly allocated memory.

const fn len(self: &Self) -> usize

Returns the number of bytes contained in this Bytes.

Examples

use bytes::Bytes;

let b = Bytes::from(&b"hello"[..]);
assert_eq!(b.len(), 5);
const fn is_empty(self: &Self) -> bool

Returns true if the Bytes has a length of 0.

Examples

use bytes::Bytes;

let b = Bytes::new();
assert!(b.is_empty());
fn is_unique(self: &Self) -> bool

Returns true if this is the only reference to the data and Into<BytesMut> would avoid cloning the underlying buffer.

Always returns false if the data is backed by a static slice, or an owner.

The result of this method may be invalidated immediately if another thread clones this value while this is being called. Ensure you have unique access to this value (&mut Bytes) first if you need to be certain the result is valid (i.e. for safety reasons).

Examples

use bytes::Bytes;

let a = Bytes::from(vec![1, 2, 3]);
assert!(a.is_unique());
let b = a.clone();
assert!(!a.is_unique());
fn copy_from_slice(data: &[u8]) -> Self

Creates Bytes instance from slice, by copying it.

fn slice<impl RangeBounds<usize>: RangeBounds<usize>>(self: &Self, range: impl RangeBounds<usize>) -> Self

Returns a slice of self for the provided range.

This will increment the reference count for the underlying memory and return a new Bytes handle set to the slice.

This operation is O(1).

Examples

use bytes::Bytes;

let a = Bytes::from(&b"hello world"[..]);
let b = a.slice(2..5);

assert_eq!(&b[..], b"llo");

Panics

Requires that begin <= end and end <= self.len(), otherwise slicing will panic.

fn slice_ref(self: &Self, subset: &[u8]) -> Self

Returns a slice of self that is equivalent to the given subset.

When processing a Bytes buffer with other tools, one often gets a &[u8] which is in fact a slice of the Bytes, i.e. a subset of it. This function turns that &[u8] into another Bytes, as if one had called self.slice() with the offsets that correspond to subset.

This operation is O(1).

Examples

use bytes::Bytes;

let bytes = Bytes::from(&b"012345678"[..]);
let as_slice = bytes.as_ref();
let subset = &as_slice[2..6];
let subslice = bytes.slice_ref(&subset);
assert_eq!(&subslice[..], b"2345");

Panics

Requires that the given sub slice is in fact contained within the Bytes buffer; otherwise this function will panic.

fn split_off(self: &mut Self, at: usize) -> Self

Splits the bytes into two at the given index.

Afterwards self contains elements [0, at), and the returned Bytes contains elements [at, len). It's guaranteed that the memory does not move, that is, the address of self does not change, and the address of the returned slice is at bytes after that.

This is an O(1) operation that just increases the reference count and sets a few indices.

Examples

use bytes::Bytes;

let mut a = Bytes::from(&b"hello world"[..]);
let b = a.split_off(5);

assert_eq!(&a[..], b"hello");
assert_eq!(&b[..], b" world");

Panics

Panics if at > len.

fn split_to(self: &mut Self, at: usize) -> Self

Splits the bytes into two at the given index.

Afterwards self contains elements [at, len), and the returned Bytes contains elements [0, at).

This is an O(1) operation that just increases the reference count and sets a few indices.

Examples

use bytes::Bytes;

let mut a = Bytes::from(&b"hello world"[..]);
let b = a.split_to(5);

assert_eq!(&a[..], b" world");
assert_eq!(&b[..], b"hello");

Panics

Panics if at > len.

fn truncate(self: &mut Self, len: usize)

Shortens the buffer, keeping the first len bytes and dropping the rest.

If len is greater than the buffer's current length, this has no effect.

The split_off method can emulate truncate, but this causes the excess bytes to be returned instead of dropped.

Examples

use bytes::Bytes;

let mut buf = Bytes::from(&b"hello world"[..]);
buf.truncate(5);
assert_eq!(buf, b"hello"[..]);
fn clear(self: &mut Self)

Clears the buffer, removing all data.

Examples

use bytes::Bytes;

let mut buf = Bytes::from(&b"hello world"[..]);
buf.clear();
assert!(buf.is_empty());
fn try_into_mut(self: Self) -> Result<BytesMut, Bytes>

Try to convert self into BytesMut.

If self is unique for the entire original buffer, this will succeed and return a BytesMut with the contents of self without copying. If self is not unique for the entire original buffer, this will fail and return self.

This will also always fail if the buffer was constructed via either from_owner or from_static.

Examples

use bytes::{Bytes, BytesMut};

let bytes = Bytes::from(b"hello".to_vec());
assert_eq!(bytes.try_into_mut(), Ok(BytesMut::from(&b"hello"[..])));

impl AsRef for Bytes

fn as_ref(self: &Self) -> &[u8]

impl Borrow for Bytes

fn borrow(self: &Self) -> &[u8]

impl Buf for Bytes

fn remaining(self: &Self) -> usize
fn chunk(self: &Self) -> &[u8]
fn advance(self: &mut Self, cnt: usize)
fn copy_to_bytes(self: &mut Self, len: usize) -> Self

impl Clone for Bytes

fn clone(self: &Self) -> Bytes

impl Debug for Bytes

fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result

impl Default for Bytes

fn default() -> Bytes

impl Deref for Bytes

fn deref(self: &Self) -> &[u8]

impl Drop for Bytes

fn drop(self: &mut Self)

impl Eq for Bytes

impl Freeze for Bytes

impl From for Bytes

fn from(slice: Box<[u8]>) -> Bytes

impl From for Bytes

fn from(vec: Vec<u8>) -> Bytes

impl From for Bytes

fn from(slice: &'static str) -> Bytes

impl From for Bytes

fn from(src: BytesMut) -> Bytes

impl From for Bytes

fn from(slice: &'static [u8]) -> Bytes

impl From for Bytes

fn from(s: String) -> Bytes

impl FromIterator for Bytes

fn from_iter<T: IntoIterator<Item = u8>>(into_iter: T) -> Self

impl Hash for Bytes

fn hash<H>(self: &Self, state: &mut H)
where
    H: Hasher

impl IntoIterator for Bytes

fn into_iter(self: Self) -> <Self as >::IntoIter

impl LowerHex for Bytes

fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result

impl Ord for Bytes

fn cmp(self: &Self, other: &Bytes) -> Ordering

impl PartialEq for Bytes

fn eq(self: &Self, other: &Vec<u8>) -> bool

impl PartialEq for Bytes

fn eq(self: &Self, other: &Bytes) -> bool

impl PartialEq for Bytes

fn eq(self: &Self, other: &BytesMut) -> bool

impl PartialEq for Bytes

fn eq(self: &Self, other: &[u8]) -> bool

impl PartialEq for Bytes

fn eq(self: &Self, other: &str) -> bool

impl PartialEq for Bytes

fn eq(self: &Self, other: &String) -> bool

impl PartialOrd for Bytes

fn partial_cmp(self: &Self, other: &Vec<u8>) -> Option<Ordering>

impl PartialOrd for Bytes

fn partial_cmp(self: &Self, other: &Bytes) -> Option<Ordering>

impl PartialOrd for Bytes

fn partial_cmp(self: &Self, other: &[u8]) -> Option<Ordering>

impl PartialOrd for Bytes

fn partial_cmp(self: &Self, other: &str) -> Option<Ordering>

impl PartialOrd for Bytes

fn partial_cmp(self: &Self, other: &String) -> Option<Ordering>

impl RefUnwindSafe for Bytes

impl Send for Bytes

impl Serialize for Bytes

fn serialize<S>(self: &Self, serializer: S) -> Result<<S as >::Ok, <S as >::Error>
where
    S: Serializer

impl Sync for Bytes

impl Unpin for Bytes

impl UnsafeUnpin for Bytes

impl UnwindSafe for Bytes

impl UpperHex for Bytes

fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result

impl<'a, T: ?Sized> PartialEq for Bytes

fn eq(self: &Self, other: &&'a T) -> bool

impl<'a, T: ?Sized> PartialOrd for Bytes

fn partial_cmp(self: &Self, other: &&'a T) -> Option<Ordering>

impl<'de> Deserialize for Bytes

fn deserialize<D>(deserializer: D) -> Result<Bytes, <D as >::Error>
where
    D: Deserializer<'de>

impl<P, T> Receiver for Bytes

impl<T> Any for Bytes

fn type_id(self: &Self) -> TypeId

impl<T> Borrow for Bytes

fn borrow(self: &Self) -> &T

impl<T> BorrowMut for Bytes

fn borrow_mut(self: &mut Self) -> &mut T

impl<T> CloneToUninit for Bytes

unsafe fn clone_to_uninit(self: &Self, dest: *mut u8)

impl<T> DeserializeOwned for Bytes

impl<T> From for Bytes

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> ToOwned for Bytes

fn to_owned(self: &Self) -> T
fn clone_into(self: &Self, target: &mut T)

impl<T, U> Into for Bytes

fn into(self: Self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

impl<T, U> TryFrom for Bytes

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

impl<T, U> TryInto for Bytes

fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>