1use crate::{EncodeError, ParseError};
2
3#[derive(Debug)]
8pub struct OptionEncoder<'a> {
9 buf: &'a mut [u8],
10 pos: usize,
11 last_number: u16,
12 wrote_any: bool,
13}
14
15impl<'a> OptionEncoder<'a> {
16 pub fn new(buf: &'a mut [u8]) -> Self {
18 Self {
19 buf,
20 pos: 0,
21 last_number: 0,
22 wrote_any: false,
23 }
24 }
25
26 pub fn with_last_number(buf: &'a mut [u8], last_number: u16) -> Self {
28 Self {
29 buf,
30 pos: 0,
31 last_number,
32 wrote_any: true,
33 }
34 }
35
36 pub fn put(&mut self, number: u16, value: &[u8]) -> Result<(), EncodeError> {
38 if self.wrote_any && number < self.last_number {
39 return Err(EncodeError::OptionOutOfOrder);
40 }
41 let delta = if self.wrote_any {
42 number - self.last_number
43 } else {
44 number
45 };
46 let delta_len = encoded_len(delta);
47 let value_len = encoded_len(value.len() as u16);
48 let required = 1 + delta_len + value_len + value.len();
49 if self.pos + required > self.buf.len() {
50 return Err(EncodeError::BufferTooSmall);
51 }
52
53 let header_pos = self.pos;
54 self.pos += 1;
55 let delta_nibble = write_extended(&mut self.buf[self.pos..], delta)?;
56 self.pos += delta_len;
57 let len_nibble = write_extended(&mut self.buf[self.pos..], value.len() as u16)?;
58 self.pos += value_len;
59 self.buf[header_pos] = (delta_nibble << 4) | len_nibble;
60 self.buf[self.pos..self.pos + value.len()].copy_from_slice(value);
61 self.pos += value.len();
62 self.last_number = number;
63 self.wrote_any = true;
64 Ok(())
65 }
66
67 pub fn end_marker(&mut self) -> Result<(), EncodeError> {
69 if self.pos >= self.buf.len() {
70 return Err(EncodeError::BufferTooSmall);
71 }
72 self.buf[self.pos] = 0xFF;
73 self.pos += 1;
74 Ok(())
75 }
76
77 pub fn put_u32(&mut self, number: u16, value: u32) -> Result<(), EncodeError> {
79 let (bytes, len) = minimal_u32(value);
80 self.put(number, &bytes[4 - len..])
81 }
82
83 pub fn put_i32(&mut self, number: u16, value: i32) -> Result<(), EncodeError> {
85 let (bytes, len) = minimal_i32(value);
86 self.put(number, &bytes[4 - len..])
87 }
88
89 pub fn finish(self) -> usize {
91 self.pos
92 }
93}
94
95pub fn parse_be_u32(bytes: &[u8]) -> Result<u32, ParseError> {
99 if bytes.len() > 4 {
100 return Err(ParseError::MalformedOption);
101 }
102 let mut arr = [0u8; 4];
103 arr[4 - bytes.len()..].copy_from_slice(bytes);
104 Ok(u32::from_be_bytes(arr))
105}
106
107pub fn parse_be_i32(bytes: &[u8]) -> Result<i32, ParseError> {
111 if bytes.is_empty() {
112 return Ok(0);
113 }
114 if bytes.len() > 4 {
115 return Err(ParseError::MalformedOption);
116 }
117 let sign = if bytes[0] & 0x80 != 0 { 0xFF } else { 0x00 };
118 let mut arr = [sign; 4];
119 arr[4 - bytes.len()..].copy_from_slice(bytes);
120 Ok(i32::from_be_bytes(arr))
121}
122
123fn minimal_u32(v: u32) -> ([u8; 4], usize) {
124 let bytes = v.to_be_bytes();
125 let skip = bytes.iter().position(|&b| b != 0).unwrap_or(4);
126 (bytes, 4 - skip)
127}
128
129fn minimal_i32(v: i32) -> ([u8; 4], usize) {
130 if v == 0 {
131 return ([0u8; 4], 0);
132 }
133 let bytes = v.to_be_bytes();
134 let mut skip = 0;
135 if v > 0 {
136 while skip < 3 && bytes[skip] == 0x00 && (bytes[skip + 1] & 0x80 == 0) {
137 skip += 1;
138 }
139 } else {
140 while skip < 3 && bytes[skip] == 0xFF && (bytes[skip + 1] & 0x80 != 0) {
141 skip += 1;
142 }
143 }
144 (bytes, 4 - skip)
145}
146
147#[derive(Clone, Debug)]
152pub struct OptionDecoder<'a> {
153 data: &'a [u8],
154 pos: usize,
155 last_number: u16,
156 finished: bool,
157 errored: bool,
158}
159
160impl<'a> OptionDecoder<'a> {
161 pub fn new(data: &'a [u8]) -> Self {
163 Self {
164 data,
165 pos: 0,
166 last_number: 0,
167 finished: false,
168 errored: false,
169 }
170 }
171
172 pub fn remainder(&self) -> &'a [u8] {
177 if self.finished {
178 &self.data[self.pos..]
179 } else {
180 &[]
181 }
182 }
183}
184
185impl<'a> Iterator for OptionDecoder<'a> {
186 type Item = Result<(u16, &'a [u8]), ParseError>;
187
188 fn next(&mut self) -> Option<Self::Item> {
189 if self.finished || self.errored {
190 return None;
191 }
192 if self.pos >= self.data.len() {
193 self.finished = true;
194 return None;
195 }
196
197 let first = self.data[self.pos];
198 if first == 0xFF {
199 self.pos += 1;
200 self.finished = true;
201 return None;
202 }
203
204 self.pos += 1;
205 let delta_nibble = first >> 4;
206 let len_nibble = first & 0x0F;
207 let (delta, delta_len) = match read_extended(&self.data[self.pos..], delta_nibble) {
208 Ok(value) => value,
209 Err(err) => {
210 self.errored = true;
211 return Some(Err(err));
212 }
213 };
214 self.pos += delta_len;
215 let (len, len_len) = match read_extended(&self.data[self.pos..], len_nibble) {
216 Ok(value) => value,
217 Err(err) => {
218 self.errored = true;
219 return Some(Err(err));
220 }
221 };
222 self.pos += len_len;
223
224 if self.pos + len as usize > self.data.len() {
225 self.errored = true;
226 return Some(Err(ParseError::Truncated));
227 }
228
229 let number = self
230 .last_number
231 .checked_add(delta)
232 .ok_or(ParseError::MalformedOption);
233 let number = match number {
234 Ok(value) => value,
235 Err(err) => {
236 self.errored = true;
237 return Some(Err(err));
238 }
239 };
240 let value = &self.data[self.pos..self.pos + len as usize];
241 self.pos += len as usize;
242 self.last_number = number;
243 Some(Ok((number, value)))
244 }
245}
246
247fn encoded_len(value: u16) -> usize {
248 match value {
249 0..=12 => 0,
250 13..=268 => 1,
251 _ => 2,
252 }
253}
254
255fn write_extended(buf: &mut [u8], value: u16) -> Result<u8, EncodeError> {
256 match value {
257 0..=12 => Ok(value as u8),
258 13..=268 => {
259 if buf.is_empty() {
260 return Err(EncodeError::BufferTooSmall);
261 }
262 buf[0] = (value - 13) as u8;
263 Ok(13)
264 }
265 _ => {
266 if buf.len() < 2 {
267 return Err(EncodeError::BufferTooSmall);
268 }
269 let extended = value - 269;
270 buf[..2].copy_from_slice(&extended.to_be_bytes());
271 Ok(14)
272 }
273 }
274}
275
276fn read_extended(data: &[u8], nibble: u8) -> Result<(u16, usize), ParseError> {
277 match nibble {
278 0..=12 => Ok((nibble as u16, 0)),
279 13 => {
280 if data.is_empty() {
281 return Err(ParseError::Truncated);
282 }
283 Ok((data[0] as u16 + 13, 1))
284 }
285 14 => {
286 if data.len() < 2 {
287 return Err(ParseError::Truncated);
288 }
289 Ok((u16::from_be_bytes([data[0], data[1]]) + 269, 2))
290 }
291 _ => Err(ParseError::InvalidOptionNibble),
292 }
293}
294
295#[cfg(test)]
296mod tests {
297 use super::*;
298
299 #[test]
302 fn parse_be_u32_values() {
303 assert_eq!(parse_be_u32(&[]).unwrap(), 0);
304 assert_eq!(parse_be_u32(&[1]).unwrap(), 1);
305 assert_eq!(parse_be_u32(&[1, 0]).unwrap(), 256);
306 assert_eq!(parse_be_u32(&[1, 0, 0]).unwrap(), 65536);
307 assert_eq!(parse_be_u32(&[0, 1, 0]).unwrap(), 256); assert_eq!(parse_be_u32(&[0xFF, 0xFF, 0xFF, 0xFF]).unwrap(), u32::MAX);
309 assert!(parse_be_u32(&[0; 5]).is_err());
310 }
311
312 #[test]
315 fn parse_be_i32_values() {
316 assert_eq!(parse_be_i32(&[]).unwrap(), 0);
317 assert_eq!(parse_be_i32(&[0x7F]).unwrap(), 127);
318 assert_eq!(parse_be_i32(&[0x00, 0x80]).unwrap(), 128);
319 assert_eq!(parse_be_i32(&[0xFF]).unwrap(), -1);
320 assert_eq!(parse_be_i32(&[0x80]).unwrap(), -128);
321 assert_eq!(parse_be_i32(&[0xFF, 0x7F]).unwrap(), -129);
322 assert_eq!(parse_be_i32(&[0x80, 0x00, 0x00, 0x00]).unwrap(), i32::MIN);
323 assert_eq!(parse_be_i32(&[0x7F, 0xFF, 0xFF, 0xFF]).unwrap(), i32::MAX);
324 assert!(parse_be_i32(&[0; 5]).is_err());
325 }
326
327 #[test]
330 fn put_u32_round_trips() {
331 let cases: &[u32] = &[0, 1, 127, 128, 255, 256, u32::MAX];
332 for &v in cases {
333 let mut buf = [0u8; 16];
334 let mut enc = OptionEncoder::new(&mut buf);
335 enc.put_u32(1, v).unwrap();
336 let len = enc.finish();
337 let (_, value) = OptionDecoder::new(&buf[..len]).next().unwrap().unwrap();
338 assert_eq!(parse_be_u32(value).unwrap(), v, "failed for u32 {v}");
339 }
340 }
341
342 #[test]
343 fn put_i32_round_trips() {
344 let cases: &[i32] = &[0, 1, 127, 128, -1, -128, -129, i32::MIN, i32::MAX];
345 for &v in cases {
346 let mut buf = [0u8; 16];
347 let mut enc = OptionEncoder::new(&mut buf);
348 enc.put_i32(1, v).unwrap();
349 let len = enc.finish();
350 let (_, value) = OptionDecoder::new(&buf[..len]).next().unwrap().unwrap();
351 assert_eq!(parse_be_i32(value).unwrap(), v, "failed for i32 {v}");
352 }
353 }
354
355 #[test]
359 fn wire_inline_delta_and_length() {
360 let mut buf = [0u8; 8];
361 let mut enc = OptionEncoder::new(&mut buf);
362 enc.put(5, &[0xAB]).unwrap();
363 assert_eq!(enc.finish(), 2);
364 assert_eq!(&buf[..2], &[0x51, 0xAB]);
365 }
366
367 #[test]
369 fn wire_option_zero_empty_value() {
370 let mut buf = [0u8; 4];
371 let mut enc = OptionEncoder::new(&mut buf);
372 enc.put(0, &[]).unwrap();
373 assert_eq!(enc.finish(), 1);
374 assert_eq!(buf[0], 0x00);
375 }
376
377 #[test]
379 fn wire_extended_delta_1byte_boundary() {
380 let mut buf = [0u8; 8];
381 let mut enc = OptionEncoder::new(&mut buf);
382 enc.put(13, &[]).unwrap();
383 assert_eq!(enc.finish(), 2);
384 assert_eq!(&buf[..2], &[0xD0, 0x00]);
386 }
387
388 #[test]
390 fn wire_extended_delta_1byte_max() {
391 let mut buf = [0u8; 8];
392 let mut enc = OptionEncoder::new(&mut buf);
393 enc.put(268, &[]).unwrap();
394 assert_eq!(enc.finish(), 2);
395 assert_eq!(&buf[..2], &[0xD0, 0xFF]);
396 }
397
398 #[test]
400 fn wire_extended_delta_2byte_boundary() {
401 let mut buf = [0u8; 8];
402 let mut enc = OptionEncoder::new(&mut buf);
403 enc.put(269, &[]).unwrap();
404 assert_eq!(enc.finish(), 3);
405 assert_eq!(&buf[..3], &[0xE0, 0x00, 0x00]);
406 }
407
408 #[test]
410 fn wire_extended_length_1byte() {
411 let mut buf = [0u8; 32];
412 let value = [0u8; 13];
413 {
414 let mut enc = OptionEncoder::new(&mut buf);
415 enc.put(0, &value).unwrap();
416 assert_eq!(enc.finish(), 15);
417 }
418 assert_eq!(buf[0], 0x0D);
420 assert_eq!(buf[1], 0x00);
421 assert_eq!(&buf[2..15], &value);
422 }
423
424 #[test]
426 fn wire_end_marker() {
427 let mut buf = [0u8; 4];
428 let mut enc = OptionEncoder::new(&mut buf);
429 enc.put(1, &[0x01]).unwrap();
430 enc.end_marker().unwrap();
431 let len = enc.finish();
432 assert_eq!(buf[len - 1], 0xFF);
433 }
434
435 #[test]
438 fn encoder_multiple_options_sequential() {
439 let mut buf = [0u8; 16];
440 let mut enc = OptionEncoder::new(&mut buf);
441 enc.put(1, &[0x01]).unwrap();
442 enc.put(3, &[0x02]).unwrap(); enc.put(3, &[0x03]).unwrap(); let len = enc.finish();
445
446 let items: Vec<_> = OptionDecoder::new(&buf[..len])
447 .collect::<Result<_, _>>()
448 .unwrap();
449 assert_eq!(items, vec![(1, &[0x01u8][..]), (3, &[0x02][..]), (3, &[0x03][..])]);
450 }
451
452 #[test]
453 fn encoder_with_last_number_continues_delta() {
454 let mut buf = [0u8; 8];
456 let mut enc = OptionEncoder::with_last_number(&mut buf, 10);
457 enc.put(12, &[0xBB]).unwrap();
458 let len = enc.finish();
459 assert_eq!(&buf[..len], &[0x21, 0xBB]);
461 }
462
463 #[test]
464 fn encoder_large_option_number_round_trip() {
465 let mut buf = [0u8; 16];
466 let mut enc = OptionEncoder::new(&mut buf);
467 enc.put(u16::MAX, &[0xCC]).unwrap();
468 let len = enc.finish();
469 let (num, val) = OptionDecoder::new(&buf[..len]).next().unwrap().unwrap();
470 assert_eq!(num, u16::MAX);
471 assert_eq!(val, &[0xCC]);
472 }
473
474 #[test]
477 fn encoder_out_of_order_returns_error() {
478 let mut buf = [0u8; 16];
479 let mut enc = OptionEncoder::new(&mut buf);
480 enc.put(5, &[]).unwrap();
481 assert_eq!(enc.put(3, &[]), Err(EncodeError::OptionOutOfOrder));
482 }
483
484 #[test]
485 fn encoder_buffer_too_small_returns_error() {
486 let mut buf = [0u8; 1]; let mut enc = OptionEncoder::new(&mut buf);
488 assert_eq!(enc.put(0, &[0x01]), Err(EncodeError::BufferTooSmall));
489 }
490
491 #[test]
492 fn encoder_end_marker_buffer_too_small() {
493 let mut buf = [0u8; 0];
494 let mut enc = OptionEncoder::new(&mut buf);
495 assert_eq!(enc.end_marker(), Err(EncodeError::BufferTooSmall));
496 }
497
498 #[test]
501 fn decoder_empty_input_yields_nothing() {
502 assert!(OptionDecoder::new(&[]).next().is_none());
503 }
504
505 #[test]
506 fn decoder_end_marker_only_yields_nothing() {
507 let mut dec = OptionDecoder::new(&[0xFF]);
508 assert!(dec.next().is_none());
509 assert_eq!(dec.remainder(), &[] as &[u8]);
510 }
511
512 #[test]
513 fn decoder_remainder_after_end_marker() {
514 let mut buf = [0u8; 16];
516 let mut enc = OptionEncoder::new(&mut buf);
517 enc.put(1, &[0xAA]).unwrap();
518 enc.end_marker().unwrap();
519 let opt_len = enc.finish();
520 buf[opt_len] = 0xDE;
521 buf[opt_len + 1] = 0xAD;
522
523 let mut dec = OptionDecoder::new(&buf[..opt_len + 2]);
524 let _ = dec.next().unwrap().unwrap(); assert!(dec.next().is_none()); assert_eq!(dec.remainder(), &[0xDE, 0xAD]);
527 }
528
529 #[test]
530 fn decoder_remainder_empty_without_end_marker() {
531 let mut buf = [0u8; 8];
532 let mut enc = OptionEncoder::new(&mut buf);
533 enc.put(1, &[0x01]).unwrap();
534 let len = enc.finish();
535
536 let mut dec = OptionDecoder::new(&buf[..len]);
537 let _ = dec.next().unwrap().unwrap();
538 assert!(dec.next().is_none());
539 assert_eq!(dec.remainder(), &[] as &[u8]);
541 }
542
543 #[test]
544 fn decoder_remainder_empty_before_exhausted() {
545 let mut buf = [0u8; 8];
547 let mut enc = OptionEncoder::new(&mut buf);
548 enc.put(1, &[0x01]).unwrap();
549 enc.end_marker().unwrap();
550 let len = enc.finish();
551
552 let dec = OptionDecoder::new(&buf[..len]);
553 assert_eq!(dec.remainder(), &[] as &[u8]);
555 }
556
557 #[test]
560 fn decoder_truncated_value_returns_error() {
561 let data = [0x03, 0xAB]; let mut dec = OptionDecoder::new(&data);
564 assert!(matches!(dec.next(), Some(Err(ParseError::Truncated))));
565 assert!(dec.next().is_none()); }
567
568 #[test]
569 fn decoder_truncated_extended_delta_returns_error() {
570 let data = [0xD0]; let mut dec = OptionDecoder::new(&data);
573 assert!(matches!(dec.next(), Some(Err(ParseError::Truncated))));
574 assert!(dec.next().is_none());
575 }
576
577 #[test]
578 fn decoder_invalid_nibble_returns_error() {
579 let data = [0xF0]; let mut dec = OptionDecoder::new(&data);
582 assert!(matches!(
583 dec.next(),
584 Some(Err(ParseError::InvalidOptionNibble))
585 ));
586 assert!(dec.next().is_none());
587 }
588
589 #[test]
590 fn decoder_option_number_overflow_returns_error() {
591 let mut buf = [0u8; 16];
593 let mut enc = OptionEncoder::new(&mut buf);
594 enc.put(u16::MAX, &[]).unwrap();
595 let len = enc.finish();
596
597 buf[len] = 0x10; let mut dec = OptionDecoder::new(&buf[..len + 1]);
600 let _ = dec.next().unwrap().unwrap(); assert!(matches!(dec.next(), Some(Err(ParseError::MalformedOption))));
602 assert!(dec.next().is_none());
603 }
604}