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 position(&self) -> usize {
178 self.pos
179 }
180
181 pub fn last_number(&self) -> u16 {
183 self.last_number
184 }
185
186 pub fn remainder(&self) -> &'a [u8] {
191 if self.finished {
192 &self.data[self.pos..]
193 } else {
194 &[]
195 }
196 }
197}
198
199impl<'a> Iterator for OptionDecoder<'a> {
200 type Item = Result<(u16, &'a [u8]), ParseError>;
201
202 fn next(&mut self) -> Option<Self::Item> {
203 if self.finished || self.errored {
204 return None;
205 }
206 if self.pos >= self.data.len() {
207 self.finished = true;
208 return None;
209 }
210
211 let first = self.data[self.pos];
212 if first == 0xFF {
213 self.pos += 1;
214 self.finished = true;
215 return None;
216 }
217
218 self.pos += 1;
219 let delta_nibble = first >> 4;
220 let len_nibble = first & 0x0F;
221 let (delta, delta_len) = match read_extended(&self.data[self.pos..], delta_nibble) {
222 Ok(value) => value,
223 Err(err) => {
224 self.errored = true;
225 return Some(Err(err));
226 }
227 };
228 self.pos += delta_len;
229 let (len, len_len) = match read_extended(&self.data[self.pos..], len_nibble) {
230 Ok(value) => value,
231 Err(err) => {
232 self.errored = true;
233 return Some(Err(err));
234 }
235 };
236 self.pos += len_len;
237
238 if self.pos + len as usize > self.data.len() {
239 self.errored = true;
240 return Some(Err(ParseError::Truncated));
241 }
242
243 let number = self
244 .last_number
245 .checked_add(delta)
246 .ok_or(ParseError::MalformedOption);
247 let number = match number {
248 Ok(value) => value,
249 Err(err) => {
250 self.errored = true;
251 return Some(Err(err));
252 }
253 };
254 let value = &self.data[self.pos..self.pos + len as usize];
255 self.pos += len as usize;
256 self.last_number = number;
257 Some(Ok((number, value)))
258 }
259}
260
261fn encoded_len(value: u16) -> usize {
262 match value {
263 0..=12 => 0,
264 13..=268 => 1,
265 _ => 2,
266 }
267}
268
269fn write_extended(buf: &mut [u8], value: u16) -> Result<u8, EncodeError> {
270 match value {
271 0..=12 => Ok(value as u8),
272 13..=268 => {
273 if buf.is_empty() {
274 return Err(EncodeError::BufferTooSmall);
275 }
276 buf[0] = (value - 13) as u8;
277 Ok(13)
278 }
279 _ => {
280 if buf.len() < 2 {
281 return Err(EncodeError::BufferTooSmall);
282 }
283 let extended = value - 269;
284 buf[..2].copy_from_slice(&extended.to_be_bytes());
285 Ok(14)
286 }
287 }
288}
289
290fn read_extended(data: &[u8], nibble: u8) -> Result<(u16, usize), ParseError> {
291 match nibble {
292 0..=12 => Ok((nibble as u16, 0)),
293 13 => {
294 if data.is_empty() {
295 return Err(ParseError::Truncated);
296 }
297 Ok((data[0] as u16 + 13, 1))
298 }
299 14 => {
300 if data.len() < 2 {
301 return Err(ParseError::Truncated);
302 }
303 let value = u16::from_be_bytes([data[0], data[1]])
304 .checked_add(269)
305 .ok_or(ParseError::InvalidOptionNibble)?;
306 Ok((value, 2))
307 }
308 _ => Err(ParseError::InvalidOptionNibble),
309 }
310}
311
312#[cfg(test)]
313mod tests {
314 use super::*;
315
316 #[test]
319 fn parse_be_u32_values() {
320 assert_eq!(parse_be_u32(&[]).unwrap(), 0);
321 assert_eq!(parse_be_u32(&[1]).unwrap(), 1);
322 assert_eq!(parse_be_u32(&[1, 0]).unwrap(), 256);
323 assert_eq!(parse_be_u32(&[1, 0, 0]).unwrap(), 65536);
324 assert_eq!(parse_be_u32(&[0, 1, 0]).unwrap(), 256); assert_eq!(parse_be_u32(&[0xFF, 0xFF, 0xFF, 0xFF]).unwrap(), u32::MAX);
326 assert!(parse_be_u32(&[0; 5]).is_err());
327 }
328
329 #[test]
332 fn parse_be_i32_values() {
333 assert_eq!(parse_be_i32(&[]).unwrap(), 0);
334 assert_eq!(parse_be_i32(&[0x7F]).unwrap(), 127);
335 assert_eq!(parse_be_i32(&[0x00, 0x80]).unwrap(), 128);
336 assert_eq!(parse_be_i32(&[0xFF]).unwrap(), -1);
337 assert_eq!(parse_be_i32(&[0x80]).unwrap(), -128);
338 assert_eq!(parse_be_i32(&[0xFF, 0x7F]).unwrap(), -129);
339 assert_eq!(parse_be_i32(&[0x80, 0x00, 0x00, 0x00]).unwrap(), i32::MIN);
340 assert_eq!(parse_be_i32(&[0x7F, 0xFF, 0xFF, 0xFF]).unwrap(), i32::MAX);
341 assert!(parse_be_i32(&[0; 5]).is_err());
342 }
343
344 #[test]
347 fn put_u32_round_trips() {
348 let cases: &[u32] = &[0, 1, 127, 128, 255, 256, u32::MAX];
349 for &v in cases {
350 let mut buf = [0u8; 16];
351 let mut enc = OptionEncoder::new(&mut buf);
352 enc.put_u32(1, v).unwrap();
353 let len = enc.finish();
354 let (_, value) = OptionDecoder::new(&buf[..len]).next().unwrap().unwrap();
355 assert_eq!(parse_be_u32(value).unwrap(), v, "failed for u32 {v}");
356 }
357 }
358
359 #[test]
360 fn put_i32_round_trips() {
361 let cases: &[i32] = &[0, 1, 127, 128, -1, -128, -129, i32::MIN, i32::MAX];
362 for &v in cases {
363 let mut buf = [0u8; 16];
364 let mut enc = OptionEncoder::new(&mut buf);
365 enc.put_i32(1, v).unwrap();
366 let len = enc.finish();
367 let (_, value) = OptionDecoder::new(&buf[..len]).next().unwrap().unwrap();
368 assert_eq!(parse_be_i32(value).unwrap(), v, "failed for i32 {v}");
369 }
370 }
371
372 #[test]
376 fn wire_inline_delta_and_length() {
377 let mut buf = [0u8; 8];
378 let mut enc = OptionEncoder::new(&mut buf);
379 enc.put(5, &[0xAB]).unwrap();
380 assert_eq!(enc.finish(), 2);
381 assert_eq!(&buf[..2], &[0x51, 0xAB]);
382 }
383
384 #[test]
386 fn wire_option_zero_empty_value() {
387 let mut buf = [0u8; 4];
388 let mut enc = OptionEncoder::new(&mut buf);
389 enc.put(0, &[]).unwrap();
390 assert_eq!(enc.finish(), 1);
391 assert_eq!(buf[0], 0x00);
392 }
393
394 #[test]
396 fn wire_extended_delta_1byte_boundary() {
397 let mut buf = [0u8; 8];
398 let mut enc = OptionEncoder::new(&mut buf);
399 enc.put(13, &[]).unwrap();
400 assert_eq!(enc.finish(), 2);
401 assert_eq!(&buf[..2], &[0xD0, 0x00]);
403 }
404
405 #[test]
407 fn wire_extended_delta_1byte_max() {
408 let mut buf = [0u8; 8];
409 let mut enc = OptionEncoder::new(&mut buf);
410 enc.put(268, &[]).unwrap();
411 assert_eq!(enc.finish(), 2);
412 assert_eq!(&buf[..2], &[0xD0, 0xFF]);
413 }
414
415 #[test]
417 fn wire_extended_delta_2byte_boundary() {
418 let mut buf = [0u8; 8];
419 let mut enc = OptionEncoder::new(&mut buf);
420 enc.put(269, &[]).unwrap();
421 assert_eq!(enc.finish(), 3);
422 assert_eq!(&buf[..3], &[0xE0, 0x00, 0x00]);
423 }
424
425 #[test]
427 fn wire_extended_length_1byte() {
428 let mut buf = [0u8; 32];
429 let value = [0u8; 13];
430 {
431 let mut enc = OptionEncoder::new(&mut buf);
432 enc.put(0, &value).unwrap();
433 assert_eq!(enc.finish(), 15);
434 }
435 assert_eq!(buf[0], 0x0D);
437 assert_eq!(buf[1], 0x00);
438 assert_eq!(&buf[2..15], &value);
439 }
440
441 #[test]
443 fn wire_end_marker() {
444 let mut buf = [0u8; 4];
445 let mut enc = OptionEncoder::new(&mut buf);
446 enc.put(1, &[0x01]).unwrap();
447 enc.end_marker().unwrap();
448 let len = enc.finish();
449 assert_eq!(buf[len - 1], 0xFF);
450 }
451
452 #[test]
455 fn encoder_multiple_options_sequential() {
456 let mut buf = [0u8; 16];
457 let mut enc = OptionEncoder::new(&mut buf);
458 enc.put(1, &[0x01]).unwrap();
459 enc.put(3, &[0x02]).unwrap(); enc.put(3, &[0x03]).unwrap(); let len = enc.finish();
462
463 let items: Vec<_> = OptionDecoder::new(&buf[..len])
464 .collect::<Result<_, _>>()
465 .unwrap();
466 assert_eq!(
467 items,
468 vec![(1, &[0x01u8][..]), (3, &[0x02][..]), (3, &[0x03][..])]
469 );
470 }
471
472 #[test]
473 fn encoder_with_last_number_continues_delta() {
474 let mut buf = [0u8; 8];
476 let mut enc = OptionEncoder::with_last_number(&mut buf, 10);
477 enc.put(12, &[0xBB]).unwrap();
478 let len = enc.finish();
479 assert_eq!(&buf[..len], &[0x21, 0xBB]);
481 }
482
483 #[test]
484 fn encoder_large_option_number_round_trip() {
485 let mut buf = [0u8; 16];
486 let mut enc = OptionEncoder::new(&mut buf);
487 enc.put(u16::MAX, &[0xCC]).unwrap();
488 let len = enc.finish();
489 let (num, val) = OptionDecoder::new(&buf[..len]).next().unwrap().unwrap();
490 assert_eq!(num, u16::MAX);
491 assert_eq!(val, &[0xCC]);
492 }
493
494 #[test]
497 fn encoder_out_of_order_returns_error() {
498 let mut buf = [0u8; 16];
499 let mut enc = OptionEncoder::new(&mut buf);
500 enc.put(5, &[]).unwrap();
501 assert_eq!(enc.put(3, &[]), Err(EncodeError::OptionOutOfOrder));
502 }
503
504 #[test]
505 fn encoder_buffer_too_small_returns_error() {
506 let mut buf = [0u8; 1]; let mut enc = OptionEncoder::new(&mut buf);
508 assert_eq!(enc.put(0, &[0x01]), Err(EncodeError::BufferTooSmall));
509 }
510
511 #[test]
512 fn encoder_end_marker_buffer_too_small() {
513 let mut buf = [0u8; 0];
514 let mut enc = OptionEncoder::new(&mut buf);
515 assert_eq!(enc.end_marker(), Err(EncodeError::BufferTooSmall));
516 }
517
518 #[test]
521 fn decoder_empty_input_yields_nothing() {
522 assert!(OptionDecoder::new(&[]).next().is_none());
523 }
524
525 #[test]
526 fn decoder_end_marker_only_yields_nothing() {
527 let mut dec = OptionDecoder::new(&[0xFF]);
528 assert!(dec.next().is_none());
529 assert_eq!(dec.remainder(), &[] as &[u8]);
530 }
531
532 #[test]
533 fn decoder_remainder_after_end_marker() {
534 let mut buf = [0u8; 16];
536 let mut enc = OptionEncoder::new(&mut buf);
537 enc.put(1, &[0xAA]).unwrap();
538 enc.end_marker().unwrap();
539 let opt_len = enc.finish();
540 buf[opt_len] = 0xDE;
541 buf[opt_len + 1] = 0xAD;
542
543 let mut dec = OptionDecoder::new(&buf[..opt_len + 2]);
544 let _ = dec.next().unwrap().unwrap(); assert!(dec.next().is_none()); assert_eq!(dec.remainder(), &[0xDE, 0xAD]);
547 }
548
549 #[test]
550 fn decoder_remainder_empty_without_end_marker() {
551 let mut buf = [0u8; 8];
552 let mut enc = OptionEncoder::new(&mut buf);
553 enc.put(1, &[0x01]).unwrap();
554 let len = enc.finish();
555
556 let mut dec = OptionDecoder::new(&buf[..len]);
557 let _ = dec.next().unwrap().unwrap();
558 assert!(dec.next().is_none());
559 assert_eq!(dec.remainder(), &[] as &[u8]);
561 }
562
563 #[test]
564 fn decoder_remainder_empty_before_exhausted() {
565 let mut buf = [0u8; 8];
567 let mut enc = OptionEncoder::new(&mut buf);
568 enc.put(1, &[0x01]).unwrap();
569 enc.end_marker().unwrap();
570 let len = enc.finish();
571
572 let dec = OptionDecoder::new(&buf[..len]);
573 assert_eq!(dec.remainder(), &[] as &[u8]);
575 }
576
577 #[test]
580 fn decoder_truncated_value_returns_error() {
581 let data = [0x03, 0xAB]; let mut dec = OptionDecoder::new(&data);
584 assert!(matches!(dec.next(), Some(Err(ParseError::Truncated))));
585 assert!(dec.next().is_none()); }
587
588 #[test]
589 fn decoder_truncated_extended_delta_returns_error() {
590 let data = [0xD0]; let mut dec = OptionDecoder::new(&data);
593 assert!(matches!(dec.next(), Some(Err(ParseError::Truncated))));
594 assert!(dec.next().is_none());
595 }
596
597 #[test]
598 fn decoder_invalid_nibble_returns_error() {
599 let data = [0xF0]; let mut dec = OptionDecoder::new(&data);
602 assert!(matches!(
603 dec.next(),
604 Some(Err(ParseError::InvalidOptionNibble))
605 ));
606 assert!(dec.next().is_none());
607 }
608
609 #[test]
610 fn decoder_option_number_overflow_returns_error() {
611 let mut buf = [0u8; 16];
613 let mut enc = OptionEncoder::new(&mut buf);
614 enc.put(u16::MAX, &[]).unwrap();
615 let len = enc.finish();
616
617 buf[len] = 0x10; let mut dec = OptionDecoder::new(&buf[..len + 1]);
620 let _ = dec.next().unwrap().unwrap(); assert!(matches!(dec.next(), Some(Err(ParseError::MalformedOption))));
622 assert!(dec.next().is_none());
623 }
624}