1pub struct Reader<'a> {
11 pub data: &'a [u8],
12 pub pos: usize,
13}
14
15impl<'a> Reader<'a> {
16 pub fn new(data: &'a [u8]) -> Self {
17 Self { data, pos: 0 }
18 }
19
20 pub fn remaining(&self) -> &'a [u8] {
21 &self.data[self.pos..]
22 }
23
24 fn need(&self, n: usize) -> Result<(), DecodeErr> {
25 if self.pos + n > self.data.len() {
26 Err(DecodeErr::Eof)
27 } else {
28 Ok(())
29 }
30 }
31
32 pub fn read_u8(&mut self) -> Result<u8, DecodeErr> {
33 self.need(1)?;
34 let v = self.data[self.pos];
35 self.pos += 1;
36 Ok(v)
37 }
38
39 pub fn read_u32_le(&mut self) -> Result<u32, DecodeErr> {
40 self.need(4)?;
41 let v = u32::from_le_bytes(self.data[self.pos..self.pos + 4].try_into().unwrap());
42 self.pos += 4;
43 Ok(v)
44 }
45
46 pub fn read_raw(&mut self, n: usize) -> Result<&'a [u8], DecodeErr> {
47 self.need(n)?;
48 let v = &self.data[self.pos..self.pos + n];
49 self.pos += n;
50 Ok(v)
51 }
52
53 pub fn read_compact_u32(&mut self) -> Result<u32, DecodeErr> {
55 let first = self.read_u8()? as u32;
56 match first & 0b11 {
57 0b00 => Ok(first >> 2),
58 0b01 => {
59 let second = self.read_u8()? as u32;
60 Ok(((first | (second << 8)) >> 2) & 0x3FFF)
61 }
62 0b10 => {
63 self.need(3)?;
64 let b1 = self.data[self.pos] as u32;
65 let b2 = self.data[self.pos + 1] as u32;
66 let b3 = self.data[self.pos + 2] as u32;
67 self.pos += 3;
68 let val = first | (b1 << 8) | (b2 << 16) | (b3 << 24);
69 Ok(val >> 2)
70 }
71 0b11 => {
72 let byte_count = (first >> 2) + 4;
73 if byte_count > 4 {
74 return Err(DecodeErr::CompactTooLarge);
75 }
76 let mut val = 0u32;
77 for i in 0..byte_count as usize {
78 val |= (self.read_u8()? as u32) << (i * 8);
79 }
80 Ok(val)
81 }
82 _ => unreachable!(),
83 }
84 }
85
86 pub fn read_string(&mut self) -> Result<String, DecodeErr> {
88 let len = self.read_compact_u32()? as usize;
89 let bytes = self.read_raw(len)?;
90 String::from_utf8(bytes.to_vec()).map_err(|_| DecodeErr::InvalidUtf8)
91 }
92
93 pub fn read_var_bytes(&mut self) -> Result<Vec<u8>, DecodeErr> {
95 let len = self.read_compact_u32()? as usize;
96 Ok(self.read_raw(len)?.to_vec())
97 }
98
99 pub fn read_fixed_bytes(&mut self, n: usize) -> Result<Vec<u8>, DecodeErr> {
101 Ok(self.read_raw(n)?.to_vec())
102 }
103
104 pub fn read_option<T>(
106 &mut self,
107 f: impl FnOnce(&mut Self) -> Result<T, DecodeErr>,
108 ) -> Result<Option<T>, DecodeErr> {
109 match self.read_u8()? {
110 0 => Ok(None),
111 1 => f(self).map(Some),
112 _ => Err(DecodeErr::InvalidOption),
113 }
114 }
115
116 pub fn skip_rest(&mut self) {
118 self.pos = self.data.len();
119 }
120}
121
122#[derive(Debug)]
123pub enum DecodeErr {
124 Eof,
125 CompactTooLarge,
126 InvalidUtf8,
127 InvalidOption,
128 InvalidTag(u8),
129 BadMessage(&'static str),
130 UnknownProtocol,
131}
132
133impl std::fmt::Display for DecodeErr {
134 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135 match self {
136 Self::Eof => write!(f, "unexpected end of input"),
137 Self::CompactTooLarge => write!(f, "compact integer exceeds u32"),
138 Self::InvalidUtf8 => write!(f, "invalid UTF-8 in string"),
139 Self::InvalidOption => write!(f, "invalid option discriminant"),
140 Self::InvalidTag(t) => write!(f, "invalid tag: {t}"),
141 Self::BadMessage(msg) => write!(f, "{msg}"),
142 Self::UnknownProtocol => {
143 write!(f, "message does not start with protocol discriminator 0x01")
144 }
145 }
146 }
147}
148
149impl std::error::Error for DecodeErr {}
150
151pub fn encode_compact_u32(buf: &mut Vec<u8>, val: u32) {
157 if val < 0x40 {
158 buf.push((val as u8) << 2);
159 } else if val < 0x4000 {
160 let v = (val << 2) | 0b01;
161 buf.push(v as u8);
162 buf.push((v >> 8) as u8);
163 } else if val < 0x4000_0000 {
164 let v = (val << 2) | 0b10;
165 buf.push(v as u8);
166 buf.push((v >> 8) as u8);
167 buf.push((v >> 16) as u8);
168 buf.push((v >> 24) as u8);
169 } else {
170 buf.push(0b11); buf.push(val as u8);
172 buf.push((val >> 8) as u8);
173 buf.push((val >> 16) as u8);
174 buf.push((val >> 24) as u8);
175 }
176}
177
178pub fn encode_string(buf: &mut Vec<u8>, s: &str) {
180 encode_compact_u32(buf, s.len() as u32);
181 buf.extend_from_slice(s.as_bytes());
182}
183
184pub fn encode_tag(buf: &mut Vec<u8>, tag: u8) {
186 buf.push(tag);
187}
188
189pub fn encode_result_ok_void(buf: &mut Vec<u8>) {
191 buf.push(0x00);
192}
193
194pub fn encode_result_ok(buf: &mut Vec<u8>) {
196 buf.push(0x00);
197}
198
199pub fn encode_result_err(buf: &mut Vec<u8>) {
201 buf.push(0x01);
202}
203
204pub fn encode_var_bytes(buf: &mut Vec<u8>, data: &[u8]) {
206 encode_compact_u32(buf, data.len() as u32);
207 buf.extend_from_slice(data);
208}
209
210pub fn encode_option_none(buf: &mut Vec<u8>) {
212 buf.push(0x00);
213}
214
215pub fn encode_option_some(buf: &mut Vec<u8>) {
217 buf.push(0x01);
218}
219
220pub fn encode_vector_len(buf: &mut Vec<u8>, count: u32) {
222 encode_compact_u32(buf, count);
223}
224
225#[cfg(test)]
226mod tests {
227 use super::*;
228
229 #[test]
230 fn compact_round_trip() {
231 for val in [0u32, 1, 63, 64, 16383, 16384, 1_073_741_823, u32::MAX] {
232 let mut buf = Vec::new();
233 encode_compact_u32(&mut buf, val);
234 let mut r = Reader::new(&buf);
235 let decoded = r.read_compact_u32().unwrap();
236 assert_eq!(val, decoded, "compact round-trip failed for {val}");
237 assert_eq!(r.pos, buf.len());
238 }
239 }
240
241 #[test]
242 fn string_round_trip() {
243 for s in [
244 "",
245 "hello",
246 "dot://mytestapp.dot",
247 "a".repeat(1000).as_str(),
248 ] {
249 let mut buf = Vec::new();
250 encode_string(&mut buf, s);
251 let mut r = Reader::new(&buf);
252 let decoded = r.read_string().unwrap();
253 assert_eq!(s, decoded);
254 }
255 }
256
257 #[test]
258 fn var_bytes_round_trip() {
259 let data = vec![0xde, 0xad, 0xbe, 0xef];
260 let mut buf = Vec::new();
261 encode_var_bytes(&mut buf, &data);
262 let mut r = Reader::new(&buf);
263 let decoded = r.read_var_bytes().unwrap();
264 assert_eq!(data, decoded);
265 }
266
267 #[test]
268 fn var_bytes_empty() {
269 let mut buf = Vec::new();
270 encode_var_bytes(&mut buf, &[]);
271 assert_eq!(buf, vec![0x00]); let mut r = Reader::new(&buf);
273 let decoded = r.read_var_bytes().unwrap();
274 assert!(decoded.is_empty());
275 }
276
277 #[test]
278 fn reader_eof_on_empty() {
279 let mut r = Reader::new(&[]);
280 assert!(r.read_u8().is_err());
281 assert!(r.read_string().is_err());
282 assert!(r.read_compact_u32().is_err());
283 }
284
285 #[test]
286 fn reader_truncated_string() {
287 let mut buf = Vec::new();
289 encode_compact_u32(&mut buf, 10);
290 buf.extend_from_slice(b"abc");
291 let mut r = Reader::new(&buf);
292 assert!(r.read_string().is_err());
293 }
294}