| #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)] |
| #![doc(test( |
| no_crate_inject, |
| attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) |
| ))] |
| #![no_std] |
| #![cfg_attr(docsrs, feature(doc_cfg))] |
| |
| //! Provides abstractions for working with bytes. |
| //! |
| //! The `bytes` crate provides an efficient byte buffer structure |
| //! ([`Bytes`]) and traits for working with buffer |
| //! implementations ([`Buf`], [`BufMut`]). |
| //! |
| //! # `Bytes` |
| //! |
| //! `Bytes` is an efficient container for storing and operating on contiguous |
| //! slices of memory. It is intended for use primarily in networking code, but |
| //! could have applications elsewhere as well. |
| //! |
| //! `Bytes` values facilitate zero-copy network programming by allowing multiple |
| //! `Bytes` objects to point to the same underlying memory. This is managed by |
| //! using a reference count to track when the memory is no longer needed and can |
| //! be freed. |
| //! |
| //! A `Bytes` handle can be created directly from an existing byte store (such as `&[u8]` |
| //! or `Vec<u8>`), but usually a `BytesMut` is used first and written to. For |
| //! example: |
| //! |
| //! ```rust |
| //! use bytes::{BytesMut, BufMut}; |
| //! |
| //! let mut buf = BytesMut::with_capacity(1024); |
| //! buf.put(&b"hello world"[..]); |
| //! buf.put_u16(1234); |
| //! |
| //! let a = buf.split(); |
| //! assert_eq!(a, b"hello world\x04\xD2"[..]); |
| //! |
| //! buf.put(&b"goodbye world"[..]); |
| //! |
| //! let b = buf.split(); |
| //! assert_eq!(b, b"goodbye world"[..]); |
| //! |
| //! assert_eq!(buf.capacity(), 998); |
| //! ``` |
| //! |
| //! In the above example, only a single buffer of 1024 is allocated. The handles |
| //! `a` and `b` will share the underlying buffer and maintain indices tracking |
| //! the view into the buffer represented by the handle. |
| //! |
| //! See the [struct docs](`Bytes`) for more details. |
| //! |
| //! # `Buf`, `BufMut` |
| //! |
| //! These two traits provide read and write access to buffers. The underlying |
| //! storage may or may not be in contiguous memory. For example, `Bytes` is a |
| //! buffer that guarantees contiguous memory, but a [rope] stores the bytes in |
| //! disjoint chunks. `Buf` and `BufMut` maintain cursors tracking the current |
| //! position in the underlying byte storage. When bytes are read or written, the |
| //! cursor is advanced. |
| //! |
| //! [rope]: https://en.wikipedia.org/wiki/Rope_(data_structure) |
| //! |
| //! ## Relation with `Read` and `Write` |
| //! |
| //! At first glance, it may seem that `Buf` and `BufMut` overlap in |
| //! functionality with [`std::io::Read`] and [`std::io::Write`]. However, they |
| //! serve different purposes. A buffer is the value that is provided as an |
| //! argument to `Read::read` and `Write::write`. `Read` and `Write` may then |
| //! perform a syscall, which has the potential of failing. Operations on `Buf` |
| //! and `BufMut` are infallible. |
| |
| extern crate alloc; |
| |
| #[cfg(feature = "std")] |
| extern crate std; |
| |
| pub mod buf; |
| pub use crate::buf::{Buf, BufMut}; |
| |
| mod bytes; |
| mod bytes_mut; |
| mod fmt; |
| mod loom; |
| pub use crate::bytes::Bytes; |
| pub use crate::bytes_mut::BytesMut; |
| |
| // Optional Serde support |
| #[cfg(feature = "serde")] |
| mod serde; |
| |
| #[inline(never)] |
| #[cold] |
| fn abort() -> ! { |
| #[cfg(feature = "std")] |
| { |
| std::process::abort(); |
| } |
| |
| #[cfg(not(feature = "std"))] |
| { |
| struct Abort; |
| impl Drop for Abort { |
| fn drop(&mut self) { |
| panic!(); |
| } |
| } |
| let _a = Abort; |
| panic!("abort"); |
| } |
| } |
| |
| #[inline(always)] |
| #[cfg(feature = "std")] |
| fn saturating_sub_usize_u64(a: usize, b: u64) -> usize { |
| use core::convert::TryFrom; |
| match usize::try_from(b) { |
| Ok(b) => a.saturating_sub(b), |
| Err(_) => 0, |
| } |
| } |
| |
| #[inline(always)] |
| #[cfg(feature = "std")] |
| fn min_u64_usize(a: u64, b: usize) -> usize { |
| use core::convert::TryFrom; |
| match usize::try_from(a) { |
| Ok(a) => usize::min(a, b), |
| Err(_) => b, |
| } |
| } |
| |
| /// Panic with a nice error message. |
| #[cold] |
| fn panic_advance(idx: usize, len: usize) -> ! { |
| panic!( |
| "advance out of bounds: the len is {} but advancing by {}", |
| len, idx |
| ); |
| } |
| |
| #[cold] |
| fn panic_does_not_fit(size: usize, nbytes: usize) -> ! { |
| panic!( |
| "size too large: the integer type can fit {} bytes, but nbytes is {}", |
| size, nbytes |
| ); |
| } |