1#![deny(missing_docs)]
9
10use gbp::{CodecError, GbpFrame};
11use tokio::io::{AsyncReadExt, AsyncWriteExt};
12use tokio::net::TcpStream;
13
14pub const MAX_FRAME: usize = 1 << 20;
16
17#[derive(Debug, thiserror::Error)]
19pub enum WireError {
20 #[error("io: {0}")]
22 Io(#[from] std::io::Error),
23 #[error("codec: {0}")]
25 Codec(#[from] CodecError),
26 #[error("frame too large: {size} bytes (max {max})")]
28 TooLarge {
29 size: usize,
31 max: usize,
33 },
34}
35
36impl WireError {
37 fn too_large(n: usize) -> Self {
38 Self::TooLarge {
39 size: n,
40 max: MAX_FRAME,
41 }
42 }
43}
44
45pub async fn write_frame(stream: &mut TcpStream, frame: &GbpFrame) -> Result<(), WireError> {
47 let bytes = frame.to_cbor();
48 write_blob(stream, &bytes).await
49}
50
51pub async fn read_frame(stream: &mut TcpStream) -> Result<GbpFrame, WireError> {
53 let buf = read_blob(stream).await?;
54 Ok(GbpFrame::from_cbor(&buf)?)
55}
56
57pub async fn write_blob(stream: &mut TcpStream, data: &[u8]) -> Result<(), WireError> {
60 if data.len() > MAX_FRAME {
61 return Err(WireError::too_large(data.len()));
62 }
63 let len = (data.len() as u32).to_le_bytes();
64 stream.write_all(&len).await?;
65 stream.write_all(data).await?;
66 stream.flush().await?;
67 Ok(())
68}
69
70pub async fn read_blob(stream: &mut TcpStream) -> Result<Vec<u8>, WireError> {
72 let mut len_buf = [0u8; 4];
73 stream.read_exact(&mut len_buf).await?;
74 let len = u32::from_le_bytes(len_buf) as usize;
75 if len > MAX_FRAME {
76 return Err(WireError::too_large(len));
77 }
78 let mut buf = vec![0u8; len];
79 stream.read_exact(&mut buf).await?;
80 Ok(buf)
81}