buf_list/lib.rs
1// Copyright (c) 2018 the linkerd2-proxy authors
2// Copyright (c) The buf-list Contributors
3// SPDX-License-Identifier: Apache-2.0
4
5#![forbid(unsafe_code)]
6#![warn(missing_docs)]
7#![cfg_attr(doc_cfg, feature(doc_cfg))]
8
9//! A segmented list of [`bytes::Bytes`] chunks.
10//!
11//! # Overview
12//!
13//! This crate provides a [`BufList`] type that is a list of [`Bytes`](bytes::Bytes) chunks. The
14//! type implements [`bytes::Buf`], so it can be used in any APIs that use `Buf`.
15//!
16//! The main use case for [`BufList`] is to buffer data received as a stream of chunks without
17//! having to copy them into a single contiguous chunk of memory. The [`BufList`] can then be passed
18//! into any APIs that accept `Buf`.
19//!
20//! If you've ever wanted a `Vec<Bytes>` or a `VecDeque<Bytes>`, this type is for you.
21//!
22//! # Cursors
23//!
24//! This crate also provides [`Cursor`], which is a cursor type around a
25//! [`BufList`]. Similar to similar to [`std::io::Cursor`], a [`Cursor`] around
26//! a [`BufList`] implements
27//!
28//! * [`Seek`](std::io::Seek), [`Read`](std::io::Read), and [`BufRead`](std::io::BufRead)
29//! * [`bytes::Buf`] as well (in other words, both [`BufList`]s and [`Cursor`]s over them
30//! can be passed into any APIs that accept `Buf`).
31//!
32//! # Examples
33//!
34//! Gather chunks into a `BufList`, then write them all out to standard error in one go:
35//!
36//! ```
37//! use buf_list::BufList;
38//! use tokio::io::AsyncWriteExt;
39//!
40//! # #[tokio::main(flavor = "current_thread")]
41//! # async fn main() -> Result<(), std::io::Error> {
42//! let mut buf_list = BufList::new();
43//! buf_list.push_chunk(&b"hello "[..]);
44//! buf_list.push_chunk(&b"world"[..]);
45//! buf_list.push_chunk(&b"!"[..]);
46//!
47//! let mut stderr = tokio::io::stderr();
48//! stderr.write_all_buf(&mut buf_list).await?;
49//! # Ok(()) }
50//! ```
51//!
52//! Collect a fallible stream of `Bytes` into a `BufList`:
53//!
54//! ```
55//! use buf_list::BufList;
56//! use bytes::Bytes;
57//! use futures::TryStreamExt;
58//!
59//! # #[tokio::main(flavor = "current_thread")]
60//! # async fn main() -> Result<(), ()> {
61//! // A common example is a stream of bytes read over HTTP.
62//! let stream = futures::stream::iter(
63//! vec![
64//! Ok(Bytes::from_static(&b"laputa, "[..])),
65//! Ok(Bytes::from_static(&b"castle "[..])),
66//! Ok(Bytes::from_static(&b"in the sky"[..]))
67//! ],
68//! );
69//!
70//! let buf_list = stream.try_collect::<BufList>().await?;
71//! assert_eq!(buf_list.num_chunks(), 3);
72//! # Ok(()) }
73//! ```
74//!
75//! ## Converting to `Stream`s
76//!
77//! A `BufList` can be converted into a `futures::Stream`, or a `TryStream`, of `Bytes` chunks. Use
78//! this recipe to do so:
79//!
80//! (This will be exposed as an API on `BufList` once `Stream` and/or `TryStream` become part of
81//! stable Rust.)
82//!
83//! ```rust
84//! use buf_list::BufList;
85//! use bytes::Bytes;
86//! use futures::{Stream, TryStream};
87//!
88//! fn into_stream(buf_list: BufList) -> impl Stream<Item = Bytes> {
89//! futures::stream::iter(buf_list)
90//! }
91//!
92//! fn into_try_stream<E>(buf_list: BufList) -> impl TryStream<Ok = Bytes, Error = E> {
93//! futures::stream::iter(buf_list.into_iter().map(Ok))
94//! }
95//! ```
96//!
97//! # Optional features
98//!
99//! * `tokio1`: With this feature enabled, [`Cursor`] implements the `tokio` crate's
100//! [`AsyncSeek`](tokio::io::AsyncSeek), [`AsyncRead`](tokio::io::AsyncRead) and
101//! [`AsyncBufRead`](tokio::io::AsyncBufRead).
102//!
103//! * `futures03`: With this feature enabled, [`Cursor`] implements the `futures` crate's
104//! [`AsyncSeek`](futures_io_03::AsyncSeek), [`AsyncRead`](futures_io_03::AsyncRead) and
105//! [`AsyncBufRead`](futures_io_03::AsyncBufRead).
106//!
107//! Note that supporting `futures03` means exporting 0.x types as a public interface. **This
108//! violates the
109//! [C-STABLE](https://rust-lang.github.io/api-guidelines/necessities.html#public-dependencies-of-a-stable-crate-are-stable-c-stable)
110//! guideline.** However, the maintainer of `buf-list` considers that acceptable since `futures03`
111//! is an optional feature and not critical to `buf-list`. As newer versions of the `futures`
112//! crate are released, `buf-list` will support their versions of the async traits as well.
113//!
114//! # Minimum supported Rust version
115//!
116//! The minimum supported Rust version (MSRV) is **1.70**. Optional features may
117//! cause a bump in the MSRV.
118//!
119//! `buf-list` has a conservative MSRV policy. MSRV bumps will be sparing, and
120//! if so, they will be accompanied by a minor version bump.
121
122mod cursor;
123pub(crate) mod errors;
124mod imp;
125
126pub use cursor::*;
127pub use imp::*;