bytes/
lib.rs

1#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
2#![doc(test(
3    no_crate_inject,
4    attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
5))]
6#![no_std]
7#![cfg_attr(docsrs, feature(doc_cfg))]
8
9//! Provides abstractions for working with bytes.
10//!
11//! The `bytes` crate provides an efficient byte buffer structure
12//! ([`Bytes`]) and traits for working with buffer
13//! implementations ([`Buf`], [`BufMut`]).
14//!
15//! # `Bytes`
16//!
17//! `Bytes` is an efficient container for storing and operating on contiguous
18//! slices of memory. It is intended for use primarily in networking code, but
19//! could have applications elsewhere as well.
20//!
21//! `Bytes` values facilitate zero-copy network programming by allowing multiple
22//! `Bytes` objects to point to the same underlying memory. This is managed by
23//! using a reference count to track when the memory is no longer needed and can
24//! be freed.
25//!
26//! A `Bytes` handle can be created directly from an existing byte store (such as `&[u8]`
27//! or `Vec<u8>`), but usually a `BytesMut` is used first and written to. For
28//! example:
29//!
30//! ```rust
31//! use bytes::{BytesMut, BufMut};
32//!
33//! let mut buf = BytesMut::with_capacity(1024);
34//! buf.put(&b"hello world"[..]);
35//! buf.put_u16(1234);
36//!
37//! let a = buf.split();
38//! assert_eq!(a, b"hello world\x04\xD2"[..]);
39//!
40//! buf.put(&b"goodbye world"[..]);
41//!
42//! let b = buf.split();
43//! assert_eq!(b, b"goodbye world"[..]);
44//!
45//! assert_eq!(buf.capacity(), 998);
46//! ```
47//!
48//! In the above example, only a single buffer of 1024 is allocated. The handles
49//! `a` and `b` will share the underlying buffer and maintain indices tracking
50//! the view into the buffer represented by the handle.
51//!
52//! See the [struct docs](`Bytes`) for more details.
53//!
54//! # `Buf`, `BufMut`
55//!
56//! These two traits provide read and write access to buffers. The underlying
57//! storage may or may not be in contiguous memory. For example, `Bytes` is a
58//! buffer that guarantees contiguous memory, but a [rope] stores the bytes in
59//! disjoint chunks. `Buf` and `BufMut` maintain cursors tracking the current
60//! position in the underlying byte storage. When bytes are read or written, the
61//! cursor is advanced.
62//!
63//! [rope]: https://en.wikipedia.org/wiki/Rope_(data_structure)
64//!
65//! ## Relation with `Read` and `Write`
66//!
67//! At first glance, it may seem that `Buf` and `BufMut` overlap in
68//! functionality with [`std::io::Read`] and [`std::io::Write`]. However, they
69//! serve different purposes. A buffer is the value that is provided as an
70//! argument to `Read::read` and `Write::write`. `Read` and `Write` may then
71//! perform a syscall, which has the potential of failing. Operations on `Buf`
72//! and `BufMut` are infallible.
73
74extern crate alloc;
75
76#[cfg(feature = "std")]
77extern crate std;
78
79pub mod buf;
80pub use crate::buf::{Buf, BufMut};
81
82mod bytes;
83mod bytes_mut;
84mod fmt;
85mod loom;
86pub use crate::bytes::Bytes;
87pub use crate::bytes_mut::BytesMut;
88
89// Optional Serde support
90#[cfg(feature = "serde")]
91mod serde;
92
93#[inline(never)]
94#[cold]
95fn abort() -> ! {
96    #[cfg(feature = "std")]
97    {
98        std::process::abort();
99    }
100
101    #[cfg(not(feature = "std"))]
102    {
103        struct Abort;
104        impl Drop for Abort {
105            fn drop(&mut self) {
106                panic!();
107            }
108        }
109        let _a = Abort;
110        panic!("abort");
111    }
112}
113
114#[inline(always)]
115#[cfg(feature = "std")]
116fn saturating_sub_usize_u64(a: usize, b: u64) -> usize {
117    match usize::try_from(b) {
118        Ok(b) => a.saturating_sub(b),
119        Err(_) => 0,
120    }
121}
122
123#[inline(always)]
124#[cfg(feature = "std")]
125fn min_u64_usize(a: u64, b: usize) -> usize {
126    match usize::try_from(a) {
127        Ok(a) => usize::min(a, b),
128        Err(_) => b,
129    }
130}
131
132/// Error type for the `try_get_` methods of [`Buf`].
133/// Indicates that there were not enough remaining
134/// bytes in the buffer while attempting
135/// to get a value from a [`Buf`] with one
136/// of the `try_get_` methods.
137#[derive(Debug, PartialEq, Eq)]
138pub struct TryGetError {
139    /// The number of bytes necessary to get the value
140    pub requested: usize,
141
142    /// The number of bytes available in the buffer
143    pub available: usize,
144}
145
146impl core::fmt::Display for TryGetError {
147    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
148        write!(
149            f,
150            "Not enough bytes remaining in buffer to read value (requested {} but only {} available)",
151            self.requested,
152            self.available
153        )
154    }
155}
156
157#[cfg(feature = "std")]
158impl std::error::Error for TryGetError {}
159
160#[cfg(feature = "std")]
161impl From<TryGetError> for std::io::Error {
162    fn from(error: TryGetError) -> Self {
163        std::io::Error::new(std::io::ErrorKind::Other, error)
164    }
165}
166
167/// Panic with a nice error message.
168#[cold]
169fn panic_advance(error_info: &TryGetError) -> ! {
170    panic!(
171        "advance out of bounds: the len is {} but advancing by {}",
172        error_info.available, error_info.requested
173    );
174}
175
176#[cold]
177fn panic_does_not_fit(size: usize, nbytes: usize) -> ! {
178    panic!(
179        "size too large: the integer type can fit {} bytes, but nbytes is {}",
180        size, nbytes
181    );
182}