1use alloc::vec::Vec;
8
9use crate::err::{Error, Result};
10
11pub const MAX_DATA_LEN: usize = 65_516;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum Pkt<'a> {
16 Flush,
17 Delim,
18 ResponseEnd,
19 Data(&'a [u8]),
20}
21
22pub struct PktReader<'a> {
24 rest: &'a [u8],
25}
26
27impl<'a> PktReader<'a> {
28 pub fn new(data: &'a [u8]) -> Self {
29 Self { rest: data }
30 }
31
32 pub fn rest(&self) -> &'a [u8] {
34 self.rest
35 }
36
37 #[allow(clippy::should_implement_trait)]
39 pub fn next(&mut self) -> Option<Result<Pkt<'a>>> {
40 if self.rest.is_empty() {
41 return None;
42 }
43 Some(self.read_one())
44 }
45
46 pub fn expect_next(&mut self) -> Result<Pkt<'a>> {
48 self.next().unwrap_or(Err(Error::UnexpectedEof))
49 }
50
51 fn read_one(&mut self) -> Result<Pkt<'a>> {
52 let head = self.rest.get(..4).ok_or(Error::UnexpectedEof)?;
53 let mut len = 0usize;
54 for &c in head {
55 let v = match c {
56 b'0'..=b'9' => c - b'0',
57 b'a'..=b'f' => c - b'a' + 10,
58 b'A'..=b'F' => c - b'A' + 10,
59 _ => return Err(Error::Corrupt("pkt-line length")),
60 };
61 len = len * 16 + usize::from(v);
62 }
63 match len {
64 0 => {
65 self.rest = &self.rest[4..];
66 Ok(Pkt::Flush)
67 }
68 1 => {
69 self.rest = &self.rest[4..];
70 Ok(Pkt::Delim)
71 }
72 2 => {
73 self.rest = &self.rest[4..];
74 Ok(Pkt::ResponseEnd)
75 }
76 3 => Err(Error::Corrupt("pkt-line length 0003")),
77 _ => {
78 let data = self.rest.get(4..len).ok_or(Error::UnexpectedEof)?;
79 self.rest = &self.rest[len..];
80 Ok(Pkt::Data(data))
81 }
82 }
83 }
84}
85
86pub fn write_data(out: &mut Vec<u8>, data: &[u8]) {
88 debug_assert!(data.len() <= MAX_DATA_LEN);
89 let len = data.len() + 4;
90 const HEX: &[u8; 16] = b"0123456789abcdef";
91 out.push(HEX[(len >> 12) & 0xf]);
92 out.push(HEX[(len >> 8) & 0xf]);
93 out.push(HEX[(len >> 4) & 0xf]);
94 out.push(HEX[len & 0xf]);
95 out.extend_from_slice(data);
96}
97
98pub fn write_line(out: &mut Vec<u8>, line: &[u8]) {
100 debug_assert!(line.len() < MAX_DATA_LEN);
101 let len = line.len() + 5;
102 const HEX: &[u8; 16] = b"0123456789abcdef";
103 out.push(HEX[(len >> 12) & 0xf]);
104 out.push(HEX[(len >> 8) & 0xf]);
105 out.push(HEX[(len >> 4) & 0xf]);
106 out.push(HEX[len & 0xf]);
107 out.extend_from_slice(line);
108 out.push(b'\n');
109}
110
111pub fn write_flush(out: &mut Vec<u8>) {
112 out.extend_from_slice(b"0000");
113}
114
115pub fn write_delim(out: &mut Vec<u8>) {
116 out.extend_from_slice(b"0001");
117}
118
119pub fn trim_line(data: &[u8]) -> &[u8] {
121 data.strip_suffix(b"\n").unwrap_or(data)
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 #[test]
129 fn roundtrip() {
130 let mut buf = Vec::new();
131 write_line(&mut buf, b"version 2");
132 write_delim(&mut buf);
133 write_data(&mut buf, &[0x01, 0xff]);
134 write_flush(&mut buf);
135
136 let mut r = PktReader::new(&buf);
137 assert_eq!(r.expect_next().unwrap(), Pkt::Data(b"version 2\n"));
138 assert_eq!(r.expect_next().unwrap(), Pkt::Delim);
139 assert_eq!(r.expect_next().unwrap(), Pkt::Data(&[0x01, 0xff]));
140 assert_eq!(r.expect_next().unwrap(), Pkt::Flush);
141 assert!(r.next().is_none());
142 }
143
144 #[test]
145 fn known_encoding() {
146 let mut buf = Vec::new();
147 write_line(&mut buf, b"a");
148 assert_eq!(buf, b"0006a\n");
149 buf.clear();
150 write_flush(&mut buf);
151 assert_eq!(buf, b"0000");
152 }
153
154 #[test]
155 fn truncated_rejected() {
156 let mut r = PktReader::new(b"000");
157 assert_eq!(r.expect_next().unwrap_err(), Error::UnexpectedEof);
158 let mut r = PktReader::new(b"0010short");
159 assert_eq!(r.expect_next().unwrap_err(), Error::UnexpectedEof);
160 }
161
162 #[test]
163 fn bad_length_rejected() {
164 let mut r = PktReader::new(b"00xx");
165 assert!(r.expect_next().is_err());
166 let mut r = PktReader::new(b"0003");
167 assert!(r.expect_next().is_err());
168 }
169}