1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
//! A non-contiguous buffer for efficient serialization of data structures //! and vectored output. //! //! This crate provides `ChunkedBytes`, a [rope]-like byte container based on //! `Bytes` and `BytesMut` from the `bytes` crate. Its primary purpose is to //! serve as an intermediate buffer for serializing fields of data structures //! into byte sequences of varying length, without whole-buffer reallocations //! like those performed to grow a `Vec`, and then consuming the bytes in bulk, //! split into regularly sized chunks suitable for [vectored output]. //! //! [rope]: https://en.wikipedia.org/wiki/Rope_(data_structure) //! [vectored output]: https://en.wikipedia.org/wiki/Vectored_I/O //! //! `ChunkedBytes` implements the traits `Buf` and `BufMut` for read and write //! access to the buffered data. It also provides the `put_bytes` method //! for appending a `Bytes` slice to its queue of non-contiguous chunks without //! copying the data. //! //! # Examples //! //! ``` //! use bytes::{BufMut, Bytes}; //! use chunked_bytes::ChunkedBytes; //! use std::net::SocketAddr; //! use tokio::io::AsyncWriteExt; //! use tokio::net::{TcpListener, TcpStream}; //! use tokio::task::JoinHandle; //! use tokio::prelude::*; //! //! #[tokio::main] //! async fn main() -> io::Result<()> { //! const MESSAGE: &[u8] = b"I \xf0\x9f\x96\xa4 \x00\xc0\xff\xee"; //! //! let listen_addr = "127.0.0.1:0".parse::<SocketAddr>().unwrap(); //! let mut server = TcpListener::bind(listen_addr).await?; //! let server_addr = server.local_addr()?; //! //! let server_handle: JoinHandle<io::Result<()>> = tokio::spawn(async move { //! let (mut receiver, _) = server.accept().await?; //! let mut buf = Vec::with_capacity(64); //! receiver.read_to_end(&mut buf).await?; //! assert_eq!(buf.as_slice(), MESSAGE); //! Ok(()) //! }); //! //! let mut sender = TcpStream::connect(server_addr).await?; //! //! let buf_size = sender.send_buffer_size()?; //! let mut buf = ChunkedBytes::with_chunk_size_hint(buf_size); //! //! buf.put("I ".as_bytes()); //! buf.put_bytes(Bytes::from("🖤 ")); //! buf.put_u32(0xc0ffee); //! //! let bytes_written = sender.write_buf(&mut buf).await?; //! assert_eq!(bytes_written, MESSAGE.len()); //! AsyncWriteExt::shutdown(&mut sender).await?; //! //! server_handle.await??; //! Ok(()) //! } #![warn(clippy::all)] #![warn(future_incompatible)] #![warn(missing_docs)] #![warn(rust_2018_idioms)] #![doc(test(no_crate_inject, attr(deny(warnings, rust_2018_idioms))))] pub mod loosely; pub mod strictly; mod chunked; mod iter; pub use self::iter::{DrainChunks, IntoChunks}; pub use self::loosely::ChunkedBytes; #[cfg(test)] mod tests;