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]
abort() -> !95 fn 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")]
saturating_sub_usize_u64(a: usize, b: u64) -> usize116 fn 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")]
min_u64_usize(a: u64, b: usize) -> usize126 fn 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 /// Panic with a nice error message.
135 #[cold]
panic_advance(idx: usize, len: usize) -> !136 fn panic_advance(idx: usize, len: usize) -> ! {
137 panic!(
138 "advance out of bounds: the len is {} but advancing by {}",
139 len, idx
140 );
141 }
142
143 #[cold]
panic_does_not_fit(size: usize, nbytes: usize) -> !144 fn panic_does_not_fit(size: usize, nbytes: usize) -> ! {
145 panic!(
146 "size too large: the integer type can fit {} bytes, but nbytes is {}",
147 size, nbytes
148 );
149 }
150