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    use core::convert::TryFrom;
118    match usize::try_from(b) {
119        Ok(b) => a.saturating_sub(b),
120        Err(_) => 0,
121    }
122}
123
124#[inline(always)]
125#[cfg(feature = "std")]
126fn min_u64_usize(a: u64, b: usize) -> usize {
127    use core::convert::TryFrom;
128    match usize::try_from(a) {
129        Ok(a) => usize::min(a, b),
130        Err(_) => b,
131    }
132}
133
134/// Error type for the `try_get_` methods of [`Buf`].
135/// Indicates that there were not enough remaining
136/// bytes in the buffer while attempting
137/// to get a value from a [`Buf`] with one
138/// of the `try_get_` methods.
139#[derive(Debug, PartialEq, Eq)]
140pub struct TryGetError {
141    /// The number of bytes necessary to get the value
142    pub requested: usize,
143
144    /// The number of bytes available in the buffer
145    pub available: usize,
146}
147
148impl core::fmt::Display for TryGetError {
149    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
150        write!(
151            f,
152            "Not enough bytes remaining in buffer to read value (requested {} but only {} available)",
153            self.requested,
154            self.available
155        )
156    }
157}
158
159#[cfg(feature = "std")]
160impl std::error::Error for TryGetError {}
161
162#[cfg(feature = "std")]
163impl From<TryGetError> for std::io::Error {
164    fn from(error: TryGetError) -> Self {
165        std::io::Error::new(std::io::ErrorKind::Other, error)
166    }
167}
168
169/// Panic with a nice error message.
170#[cold]
171fn panic_advance(error_info: &TryGetError) -> ! {
172    panic!(
173        "advance out of bounds: the len is {} but advancing by {}",
174        error_info.available, error_info.requested
175    );
176}
177
178#[cold]
179fn panic_does_not_fit(size: usize, nbytes: usize) -> ! {
180    panic!(
181        "size too large: the integer type can fit {} bytes, but nbytes is {}",
182        size, nbytes
183    );
184}
185
186/// Precondition: dst >= original
187///
188/// The following line is equivalent to:
189///
190/// ```rust,ignore
191/// self.ptr.as_ptr().offset_from(ptr) as usize;
192/// ```
193///
194/// But due to min rust is 1.39 and it is only stabilized
195/// in 1.47, we cannot use it.
196#[inline]
197fn offset_from(dst: *const u8, original: *const u8) -> usize {
198    dst as usize - original as usize
199}