Coverage Report

Created: 2026-07-16 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/lib.rs
Line
Count
Source
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
74
extern crate alloc;
75
76
#[cfg(feature = "std")]
77
extern crate std;
78
79
pub mod buf;
80
pub use crate::buf::{Buf, BufMut};
81
82
mod bytes;
83
mod bytes_mut;
84
mod fmt;
85
mod loom;
86
pub use crate::bytes::Bytes;
87
pub use crate::bytes_mut::BytesMut;
88
89
// Optional Serde support
90
#[cfg(feature = "serde")]
91
mod serde;
92
93
#[inline(never)]
94
#[cold]
95
0
fn abort() -> ! {
96
    #[cfg(feature = "std")]
97
    {
98
0
        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")]
116
0
fn saturating_sub_usize_u64(a: usize, b: u64) -> usize {
117
0
    match usize::try_from(b) {
118
0
        Ok(b) => a.saturating_sub(b),
119
0
        Err(_) => 0,
120
    }
121
0
}
122
123
#[inline(always)]
124
#[cfg(feature = "std")]
125
0
fn min_u64_usize(a: u64, b: usize) -> usize {
126
0
    match usize::try_from(a) {
127
0
        Ok(a) => usize::min(a, b),
128
0
        Err(_) => b,
129
    }
130
0
}
131
132
/// Performs bounds checking of a range.
133
///
134
/// This is a spiritual copy of [core::slice::index::range] because that
135
/// function is currently unstable.
136
#[inline(always)]
137
#[track_caller]
138
0
fn range(range: impl core::ops::RangeBounds<usize>, len: usize) -> (usize, usize) {
139
    use core::ops::Bound;
140
141
0
    let begin = match range.start_bound() {
142
0
        Bound::Included(&n) => n,
143
0
        Bound::Excluded(&n) => n.checked_add(1).expect("out of range"),
144
0
        Bound::Unbounded => 0,
145
    };
146
147
0
    let end = match range.end_bound() {
148
0
        Bound::Included(&n) => n.checked_add(1).expect("out of range"),
149
0
        Bound::Excluded(&n) => n,
150
0
        Bound::Unbounded => len,
151
    };
152
153
0
    assert!(
154
0
        begin <= end,
155
0
        "range start must not be greater than end: {:?} <= {:?}",
156
        begin,
157
        end,
158
    );
159
0
    assert!(
160
0
        end <= len,
161
0
        "range end out of bounds: {:?} <= {:?}",
162
        end,
163
        len,
164
    );
165
166
0
    (begin, end)
167
0
}
168
169
/// Error type for the `try_get_` methods of [`Buf`].
170
/// Indicates that there were not enough remaining
171
/// bytes in the buffer while attempting
172
/// to get a value from a [`Buf`] with one
173
/// of the `try_get_` methods.
174
#[derive(Debug, PartialEq, Eq)]
175
pub struct TryGetError {
176
    /// The number of bytes necessary to get the value
177
    pub requested: usize,
178
179
    /// The number of bytes available in the buffer
180
    pub available: usize,
181
}
182
183
impl core::fmt::Display for TryGetError {
184
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
185
0
        write!(
186
0
            f,
187
0
            "Not enough bytes remaining in buffer to read value (requested {} but only {} available)",
188
            self.requested,
189
            self.available
190
        )
191
0
    }
192
}
193
194
#[cfg(feature = "std")]
195
impl std::error::Error for TryGetError {}
196
197
#[cfg(feature = "std")]
198
impl From<TryGetError> for std::io::Error {
199
0
    fn from(error: TryGetError) -> Self {
200
0
        std::io::Error::new(std::io::ErrorKind::Other, error)
201
0
    }
202
}
203
204
/// Panic with a nice error message.
205
#[cold]
206
0
fn panic_advance(error_info: &TryGetError) -> ! {
207
0
    panic!(
208
0
        "advance out of bounds: the len is {} but advancing by {}",
209
        error_info.available, error_info.requested
210
    );
211
}
212
213
#[cold]
214
0
fn panic_does_not_fit(size: usize, nbytes: usize) -> ! {
215
0
    panic!(
216
0
        "size too large: the integer type can fit {} bytes, but nbytes is {}",
217
        size, nbytes
218
    );
219
}