libaprs_engine/
transport.rs1use std::io::{self, Read};
2
3pub const DEFAULT_TRANSPORT_READ_LIMIT: usize = 1024 * 1024;
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub enum TransportErrorCode {
9 OversizedInput,
11 InvalidFrame,
13 UnexpectedEof,
15 Timeout,
17 Io,
19}
20
21impl TransportErrorCode {
22 #[must_use]
24 pub const fn code(self) -> &'static str {
25 match self {
26 Self::OversizedInput => "transport.oversized_input",
27 Self::InvalidFrame => "transport.invalid_frame",
28 Self::UnexpectedEof => "transport.unexpected_eof",
29 Self::Timeout => "transport.timeout",
30 Self::Io => "transport.io",
31 }
32 }
33}
34
35pub trait PacketSource {
37 type Error;
39
40 fn recv_packets(&mut self) -> Result<Vec<Vec<u8>>, Self::Error>;
42}
43
44pub trait PacketSink {
46 type Error;
48
49 fn send_packet(&mut self, packet: &[u8]) -> Result<(), Self::Error>;
51}
52
53pub fn read_all_with_limit(mut reader: impl Read, max_bytes: usize) -> io::Result<Vec<u8>> {
55 let mut input = Vec::new();
56 let mut limited = (&mut reader).take(max_bytes.saturating_add(1) as u64);
57 limited.read_to_end(&mut input)?;
58 if input.len() > max_bytes {
59 return Err(oversized_input_error());
60 }
61 Ok(input)
62}
63
64#[must_use]
66pub fn oversized_input_error() -> io::Error {
67 io::Error::new(
68 io::ErrorKind::InvalidData,
69 TransportErrorCode::OversizedInput.code(),
70 )
71}
72
73#[derive(Clone, Debug, Eq, PartialEq)]
75pub struct LineTransport<'a> {
76 input: &'a [u8],
77}
78
79impl<'a> LineTransport<'a> {
80 #[must_use]
82 pub fn new(input: &'a [u8]) -> Self {
83 Self { input }
84 }
85
86 #[must_use]
88 pub fn packets(&self) -> Vec<&'a [u8]> {
89 self.input
90 .split(|byte| *byte == b'\n')
91 .map(trim_trailing_carriage_return)
92 .filter(|line| !line.is_empty())
93 .collect()
94 }
95}
96
97impl PacketSource for LineTransport<'_> {
98 type Error = io::Error;
99
100 fn recv_packets(&mut self) -> Result<Vec<Vec<u8>>, Self::Error> {
101 Ok(self.packets().into_iter().map(<[u8]>::to_vec).collect())
102 }
103}
104
105impl PacketSink for Vec<Vec<u8>> {
106 type Error = io::Error;
107
108 fn send_packet(&mut self, packet: &[u8]) -> Result<(), Self::Error> {
109 self.push(packet.to_vec());
110 Ok(())
111 }
112}
113
114fn trim_trailing_carriage_return(line: &[u8]) -> &[u8] {
115 line.strip_suffix(b"\r").unwrap_or(line)
116}