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
80
81
82
83
84
85
86
87
88
//! 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::{Buf, BufMut, Bytes};
//! use chunked_bytes::ChunkedBytes;
//! use std::io::{self, IoSlice, Read, Write};
//! use std::net::{SocketAddr, TcpListener, TcpStream, Shutdown};
//! use std::thread;
//!
//! fn write_vectored<W: Write>(
//! buf: &mut ChunkedBytes,
//! mut out: W,
//! ) -> io::Result<usize> {
//! let mut io_bufs = [IoSlice::new(&[]); 32];
//! let io_vec_len = buf.chunks_vectored(&mut io_bufs);
//! let bytes_written = out.write_vectored(&io_bufs[..io_vec_len])?;
//! buf.advance(bytes_written);
//! Ok(bytes_written)
//! }
//!
//! 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 server = TcpListener::bind(listen_addr)?;
//! let server_addr = server.local_addr()?;
//!
//! let server_handle: thread::JoinHandle<io::Result<()>> =
//! thread::spawn(move || {
//! let (mut receiver, _) = server.accept()?;
//! let mut buf = Vec::with_capacity(64);
//! receiver.read_to_end(&mut buf)?;
//! assert_eq!(buf.as_slice(), MESSAGE);
//! Ok(())
//! });
//!
//! let mut sender = TcpStream::connect(server_addr)?;
//!
//! let mut buf = ChunkedBytes::with_chunk_size_hint(4096);
//!
//! buf.put("I ".as_bytes());
//! buf.put_bytes(Bytes::from("🖤 "));
//! buf.put_u32(0xc0ffee);
//!
//! let bytes_written = write_vectored(&mut buf, &mut sender)?;
//! assert_eq!(bytes_written, MESSAGE.len());
//!
//! sender.shutdown(Shutdown::Write)?;
//!
//! server_handle.join().expect("server thread panicked")?;
//! Ok(())
//! }
pub use ;
pub use ChunkedBytes;