Skip to main content

substrate_data/wire/io/
framing.rs

1//! Frames written and read with their length in front.
2
3use std::io::{self, Read, Write};
4
5use crate::Schema;
6
7/// How a frame's length is written.
8pub type Len = u32;
9/// The longest frame read: anything longer is a broken or hostile peer.
10pub const MAX_FRAME: usize = 256 << 20;
11
12/// Writes `message` as one frame, and flushes.
13///
14/// # Errors
15///
16/// The writer's I/O error.
17pub fn write_frame<T: Schema>(w: &mut impl Write, message: &T) -> io::Result<()> {
18    write_frame_bytes(w, &crate::to_bytes(message))
19}
20
21/// Writes `bytes` (a message's binary form) as one frame, and flushes.
22///
23/// # Errors
24///
25/// The writer's I/O error; [`io::ErrorKind::InvalidInput`] for a frame over [`MAX_FRAME`].
26pub fn write_frame_bytes(w: &mut impl Write, bytes: &[u8]) -> io::Result<()> {
27    let len = Len::try_from(bytes.len())
28        .ok()
29        .filter(|_| bytes.len() <= MAX_FRAME)
30        .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "frame too long"))?;
31    // One write: a reader never sees a length without its body behind it.
32    let mut frame = Vec::with_capacity(size_of::<Len>() + bytes.len());
33    frame.extend_from_slice(&len.to_le_bytes());
34    frame.extend_from_slice(bytes);
35    w.write_all(&frame)?;
36    w.flush()
37}
38
39/// The next frame's bytes; `None` where the stream ends between frames.
40///
41/// # Errors
42///
43/// The reader's I/O error; [`io::ErrorKind::InvalidData`] for a length over [`MAX_FRAME`].
44pub fn read_frame_bytes(r: &mut impl Read) -> io::Result<Option<Vec<u8>>> {
45    let mut len = [0; size_of::<Len>()];
46    match r.read_exact(&mut len) {
47        Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => return Ok(None),
48        other => other?,
49    }
50    let len = Len::from_le_bytes(len) as usize;
51    if len > MAX_FRAME {
52        return Err(io::Error::new(io::ErrorKind::InvalidData, "frame too long"));
53    }
54    let mut bytes = vec![0; len];
55    r.read_exact(&mut bytes)?;
56    Ok(Some(bytes))
57}
58
59/// The next message; `None` where the stream ends between frames.
60///
61/// # Errors
62///
63/// The reader's I/O error, or [`io::ErrorKind::InvalidData`] for a frame that isn't a `T`.
64pub fn read_frame<T: Schema>(r: &mut impl Read) -> io::Result<Option<T>> {
65    let Some(bytes) = read_frame_bytes(r)? else {
66        return Ok(None);
67    };
68    crate::read_bytes(&bytes)
69        .map(Some)
70        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, crate::Errors(e)))
71}