1use crate::error::DecodeError;
11use crate::limits::MAX_FRAME_BYTES;
12use serde::Serialize;
13use serde::de::DeserializeOwned;
14
15const MAX_SCAN_DEPTH: u32 = 64;
18
19const MAJOR_BYTES: u8 = 2;
20const MAJOR_TEXT: u8 = 3;
21const MAJOR_ARRAY: u8 = 4;
22const MAJOR_MAP: u8 = 5;
23const MAJOR_TAG: u8 = 6;
24const MAJOR_SIMPLE: u8 = 7;
25const BREAK: u8 = 0xff;
26const NULL: u8 = 0xf6;
27
28pub fn encode_named<T: Serialize + ?Sized>(value: &T) -> Result<Vec<u8>, DecodeError> {
30 let mut buffer = Vec::new();
31 encode_named_into(value, &mut buffer)?;
32 Ok(buffer)
33}
34
35pub fn encode_named_into<T: Serialize + ?Sized>(
40 value: &T,
41 buffer: &mut Vec<u8>,
42) -> Result<(), DecodeError> {
43 buffer.clear();
44 ciborium::into_writer(value, &mut *buffer)
45 .map_err(|error| DecodeError::Encode(error.to_string()))
46}
47
48pub fn decode_named<T: DeserializeOwned>(payload: &[u8]) -> Result<T, DecodeError> {
53 let mut reader = payload;
54 let value = ciborium::from_reader(&mut reader)
55 .map_err(|error| DecodeError::Decode(error.to_string()))?;
56 if !reader.is_empty() {
57 return Err(DecodeError::Decode(format!(
58 "{} trailing byte(s) after the CBOR value",
59 reader.len()
60 )));
61 }
62 Ok(value)
63}
64
65pub fn encode_named_framed<T: Serialize + ?Sized>(
70 value: &T,
71 capacity_hint: usize,
72 max_bytes: usize,
73) -> Result<Vec<u8>, DecodeError> {
74 let mut framed = Vec::with_capacity(4 + capacity_hint);
75 framed.extend_from_slice(&[0; 4]);
76 ciborium::into_writer(value, &mut framed)
77 .map_err(|error| DecodeError::Encode(error.to_string()))?;
78 let length = framed.len() - 4;
79 if length > max_bytes.min(MAX_FRAME_BYTES) {
80 return Err(DecodeError::Frame(format!(
81 "payload is {length}B, exceeds frame cap {}B",
82 max_bytes.min(MAX_FRAME_BYTES)
83 )));
84 }
85 framed[..4].copy_from_slice(&(length as u32).to_le_bytes());
86 Ok(framed)
87}
88
89#[derive(Debug, Default)]
99pub struct NamedFields<'a> {
100 fields: Vec<(&'a str, &'a [u8])>,
101}
102
103impl<'a> NamedFields<'a> {
104 pub fn decode(payload: &'a [u8]) -> Result<Self, DecodeError> {
106 Self::decode_within(payload, usize::MAX)
107 }
108
109 pub fn decode_within(payload: &'a [u8], max_fields: usize) -> Result<Self, DecodeError> {
113 let too_many = || {
114 DecodeError::Decode(format!(
115 "a named-field map holds more than {max_fields} fields"
116 ))
117 };
118 let mut cursor = Cursor {
119 bytes: payload,
120 at: 0,
121 };
122 let (major, argument) = cursor.head()?;
123 if major != MAJOR_MAP {
124 return Err(DecodeError::Decode(
125 "a named-field value is a map".to_owned(),
126 ));
127 }
128 let mut fields: Vec<(&'a str, &'a [u8])> = Vec::new();
129 match argument {
130 Argument::Value(count) => {
131 if usize::try_from(count)
132 .ok()
133 .is_none_or(|count| count > max_fields)
134 {
135 return Err(too_many());
136 }
137 for _ in 0..count {
138 fields.push(cursor.entry()?);
139 }
140 }
141 Argument::Indefinite => {
142 while !cursor.at_break()? {
143 if fields.len() == max_fields {
144 return Err(too_many());
145 }
146 fields.push(cursor.entry()?);
147 }
148 cursor.at += 1;
149 }
150 }
151 if cursor.at != payload.len() {
152 return Err(DecodeError::Decode(format!(
153 "{} trailing byte(s) after the CBOR value",
154 payload.len() - cursor.at
155 )));
156 }
157 let mut keys: Vec<&str> = fields.iter().map(|(key, _)| *key).collect();
159 keys.sort_unstable();
160 if let Some(pair) = keys.windows(2).find(|pair| pair[0] == pair[1]) {
161 return Err(DecodeError::Decode(format!(
162 "duplicate field `{}`",
163 pair[0]
164 )));
165 }
166 Ok(Self { fields })
167 }
168
169 pub fn get(&self, key: &str) -> Option<&'a [u8]> {
171 self.fields
172 .iter()
173 .find(|(name, _)| *name == key)
174 .map(|(_, value)| *value)
175 }
176
177 pub fn text(&self, key: &str) -> Result<Option<&'a str>, DecodeError> {
180 let Some(value) = self.get(key) else {
181 return Ok(None);
182 };
183 if value == [NULL] {
184 return Ok(None);
185 }
186 let mut cursor = Cursor {
187 bytes: value,
188 at: 0,
189 };
190 let (major, argument) = cursor.head()?;
191 let (MAJOR_TEXT, Argument::Value(length)) = (major, argument) else {
192 return Err(DecodeError::Decode(format!("field `{key}` is not text")));
193 };
194 let text = cursor.take(length)?;
195 std::str::from_utf8(text)
196 .map(Some)
197 .map_err(|_| DecodeError::Decode(format!("field `{key}` is not UTF-8")))
198 }
199
200 pub fn value<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>, DecodeError> {
203 self.get(key).map(decode_named).transpose()
204 }
205}
206
207enum Argument {
210 Value(u64),
211 Indefinite,
212}
213
214struct Cursor<'a> {
215 bytes: &'a [u8],
216 at: usize,
217}
218
219impl<'a> Cursor<'a> {
220 fn entry(&mut self) -> Result<(&'a str, &'a [u8]), DecodeError> {
221 let (major, argument) = self.head()?;
222 let (MAJOR_TEXT, Argument::Value(length)) = (major, argument) else {
223 return Err(DecodeError::Decode(
224 "a named-field key is definite text".to_owned(),
225 ));
226 };
227 let key = std::str::from_utf8(self.take(length)?)
228 .map_err(|_| DecodeError::Decode("a named-field key is UTF-8".to_owned()))?;
229 let start = self.at;
230 self.skip(0)?;
231 Ok((key, &self.bytes[start..self.at]))
232 }
233
234 fn head(&mut self) -> Result<(u8, Argument), DecodeError> {
235 let initial = *self.bytes.get(self.at).ok_or_else(truncated)?;
236 self.at += 1;
237 let major = initial >> 5;
238 let argument = match initial & 0x1f {
239 info @ 0..=23 => Argument::Value(u64::from(info)),
240 24 => Argument::Value(u64::from(self.take(1)?[0])),
241 25 => Argument::Value(u64::from(u16::from_be_bytes(
242 self.take(2)?.try_into().map_err(|_| truncated())?,
243 ))),
244 26 => Argument::Value(u64::from(u32::from_be_bytes(
245 self.take(4)?.try_into().map_err(|_| truncated())?,
246 ))),
247 27 => Argument::Value(u64::from_be_bytes(
248 self.take(8)?.try_into().map_err(|_| truncated())?,
249 )),
250 31 => Argument::Indefinite,
251 _ => {
252 return Err(DecodeError::Decode(
253 "reserved CBOR additional information".to_owned(),
254 ));
255 }
256 };
257 Ok((major, argument))
258 }
259
260 fn skip(&mut self, depth: u32) -> Result<(), DecodeError> {
261 if depth > MAX_SCAN_DEPTH {
262 return Err(DecodeError::Decode(format!(
263 "CBOR nesting exceeds {MAX_SCAN_DEPTH}"
264 )));
265 }
266 let (major, argument) = self.head()?;
267 match (major, argument) {
268 (MAJOR_BYTES | MAJOR_TEXT, Argument::Value(length)) => {
269 self.take(length)?;
270 }
271 (MAJOR_BYTES | MAJOR_TEXT, Argument::Indefinite) => {
272 while !self.at_break()? {
273 let (chunk_major, chunk) = self.head()?;
274 let Argument::Value(length) = chunk else {
275 return Err(DecodeError::Decode(
276 "an indefinite string chunk is definite".to_owned(),
277 ));
278 };
279 if chunk_major != major {
280 return Err(DecodeError::Decode(
281 "an indefinite string chunk has its string's type".to_owned(),
282 ));
283 }
284 self.take(length)?;
285 }
286 self.at += 1;
287 }
288 (MAJOR_ARRAY, Argument::Value(count)) => {
289 for _ in 0..count {
290 self.skip(depth + 1)?;
291 }
292 }
293 (MAJOR_MAP, Argument::Value(count)) => {
294 for _ in 0..count {
295 self.skip(depth + 1)?;
296 self.skip(depth + 1)?;
297 }
298 }
299 (MAJOR_ARRAY | MAJOR_MAP, Argument::Indefinite) => {
300 let mut items = 0_u64;
301 while !self.at_break()? {
302 self.skip(depth + 1)?;
303 items += 1;
304 }
305 if major == MAJOR_MAP && items % 2 == 1 {
306 return Err(DecodeError::Decode(
307 "an indefinite map holds whole pairs".to_owned(),
308 ));
309 }
310 self.at += 1;
311 }
312 (MAJOR_TAG, Argument::Value(_)) => self.skip(depth + 1)?,
313 (MAJOR_SIMPLE, Argument::Value(_)) => {}
314 (_, Argument::Value(_)) => {}
315 (_, Argument::Indefinite) => {
316 return Err(DecodeError::Decode(
317 "only strings, arrays and maps are indefinite".to_owned(),
318 ));
319 }
320 }
321 Ok(())
322 }
323
324 fn at_break(&self) -> Result<bool, DecodeError> {
325 self.bytes
326 .get(self.at)
327 .map(|byte| *byte == BREAK)
328 .ok_or_else(truncated)
329 }
330
331 fn take(&mut self, length: u64) -> Result<&'a [u8], DecodeError> {
332 let end = usize::try_from(length)
333 .ok()
334 .and_then(|length| self.at.checked_add(length))
335 .filter(|end| *end <= self.bytes.len())
336 .ok_or_else(truncated)?;
337 let taken = &self.bytes[self.at..end];
338 self.at = end;
339 Ok(taken)
340 }
341}
342
343fn truncated() -> DecodeError {
344 DecodeError::Decode("the CBOR value is truncated".to_owned())
345}
346
347pub fn frame_encode(payload: &[u8]) -> Result<Vec<u8>, DecodeError> {
350 if payload.len() > MAX_FRAME_BYTES {
351 return Err(DecodeError::Frame(format!(
352 "payload is {}B, exceeds frame cap {MAX_FRAME_BYTES}B",
353 payload.len()
354 )));
355 }
356 let mut framed = Vec::with_capacity(4 + payload.len());
357 framed.extend_from_slice(&(payload.len() as u32).to_le_bytes());
358 framed.extend_from_slice(payload);
359 Ok(framed)
360}
361
362pub fn frame_decode(buf: &[u8]) -> Result<Option<(&[u8], usize)>, DecodeError> {
367 let Some(prefix) = buf.get(..4) else {
368 return Ok(None);
369 };
370 let len = u32::from_le_bytes(prefix.try_into().expect("4-byte slice")) as usize;
371 if len > MAX_FRAME_BYTES {
372 return Err(DecodeError::Frame(format!(
373 "frame length {len}B exceeds cap {MAX_FRAME_BYTES}B"
374 )));
375 }
376 match buf.get(4..4 + len) {
377 Some(payload) => Ok(Some((payload, 4 + len))),
378 None => Ok(None),
379 }
380}
381
382#[cfg(test)]
383mod tests {
384 use super::*;
385 use std::time::{Duration, Instant};
386
387 #[test]
388 fn given_a_payload_when_framed_then_should_round_trip() {
389 let framed = frame_encode(b"hello").expect("frames");
390 assert_eq!(&framed[..4], &5u32.to_le_bytes());
391 let (payload, consumed) = frame_decode(&framed)
392 .expect("decodes")
393 .expect("whole frame present");
394 assert_eq!(payload, b"hello");
395 assert_eq!(consumed, framed.len());
396 }
397
398 #[test]
399 fn given_a_partial_frame_when_decoded_then_should_ask_for_more() {
400 let framed = frame_encode(b"hello").expect("frames");
401 assert!(frame_decode(&framed[..3]).expect("no error").is_none());
402 assert!(frame_decode(&framed[..6]).expect("no error").is_none());
403 }
404
405 #[test]
406 fn given_an_oversized_length_prefix_when_decoded_then_should_error() {
407 let mut bad = Vec::new();
408 bad.extend_from_slice(&((MAX_FRAME_BYTES as u32) + 1).to_le_bytes());
409 assert!(matches!(frame_decode(&bad), Err(DecodeError::Frame(_))));
410 }
411
412 #[test]
413 fn given_named_encoding_when_round_tripped_then_should_preserve_fields() {
414 #[derive(serde::Serialize, serde::Deserialize, PartialEq, Debug)]
415 struct Body {
416 id: u32,
417 name: String,
418 }
419 let body = Body {
420 id: 7,
421 name: "alice".to_owned(),
422 };
423 let bytes = encode_named(&body).expect("encodes");
424 let back: Body = decode_named(&bytes).expect("decodes");
425 assert_eq!(back, body);
426 }
427
428 #[test]
429 fn given_trailing_bytes_when_decoded_then_should_error() {
430 let mut bytes = encode_named(&7u32).expect("encodes");
431 bytes.push(0x00);
432 assert!(matches!(
433 decode_named::<u32>(&bytes),
434 Err(DecodeError::Decode(_))
435 ));
436 }
437 #[test]
438 fn given_the_in_place_encoder_when_reused_then_should_match_encode_named_bytes() {
439 let value = serde_json::json!({"a": 1, "b": "two"});
440 let mut buffer = vec![0xff; 64]; super::encode_named_into(&value, &mut buffer).expect("encodes");
442 assert_eq!(buffer, super::encode_named(&value).expect("encodes"));
443 }
444
445 #[test]
446 fn given_the_framed_encoder_when_used_then_should_prefix_the_named_bytes_and_cap_them() {
447 let value = serde_json::json!({"a": 1, "b": "two"});
448 let framed = encode_named_framed(&value, 16, 1024).expect("frames");
449 let encoded = encode_named(&value).expect("encodes");
450 assert_eq!(&framed[..4], &(encoded.len() as u32).to_le_bytes());
451 assert_eq!(&framed[4..], &encoded);
452 assert_eq!(
453 encode_named_framed(&value, 16, encoded.len()).expect("exact cap frames"),
454 framed
455 );
456 assert!(matches!(
457 encode_named_framed(&value, 16, encoded.len() - 1),
458 Err(DecodeError::Frame(_))
459 ));
460 }
461
462 #[test]
463 fn given_a_payload_at_the_frame_cap_when_framed_then_should_round_trip_and_refuse_one_byte_more()
464 {
465 let over = vec![7u8; MAX_FRAME_BYTES + 1];
466 let payload = &over[..MAX_FRAME_BYTES];
467 let framed = frame_encode(payload).expect("a payload at the cap frames");
468 assert_eq!(&framed[..4], &(MAX_FRAME_BYTES as u32).to_le_bytes());
469 let (decoded, consumed) = frame_decode(&framed)
470 .expect("a frame at the cap decodes")
471 .expect("whole frame present");
472 assert!(decoded == payload, "the payload round trips");
473 assert_eq!(consumed, framed.len());
474 assert!(matches!(frame_encode(&over), Err(DecodeError::Frame(_))));
475 }
476
477 #[derive(serde::Serialize)]
478 struct Keyed {
479 v: u32,
480 namespace: String,
481 #[serde(default, skip_serializing_if = "Option::is_none")]
482 session: Option<String>,
483 #[serde(with = "crate::encoding::bin_bytes")]
484 value: Vec<u8>,
485 }
486
487 fn distinct_fields(count: u32) -> Vec<u8> {
488 let mut payload = vec![0xba];
489 payload.extend_from_slice(&count.to_be_bytes());
490 for index in 0..count {
491 payload.extend(text(&format!("f{index}")));
492 payload.push(0xf6);
493 }
494 payload
495 }
496
497 fn fastest_scan(payload: &[u8]) -> Duration {
498 (0..3)
499 .map(|_| {
500 let started = Instant::now();
501 NamedFields::decode(payload).expect("distinct fields scan");
502 started.elapsed()
503 })
504 .min()
505 .unwrap_or_default()
506 }
507
508 fn text(value: &str) -> Vec<u8> {
509 let mut bytes = vec![0x60 | value.len() as u8];
510 bytes.extend_from_slice(value.as_bytes());
511 bytes
512 }
513
514 #[test]
517 fn given_a_named_map_when_scanned_then_should_find_each_value_in_place() {
518 let keyed = Keyed {
519 v: 1,
520 namespace: "notes".to_owned(),
521 session: None,
522 value: vec![7; 8 << 20],
523 };
524 let payload = encode_named(&keyed).expect("encodes");
525 let fields = NamedFields::decode(&payload).expect("scans");
526 assert_eq!(fields.text("namespace").expect("text"), Some("notes"));
527 assert_eq!(fields.value::<u32>("v").expect("value"), Some(1));
528 assert_eq!(fields.text("session").expect("absent"), None);
529 assert_eq!(fields.value::<u32>("session").expect("absent"), None);
530 let value = fields.get("value").expect("present");
531 assert!(value.len() > 8 << 20);
532 let range = payload.as_ptr_range();
533 assert!(
534 range.contains(&value.as_ptr()) && value.as_ptr_range().end <= range.end,
535 "the value is borrowed from the payload"
536 );
537 assert!(
538 matches!(fields.text("value"), Err(DecodeError::Decode(_))),
539 "a byte string is not text"
540 );
541 assert!(
542 matches!(
543 fields.value::<u32>("namespace"),
544 Err(DecodeError::Decode(_))
545 ),
546 "text is not a number"
547 );
548 }
549
550 #[test]
551 fn given_indefinite_and_nested_values_when_scanned_then_should_step_over_them() {
552 let mut payload = vec![0xbf];
554 payload.extend(text("a"));
555 payload.extend([0x9f, 0x01, 0xa1]);
556 payload.extend(text("x"));
557 payload.extend(text("y"));
558 payload.push(0xff);
559 payload.extend(text("b"));
560 payload.extend([0x7f, 0x62, b'a', b'b', 0x62, b'c', b'd', 0xff]);
561 payload.extend(text("c"));
562 payload.extend([0xc1, 0x02]);
563 payload.extend(text("d"));
564 payload.push(0xf6);
565 payload.push(0xff);
566 let fields = NamedFields::decode(&payload).expect("scans");
567 assert_eq!(fields.get("a"), Some(&payload[3..11]));
568 assert_eq!(
569 fields.value::<String>("b").expect("joined"),
570 Some("abcd".to_owned())
571 );
572 assert!(
573 matches!(fields.text("b"), Err(DecodeError::Decode(_))),
574 "a borrowed text is definite"
575 );
576 assert_eq!(fields.value::<u32>("c").expect("tagged"), Some(2));
577 assert_eq!(fields.text("d").expect("null reads as absent"), None);
578 assert_eq!(fields.value::<Option<u32>>("d").expect("null"), Some(None));
579 }
580
581 #[test]
582 fn given_heads_with_one_two_and_eight_byte_arguments_when_scanned_then_should_find_each_value()
583 {
584 let mut payload = vec![0xa3];
586 payload.extend(text("a"));
587 let one = payload.len();
588 payload.extend([0x58, 24]);
589 payload.extend([7; 24]);
590 let one_end = payload.len();
591 payload.extend(text("b"));
592 let two = payload.len();
593 payload.extend([0x59, 0x01, 0x00]);
594 payload.extend([7; 256]);
595 let two_end = payload.len();
596 payload.extend(text("c"));
597 let eight = payload.len();
598 payload.extend([0x1b, 0, 0, 0, 0, 0, 0, 0, 1]);
599 let fields = NamedFields::decode(&payload).expect("scans");
600 assert_eq!(fields.get("a"), Some(&payload[one..one_end]));
601 assert_eq!(fields.get("b"), Some(&payload[two..two_end]));
602 assert_eq!(fields.get("c"), Some(&payload[eight..]));
603 }
604
605 #[test]
606 fn given_arrays_nested_to_the_scan_bound_when_scanned_then_should_accept_them_and_refuse_one_more()
607 {
608 let bound = MAX_SCAN_DEPTH as usize;
609 for (levels, accepted) in [(bound, true), (bound + 1, false)] {
610 let mut payload = vec![0xa1];
611 payload.extend(text("a"));
612 payload.extend(std::iter::repeat_n(0x81, levels));
613 payload.push(0x01);
614 assert_eq!(
615 NamedFields::decode(&payload).is_ok(),
616 accepted,
617 "levels: {levels}"
618 );
619 }
620 }
621
622 #[test]
623 fn given_nesting_past_the_scan_bound_in_any_container_when_scanned_then_should_refuse_it() {
624 let levels = MAX_SCAN_DEPTH as usize + 1;
625 let nested = |open: &[u8], close: &[u8]| {
626 let mut payload = vec![0xa1];
627 payload.extend(text("a"));
628 for _ in 0..levels {
629 payload.extend_from_slice(open);
630 }
631 payload.push(0x01);
632 for _ in 0..levels {
633 payload.extend_from_slice(close);
634 }
635 payload
636 };
637 for (case, payload) in [
638 ("map keys", nested(&[0xa1], &[0x01])),
639 ("map values", nested(&[0xa1, 0x01], &[])),
640 ("indefinite arrays", nested(&[0x9f], &[0xff])),
641 ("tags", nested(&[0xc1], &[])),
642 ] {
643 assert!(
644 matches!(NamedFields::decode(&payload), Err(DecodeError::Decode(_))),
645 "{case} must be refused"
646 );
647 }
648 }
649
650 #[test]
651 fn given_a_nested_indefinite_map_when_scanned_then_should_accept_only_whole_pairs() {
652 let field = |value: &[u8]| {
653 let mut payload = vec![0xa1];
654 payload.extend(text("a"));
655 payload.extend_from_slice(value);
656 payload
657 };
658 assert!(
659 matches!(
660 NamedFields::decode(&field(&[0xbf, 0x01, 0xff])),
661 Err(DecodeError::Decode(_))
662 ),
663 "a key without a value must be refused"
664 );
665 for (case, value) in [
666 ("one pair", &[0xbf, 0x01, 0x02, 0xff][..]),
667 ("an odd array", &[0x9f, 0x01, 0xff][..]),
668 ] {
669 let payload = field(value);
670 let fields = NamedFields::decode(&payload).expect(case);
671 assert_eq!(fields.get("a"), Some(value), "{case}");
672 }
673 }
674
675 #[test]
676 fn given_a_named_map_with_many_distinct_fields_when_scanned_then_should_check_them_in_linearithmic_time()
677 {
678 let small = fastest_scan(&distinct_fields(10_000));
680 let large_payload = distinct_fields(80_000);
681 let large = fastest_scan(&large_payload);
682
683 assert!(
684 large < small.max(Duration::from_micros(100)) * 32,
685 "80,000 fields took {large:?}, 10,000 took {small:?}"
686 );
687 let fields = NamedFields::decode(&large_payload).expect("distinct fields scan");
688 assert_eq!(fields.get("f79999"), Some(&[0xf6_u8][..]));
689 let mut repeated = large_payload;
690 repeated.extend(text("f7"));
691 repeated.push(0xf6);
692 repeated[1..5].copy_from_slice(&80_001_u32.to_be_bytes());
693 assert!(matches!(
694 NamedFields::decode(&repeated),
695 Err(DecodeError::Decode(_))
696 ));
697 }
698
699 #[test]
700 fn given_a_named_map_over_the_field_bound_when_scanned_within_it_then_should_refuse_it() {
701 for indefinite in [false, true] {
702 let mut payload = if indefinite { vec![0xbf] } else { vec![0xa3] };
703 for key in ["a", "b", "c"] {
704 payload.extend(text(key));
705 payload.push(0x01);
706 }
707 if indefinite {
708 payload.push(0xff);
709 }
710
711 assert!(
712 matches!(
713 NamedFields::decode_within(&payload, 2),
714 Err(DecodeError::Decode(_))
715 ),
716 "indefinite: {indefinite}"
717 );
718 let within = NamedFields::decode_within(&payload, 3).expect("three fields fit");
719 assert_eq!(within.get("c"), Some(&[0x01_u8][..]));
720 }
721 }
722
723 #[test]
724 fn given_malformed_named_maps_when_scanned_then_should_refuse_them() {
725 let mut duplicate = vec![0xa2];
726 duplicate.extend(text("a"));
727 duplicate.push(0x01);
728 duplicate.extend(text("a"));
729 duplicate.push(0x02);
730 let mut trailing = vec![0xa1];
731 trailing.extend(text("a"));
732 trailing.extend([0x01, 0x00]);
733 let mut numeric_key = vec![0xa1, 0x01, 0x01];
734 let mut truncated = vec![0xa1];
735 truncated.extend(text("a"));
736 truncated.extend([0x45, 0x01, 0x02]);
737 let mut odd = vec![0xbf];
738 odd.extend(text("a"));
739 odd.extend([0x01, 0xbf, 0x01, 0xff, 0xff]);
740 let mut deep = vec![0xa1];
741 deep.extend(text("a"));
742 deep.extend(std::iter::repeat_n(0x81, MAX_SCAN_DEPTH as usize + 2));
743 deep.push(0x01);
744 let mut reserved = vec![0xa1];
745 reserved.extend(text("a"));
746 reserved.push(0x1c);
747 let mut indefinite_number = vec![0xa1];
748 indefinite_number.extend(text("a"));
749 indefinite_number.push(0x1f);
750 numeric_key.push(0x00);
751 numeric_key.truncate(3);
752 for (case, payload) in [
753 ("duplicate", duplicate),
754 ("trailing", trailing),
755 ("numeric key", numeric_key),
756 ("truncated", truncated),
757 ("odd indefinite map", odd),
758 ("deep", deep),
759 ("reserved info", reserved),
760 ("indefinite number", indefinite_number),
761 ("not a map", vec![0x01]),
762 ("empty", Vec::new()),
763 ] {
764 assert!(
765 matches!(NamedFields::decode(&payload), Err(DecodeError::Decode(_))),
766 "{case} must be refused"
767 );
768 }
769 assert!(
770 NamedFields::decode(&[0xa0])
771 .expect("empty map")
772 .get("a")
773 .is_none()
774 );
775 }
776}