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