1use crate::error::{Error, Result};
4use crate::reader::MAX_DEPTH;
5use crate::tag::Tag;
6use crate::value::Value;
7use crate::{element_type as et, tag_control as tc};
8
9pub struct TlvWriter<'a> {
11 out: &'a mut Vec<u8>,
12}
13
14impl<'a> TlvWriter<'a> {
15 pub fn new(out: &'a mut Vec<u8>) -> Self {
18 Self { out }
19 }
20
21 fn write_tag(&mut self, tag: Tag, element_type: u8) {
24 match tag {
25 Tag::Anonymous => {
26 self.out.push(tc::ANONYMOUS | element_type);
27 }
28 Tag::Context(n) => {
29 self.out.push(tc::CONTEXT | element_type);
30 self.out.push(n);
31 }
32 Tag::CommonProfile(n) => {
33 if let Ok(n16) = u16::try_from(n) {
34 self.out.push(tc::COMMON_PROFILE_2 | element_type);
35 self.out.extend_from_slice(&n16.to_le_bytes());
36 } else {
37 self.out.push(tc::COMMON_PROFILE_4 | element_type);
38 self.out.extend_from_slice(&n.to_le_bytes());
39 }
40 }
41 Tag::ImplicitProfile(n) => {
42 if let Ok(n16) = u16::try_from(n) {
43 self.out.push(tc::IMPLICIT_PROFILE_2 | element_type);
44 self.out.extend_from_slice(&n16.to_le_bytes());
45 } else {
46 self.out.push(tc::IMPLICIT_PROFILE_4 | element_type);
47 self.out.extend_from_slice(&n.to_le_bytes());
48 }
49 }
50 Tag::FullyQualified {
51 vendor,
52 profile,
53 tag,
54 } => {
55 if let Ok(tag16) = u16::try_from(tag) {
56 self.out.push(tc::FULLY_QUALIFIED_6 | element_type);
57 self.out.extend_from_slice(&vendor.to_le_bytes());
58 self.out.extend_from_slice(&profile.to_le_bytes());
59 self.out.extend_from_slice(&tag16.to_le_bytes());
60 } else {
61 self.out.push(tc::FULLY_QUALIFIED_8 | element_type);
62 self.out.extend_from_slice(&vendor.to_le_bytes());
63 self.out.extend_from_slice(&profile.to_le_bytes());
64 self.out.extend_from_slice(&tag.to_le_bytes());
65 }
66 }
67 }
68 }
69
70 pub fn put_bool(&mut self, tag: Tag, v: bool) -> Result<()> {
77 let et = if v { et::BOOL_TRUE } else { et::BOOL_FALSE };
78 self.write_tag(tag, et);
79 Ok(())
80 }
81
82 pub fn put_null(&mut self, tag: Tag) -> Result<()> {
89 self.write_tag(tag, et::NULL);
90 Ok(())
91 }
92
93 pub fn put_uint(&mut self, tag: Tag, v: u64) -> Result<()> {
102 if let Ok(n) = u8::try_from(v) {
103 self.write_tag(tag, et::UINT8);
104 self.out.push(n);
105 } else if let Ok(n) = u16::try_from(v) {
106 self.write_tag(tag, et::UINT16);
107 self.out.extend_from_slice(&n.to_le_bytes());
108 } else if let Ok(n) = u32::try_from(v) {
109 self.write_tag(tag, et::UINT32);
110 self.out.extend_from_slice(&n.to_le_bytes());
111 } else {
112 self.write_tag(tag, et::UINT64);
113 self.out.extend_from_slice(&v.to_le_bytes());
114 }
115 Ok(())
116 }
117
118 pub fn put_int(&mut self, tag: Tag, v: i64) -> Result<()> {
127 if let Ok(n) = i8::try_from(v) {
128 self.write_tag(tag, et::INT8);
129 self.out.push(n.to_le_bytes()[0]);
130 } else if let Ok(n) = i16::try_from(v) {
131 self.write_tag(tag, et::INT16);
132 self.out.extend_from_slice(&n.to_le_bytes());
133 } else if let Ok(n) = i32::try_from(v) {
134 self.write_tag(tag, et::INT32);
135 self.out.extend_from_slice(&n.to_le_bytes());
136 } else {
137 self.write_tag(tag, et::INT64);
138 self.out.extend_from_slice(&v.to_le_bytes());
139 }
140 Ok(())
141 }
142
143 pub fn put_float(&mut self, tag: Tag, v: f32) -> Result<()> {
150 self.write_tag(tag, et::FLOAT32);
151 self.out.extend_from_slice(&v.to_le_bytes());
152 Ok(())
153 }
154
155 pub fn put_double(&mut self, tag: Tag, v: f64) -> Result<()> {
162 self.write_tag(tag, et::FLOAT64);
163 self.out.extend_from_slice(&v.to_le_bytes());
164 Ok(())
165 }
166
167 pub fn put_utf8(&mut self, tag: Tag, v: &str) -> Result<()> {
176 self.put_string_payload(
177 tag,
178 v.as_bytes(),
179 et::UTF8_LEN8,
180 et::UTF8_LEN16,
181 et::UTF8_LEN32,
182 et::UTF8_LEN64,
183 )
184 }
185
186 pub fn put_bytes(&mut self, tag: Tag, v: &[u8]) -> Result<()> {
195 self.put_string_payload(
196 tag,
197 v,
198 et::BYTES_LEN8,
199 et::BYTES_LEN16,
200 et::BYTES_LEN32,
201 et::BYTES_LEN64,
202 )
203 }
204
205 pub fn put_preencoded(&mut self, tag: Tag, element: &[u8]) -> Result<()> {
222 let (&control, rest) = element.split_first().ok_or(Error::UnexpectedEof)?;
223 if control & tc::TAG_CONTROL_MASK != tc::ANONYMOUS {
224 return Err(Error::InvalidTagControl(control & tc::TAG_CONTROL_MASK));
225 }
226 let element_type = control & et::ELEMENT_TYPE_MASK;
227 if element_type == et::END_OF_CONTAINER {
228 return Err(Error::InvalidElementType(element_type));
229 }
230 self.write_tag(tag, element_type);
231 self.out.extend_from_slice(rest);
232 Ok(())
233 }
234
235 fn put_string_payload(
236 &mut self,
237 tag: Tag,
238 bytes: &[u8],
239 et_len8: u8,
240 et_len16: u8,
241 et_len32: u8,
242 et_len64: u8,
243 ) -> Result<()> {
244 let len = bytes.len();
245 if let Ok(len8) = u8::try_from(len) {
246 self.write_tag(tag, et_len8);
247 self.out.push(len8);
248 } else if let Ok(len16) = u16::try_from(len) {
249 self.write_tag(tag, et_len16);
250 self.out.extend_from_slice(&len16.to_le_bytes());
251 } else if let Ok(len32) = u32::try_from(len) {
252 self.write_tag(tag, et_len32);
253 self.out.extend_from_slice(&len32.to_le_bytes());
254 } else {
255 let len64 = u64::try_from(len).map_err(|_| Error::LengthOverflow)?;
256 self.write_tag(tag, et_len64);
257 self.out.extend_from_slice(&len64.to_le_bytes());
258 }
259 self.out.extend_from_slice(bytes);
260 Ok(())
261 }
262
263 pub fn start_structure(&mut self, tag: Tag) -> Result<()> {
272 self.write_tag(tag, et::STRUCTURE);
273 Ok(())
274 }
275
276 pub fn start_array(&mut self, tag: Tag) -> Result<()> {
284 self.write_tag(tag, et::ARRAY);
285 Ok(())
286 }
287
288 pub fn start_list(&mut self, tag: Tag) -> Result<()> {
296 self.write_tag(tag, et::LIST);
297 Ok(())
298 }
299
300 pub fn end_container(&mut self) -> Result<()> {
308 self.out.push(et::END_OF_CONTAINER);
309 Ok(())
310 }
311
312 pub fn write_value(&mut self, tag: Tag, value: &Value) -> Result<()> {
332 self.write_value_at_depth(tag, value, 0)
333 }
334
335 fn write_value_at_depth(&mut self, tag: Tag, value: &Value, depth: usize) -> Result<()> {
339 match value {
340 Value::Bool(v) => self.put_bool(tag, *v),
341 Value::Null => self.put_null(tag),
342 Value::Uint(v) => self.put_uint(tag, *v),
343 Value::Int(v) => self.put_int(tag, *v),
344 Value::Float(v) => self.put_float(tag, *v),
345 Value::Double(v) => self.put_double(tag, *v),
346 Value::Utf8(v) => self.put_utf8(tag, v),
347 Value::Bytes(v) => self.put_bytes(tag, v),
348 Value::Structure(members) => {
349 if depth >= MAX_DEPTH {
350 return Err(Error::ContainerTooDeep);
351 }
352 self.start_structure(tag)?;
353 for (member_tag, member_value) in members {
354 self.write_value_at_depth(*member_tag, member_value, depth + 1)?;
355 }
356 self.end_container()
357 }
358 Value::Array(elements) => {
359 if depth >= MAX_DEPTH {
360 return Err(Error::ContainerTooDeep);
361 }
362 self.start_array(tag)?;
363 for element in elements {
364 self.write_value_at_depth(Tag::Anonymous, element, depth + 1)?;
365 }
366 self.end_container()
367 }
368 Value::List(members) => {
369 if depth >= MAX_DEPTH {
370 return Err(Error::ContainerTooDeep);
371 }
372 self.start_list(tag)?;
373 for (member_tag, member_value) in members {
374 self.write_value_at_depth(*member_tag, member_value, depth + 1)?;
375 }
376 self.end_container()
377 }
378 }
379 }
380}
381
382#[cfg(test)]
383#[allow(clippy::unwrap_used)] mod tests {
386 use super::*;
387
388 #[test]
391 fn put_bool_true_anonymous_matches_vector_0001() {
392 let mut buf = Vec::new();
393 let mut w = TlvWriter::new(&mut buf);
394 w.put_bool(Tag::Anonymous, true).unwrap();
395 assert_eq!(buf, [0x09]);
396 }
397
398 #[test]
399 fn put_bool_false_anonymous_matches_vector_0002() {
400 let mut buf = Vec::new();
401 let mut w = TlvWriter::new(&mut buf);
402 w.put_bool(Tag::Anonymous, false).unwrap();
403 assert_eq!(buf, [0x08]);
404 }
405
406 #[test]
409 fn put_null_anonymous_emits_0x14() {
410 let mut buf = Vec::new();
411 let mut w = TlvWriter::new(&mut buf);
412 w.put_null(Tag::Anonymous).unwrap();
413 assert_eq!(buf, [0x14]);
414 }
415
416 #[test]
419 fn put_uint_42_anonymous_picks_1_byte_width_matches_vector_0003() {
420 let mut buf = Vec::new();
421 let mut w = TlvWriter::new(&mut buf);
422 w.put_uint(Tag::Anonymous, 42).unwrap();
423 assert_eq!(buf, [0x04, 0x2A]);
424 }
425
426 #[test]
427 fn put_uint_max_u8_anonymous_still_1_byte() {
428 let mut buf = Vec::new();
429 let mut w = TlvWriter::new(&mut buf);
430 w.put_uint(Tag::Anonymous, 255).unwrap();
431 assert_eq!(buf, [0x04, 0xFF]);
432 }
433
434 #[test]
435 fn put_uint_0x1234_anonymous_2_byte_le() {
436 let mut buf = Vec::new();
437 let mut w = TlvWriter::new(&mut buf);
438 w.put_uint(Tag::Anonymous, 0x1234).unwrap();
439 assert_eq!(buf, [0x05, 0x34, 0x12]);
440 }
441
442 #[test]
443 fn put_uint_0xcafebabe_anonymous_4_byte_le() {
444 let mut buf = Vec::new();
445 let mut w = TlvWriter::new(&mut buf);
446 w.put_uint(Tag::Anonymous, 0xCAFE_BABE).unwrap();
447 assert_eq!(buf, [0x06, 0xBE, 0xBA, 0xFE, 0xCA]);
448 }
449
450 #[test]
451 fn put_uint_big_anonymous_8_byte_le() {
452 let mut buf = Vec::new();
453 let mut w = TlvWriter::new(&mut buf);
454 w.put_uint(Tag::Anonymous, 0x0123_4567_89AB_CDEF).unwrap();
455 assert_eq!(buf, [0x07, 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01]);
456 }
457
458 #[test]
461 fn put_int_neg17_anonymous_matches_vector_0008() {
462 let mut buf = Vec::new();
463 let mut w = TlvWriter::new(&mut buf);
464 w.put_int(Tag::Anonymous, -17).unwrap();
465 assert_eq!(buf, [0x00, 0xEF]);
466 }
467
468 #[test]
469 fn put_int_neg128_anonymous_1_byte() {
470 let mut buf = Vec::new();
471 let mut w = TlvWriter::new(&mut buf);
472 w.put_int(Tag::Anonymous, -128).unwrap();
473 assert_eq!(buf, [0x00, 0x80]);
474 }
475
476 #[test]
477 fn put_int_neg129_anonymous_2_byte() {
478 let mut buf = Vec::new();
479 let mut w = TlvWriter::new(&mut buf);
480 w.put_int(Tag::Anonymous, -129).unwrap();
481 assert_eq!(buf, [0x01, 0x7F, 0xFF]);
482 }
483
484 #[test]
485 fn put_int_i32_min_anonymous_4_byte() {
486 let mut buf = Vec::new();
487 let mut w = TlvWriter::new(&mut buf);
488 w.put_int(Tag::Anonymous, i64::from(i32::MIN)).unwrap();
489 assert_eq!(buf, [0x02, 0x00, 0x00, 0x00, 0x80]);
490 }
491
492 #[test]
493 fn put_int_i64_min_anonymous_8_byte() {
494 let mut buf = Vec::new();
495 let mut w = TlvWriter::new(&mut buf);
496 w.put_int(Tag::Anonymous, i64::MIN).unwrap();
497 assert_eq!(buf, [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]);
498 }
499
500 #[test]
503 fn put_float_zero_anonymous_matches_vector_0013() {
504 let mut buf = Vec::new();
505 let mut w = TlvWriter::new(&mut buf);
506 w.put_float(Tag::Anonymous, 0.0).unwrap();
507 assert_eq!(buf, [0x0A, 0x00, 0x00, 0x00, 0x00]);
508 }
509
510 #[test]
511 fn put_double_zero_anonymous_matches_vector_0014() {
512 let mut buf = Vec::new();
513 let mut w = TlvWriter::new(&mut buf);
514 w.put_double(Tag::Anonymous, 0.0).unwrap();
515 assert_eq!(buf, [0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
516 }
517
518 #[test]
521 fn put_uint_with_context_tag_5_emits_tag_byte() {
522 let mut buf = Vec::new();
523 let mut w = TlvWriter::new(&mut buf);
524 w.put_uint(Tag::Context(5), 42).unwrap();
525 assert_eq!(buf, [0x24, 0x05, 0x2A]);
528 }
529
530 #[test]
533 fn put_uint_with_common_profile_2_byte_tag() {
534 let mut buf = Vec::new();
535 let mut w = TlvWriter::new(&mut buf);
536 w.put_uint(Tag::CommonProfile(7), 42).unwrap();
537 assert_eq!(buf, [0x44, 0x07, 0x00, 0x2A]);
540 }
541
542 #[test]
543 fn put_uint_with_common_profile_4_byte_tag() {
544 let mut buf = Vec::new();
545 let mut w = TlvWriter::new(&mut buf);
546 w.put_uint(Tag::CommonProfile(0x0001_2345), 42).unwrap();
547 assert_eq!(buf, [0x64, 0x45, 0x23, 0x01, 0x00, 0x2A]);
550 }
551
552 #[test]
553 fn put_uint_with_common_profile_at_u16_boundary_picks_2_byte() {
554 let mut buf = Vec::new();
555 let mut w = TlvWriter::new(&mut buf);
556 w.put_uint(Tag::CommonProfile(0xFFFF), 0).unwrap();
557 assert_eq!(buf, [0x44, 0xFF, 0xFF, 0x00]);
558 }
559
560 #[test]
561 fn put_uint_with_common_profile_just_above_u16_picks_4_byte() {
562 let mut buf = Vec::new();
563 let mut w = TlvWriter::new(&mut buf);
564 w.put_uint(Tag::CommonProfile(0x0001_0000), 0).unwrap();
565 assert_eq!(buf, [0x64, 0x00, 0x00, 0x01, 0x00, 0x00]);
566 }
567
568 #[test]
571 fn put_uint_with_implicit_profile_2_byte_tag() {
572 let mut buf = Vec::new();
573 let mut w = TlvWriter::new(&mut buf);
574 w.put_uint(Tag::ImplicitProfile(7), 42).unwrap();
575 assert_eq!(buf, [0x84, 0x07, 0x00, 0x2A]);
577 }
578
579 #[test]
580 fn put_uint_with_implicit_profile_4_byte_tag() {
581 let mut buf = Vec::new();
582 let mut w = TlvWriter::new(&mut buf);
583 w.put_uint(Tag::ImplicitProfile(0x0001_2345), 42).unwrap();
584 assert_eq!(buf, [0xA4, 0x45, 0x23, 0x01, 0x00, 0x2A]);
586 }
587
588 #[test]
591 fn put_uint_with_fully_qualified_6_byte() {
592 let mut buf = Vec::new();
593 let mut w = TlvWriter::new(&mut buf);
594 w.put_uint(
595 Tag::FullyQualified {
596 vendor: 0xFFF1,
597 profile: 0x0006,
598 tag: 5,
599 },
600 42,
601 )
602 .unwrap();
603 assert_eq!(buf, [0xC4, 0xF1, 0xFF, 0x06, 0x00, 0x05, 0x00, 0x2A]);
606 }
607
608 #[test]
609 fn put_uint_with_fully_qualified_8_byte() {
610 let mut buf = Vec::new();
611 let mut w = TlvWriter::new(&mut buf);
612 w.put_uint(
613 Tag::FullyQualified {
614 vendor: 0xFFF1,
615 profile: 0x0006,
616 tag: 0x0001_2345,
617 },
618 42,
619 )
620 .unwrap();
621 assert_eq!(
623 buf,
624 [0xE4, 0xF1, 0xFF, 0x06, 0x00, 0x45, 0x23, 0x01, 0x00, 0x2A]
625 );
626 }
627
628 #[test]
631 fn put_utf8_hello_anonymous_matches_vector_0015() {
632 let mut buf = Vec::new();
633 let mut w = TlvWriter::new(&mut buf);
634 w.put_utf8(Tag::Anonymous, "Hello!").unwrap();
635 assert_eq!(buf, [0x0C, 0x06, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x21]);
636 }
637
638 #[test]
639 fn put_utf8_empty_anonymous_matches_vector_0016() {
640 let mut buf = Vec::new();
641 let mut w = TlvWriter::new(&mut buf);
642 w.put_utf8(Tag::Anonymous, "").unwrap();
643 assert_eq!(buf, [0x0C, 0x00]);
644 }
645
646 #[test]
647 fn put_utf8_at_255_byte_boundary_uses_len8() {
648 let s: String = "a".repeat(255);
649 let mut buf = Vec::new();
650 let mut w = TlvWriter::new(&mut buf);
651 w.put_utf8(Tag::Anonymous, &s).unwrap();
652 assert_eq!(buf.len(), 1 + 1 + 255);
653 assert_eq!(buf[0], 0x0C);
654 assert_eq!(buf[1], 0xFF);
655 assert!(buf[2..].iter().all(|&b| b == b'a'));
656 }
657
658 #[test]
659 fn put_utf8_at_256_bytes_picks_len16() {
660 let s: String = "a".repeat(256);
661 let mut buf = Vec::new();
662 let mut w = TlvWriter::new(&mut buf);
663 w.put_utf8(Tag::Anonymous, &s).unwrap();
664 assert_eq!(buf.len(), 1 + 2 + 256);
665 assert_eq!(buf[0], 0x0D);
666 assert_eq!(&buf[1..3], &[0x00, 0x01]);
667 assert!(buf[3..].iter().all(|&b| b == b'a'));
668 }
669
670 #[test]
671 fn put_utf8_at_u16_max_uses_len16() {
672 let s: String = "a".repeat(usize::from(u16::MAX));
673 let mut buf = Vec::new();
674 let mut w = TlvWriter::new(&mut buf);
675 w.put_utf8(Tag::Anonymous, &s).unwrap();
676 assert_eq!(buf[0], 0x0D);
677 assert_eq!(&buf[1..3], &[0xFF, 0xFF]);
678 assert_eq!(buf.len(), 1 + 2 + usize::from(u16::MAX));
679 }
680
681 #[test]
682 fn put_utf8_above_u16_max_picks_len32() {
683 let len = usize::from(u16::MAX) + 1; let s: String = "a".repeat(len);
685 let mut buf = Vec::new();
686 let mut w = TlvWriter::new(&mut buf);
687 w.put_utf8(Tag::Anonymous, &s).unwrap();
688 assert_eq!(buf[0], 0x0E);
689 assert_eq!(&buf[1..5], &[0x00, 0x00, 0x01, 0x00]);
690 assert_eq!(buf.len(), 1 + 4 + len);
691 }
692
693 #[test]
696 fn put_bytes_five_bytes_anonymous_matches_vector_0017() {
697 let mut buf = Vec::new();
698 let mut w = TlvWriter::new(&mut buf);
699 w.put_bytes(Tag::Anonymous, &[0x00, 0x01, 0x02, 0x03, 0x04])
700 .unwrap();
701 assert_eq!(buf, [0x10, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04]);
702 }
703
704 #[test]
705 fn put_bytes_empty_anonymous_matches_vector_0018() {
706 let mut buf = Vec::new();
707 let mut w = TlvWriter::new(&mut buf);
708 w.put_bytes(Tag::Anonymous, &[]).unwrap();
709 assert_eq!(buf, [0x10, 0x00]);
710 }
711
712 #[test]
713 fn put_bytes_at_256_bytes_picks_len16() {
714 let data = vec![0xAB; 256];
715 let mut buf = Vec::new();
716 let mut w = TlvWriter::new(&mut buf);
717 w.put_bytes(Tag::Anonymous, &data).unwrap();
718 assert_eq!(buf[0], 0x11);
719 assert_eq!(&buf[1..3], &[0x00, 0x01]);
720 assert_eq!(buf.len(), 1 + 2 + 256);
721 assert!(buf[3..].iter().all(|&b| b == 0xAB));
722 }
723
724 #[test]
727 fn write_value_dispatches_on_utf8_and_bytes_variants() {
728 for (value, expected) in [
729 (
730 Value::Utf8(String::from("Hello!")),
731 vec![0x0C, 0x06, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x21],
732 ),
733 (
734 Value::Bytes(vec![0x00, 0x01, 0x02, 0x03, 0x04]),
735 vec![0x10, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04],
736 ),
737 ] {
738 let mut buf = Vec::new();
739 let mut w = TlvWriter::new(&mut buf);
740 w.write_value(Tag::Anonymous, &value).unwrap();
741 assert_eq!(buf, expected, "value={value:?}");
742 }
743 }
744
745 #[test]
746 fn write_value_dispatches_on_variant() {
747 for (value, expected) in [
749 (Value::Bool(true), vec![0x09]),
750 (Value::Null, vec![0x14]),
751 (Value::Uint(42), vec![0x04, 0x2A]),
752 (Value::Int(-17), vec![0x00, 0xEF]),
753 (Value::Float(0.0), vec![0x0A, 0x00, 0x00, 0x00, 0x00]),
754 (
755 Value::Double(0.0),
756 vec![0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
757 ),
758 ] {
759 let mut buf = Vec::new();
760 let mut w = TlvWriter::new(&mut buf);
761 w.write_value(Tag::Anonymous, &value).unwrap();
762 assert_eq!(buf, expected, "value={value:?}");
763 }
764 }
765
766 #[test]
769 fn start_structure_anonymous_emits_0x15() {
770 let mut buf = Vec::new();
771 let mut w = TlvWriter::new(&mut buf);
772 w.start_structure(Tag::Anonymous).unwrap();
773 assert_eq!(buf, [0x15]);
774 }
775
776 #[test]
777 fn start_array_anonymous_emits_0x16() {
778 let mut buf = Vec::new();
779 let mut w = TlvWriter::new(&mut buf);
780 w.start_array(Tag::Anonymous).unwrap();
781 assert_eq!(buf, [0x16]);
782 }
783
784 #[test]
785 fn start_list_anonymous_emits_0x17() {
786 let mut buf = Vec::new();
787 let mut w = TlvWriter::new(&mut buf);
788 w.start_list(Tag::Anonymous).unwrap();
789 assert_eq!(buf, [0x17]);
790 }
791
792 #[test]
793 fn end_container_emits_0x18() {
794 let mut buf = Vec::new();
795 let mut w = TlvWriter::new(&mut buf);
796 w.end_container().unwrap();
797 assert_eq!(buf, [0x18]);
798 }
799
800 #[test]
801 fn start_structure_with_context_tag_emits_combined_byte() {
802 let mut buf = Vec::new();
803 let mut w = TlvWriter::new(&mut buf);
804 w.start_structure(Tag::Context(7)).unwrap();
805 assert_eq!(buf, [0x35, 0x07]);
807 }
808
809 #[test]
810 fn empty_structure_anonymous_matches_vector_0019() {
811 let mut buf = Vec::new();
812 let mut w = TlvWriter::new(&mut buf);
813 w.start_structure(Tag::Anonymous).unwrap();
814 w.end_container().unwrap();
815 assert_eq!(buf, [0x15, 0x18]);
816 }
817
818 #[test]
819 fn structure_with_one_member_matches_vector_0021() {
820 let mut buf = Vec::new();
822 let mut w = TlvWriter::new(&mut buf);
823 w.start_structure(Tag::Anonymous).unwrap();
824 w.put_uint(Tag::Context(0), 42).unwrap();
825 w.end_container().unwrap();
826 assert_eq!(buf, [0x15, 0x24, 0x00, 0x2A, 0x18]);
827 }
828
829 #[test]
832 fn write_value_empty_structure_matches_vector_0019() {
833 let mut buf = Vec::new();
834 let mut w = TlvWriter::new(&mut buf);
835 w.write_value(Tag::Anonymous, &Value::Structure(Vec::new()))
836 .unwrap();
837 assert_eq!(buf, [0x15, 0x18]);
838 }
839
840 #[test]
841 fn write_value_empty_array_matches_vector_0020() {
842 let mut buf = Vec::new();
843 let mut w = TlvWriter::new(&mut buf);
844 w.write_value(Tag::Anonymous, &Value::Array(Vec::new()))
845 .unwrap();
846 assert_eq!(buf, [0x16, 0x18]);
847 }
848
849 #[test]
850 fn write_value_structure_with_ctx_member_matches_vector_0021() {
851 let value = Value::Structure(vec![(Tag::Context(0), Value::Uint(42))]);
852 let mut buf = Vec::new();
853 let mut w = TlvWriter::new(&mut buf);
854 w.write_value(Tag::Anonymous, &value).unwrap();
855 assert_eq!(buf, [0x15, 0x24, 0x00, 0x2A, 0x18]);
856 }
857
858 #[test]
859 fn write_value_array_of_three_uint8_matches_vector_0022() {
860 let value = Value::Array(vec![Value::Uint(1), Value::Uint(2), Value::Uint(3)]);
861 let mut buf = Vec::new();
862 let mut w = TlvWriter::new(&mut buf);
863 w.write_value(Tag::Anonymous, &value).unwrap();
864 assert_eq!(buf, [0x16, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x18]);
865 }
866
867 #[test]
868 fn write_value_structure_with_bool_at_ctx7_matches_vector_0023() {
869 let value = Value::Structure(vec![(Tag::Context(7), Value::Bool(true))]);
870 let mut buf = Vec::new();
871 let mut w = TlvWriter::new(&mut buf);
872 w.write_value(Tag::Anonymous, &value).unwrap();
873 assert_eq!(buf, [0x15, 0x29, 0x07, 0x18]);
874 }
875
876 #[test]
877 fn write_value_empty_list_emits_0x17_0x18() {
878 let mut buf = Vec::new();
879 let mut w = TlvWriter::new(&mut buf);
880 w.write_value(Tag::Anonymous, &Value::List(Vec::new()))
881 .unwrap();
882 assert_eq!(buf, [0x17, 0x18]);
883 }
884
885 #[test]
888 fn put_preencoded_retags_anonymous_struct_to_context_1() {
889 let anonymous_struct = vec![0x15u8, 0x18];
891 let mut buf = Vec::new();
892 let mut w = TlvWriter::new(&mut buf);
893 w.put_preencoded(Tag::Context(1), &anonymous_struct)
894 .unwrap();
895 assert_eq!(buf, [0x35, 0x01, 0x18]);
900 }
901
902 #[test]
903 fn put_preencoded_rejects_empty_input() {
904 let mut buf = Vec::new();
905 let mut w = TlvWriter::new(&mut buf);
906 assert!(matches!(
907 w.put_preencoded(Tag::Context(0), &[]),
908 Err(Error::UnexpectedEof)
909 ));
910 }
911
912 #[test]
913 fn put_preencoded_rejects_non_anonymous_input() {
914 let non_anonymous = vec![0x28u8, 0x00];
916 let mut buf = Vec::new();
917 let mut w = TlvWriter::new(&mut buf);
918 assert!(matches!(
919 w.put_preencoded(Tag::Context(0), &non_anonymous),
920 Err(Error::InvalidTagControl(_))
921 ));
922 }
923
924 #[test]
925 fn put_preencoded_rejects_bare_end_of_container() {
926 let mut buf = Vec::new();
929 let mut w = TlvWriter::new(&mut buf);
930 assert!(matches!(
931 w.put_preencoded(Tag::Context(1), &[0x18]),
932 Err(Error::InvalidElementType(_))
933 ));
934 }
935
936 #[test]
937 fn write_value_nested_structure() {
938 let inner = Value::Structure(vec![(Tag::Context(0), Value::Uint(42))]);
940 let outer = Value::Structure(vec![(Tag::Context(0), inner)]);
941 let mut buf = Vec::new();
942 let mut w = TlvWriter::new(&mut buf);
943 w.write_value(Tag::Anonymous, &outer).unwrap();
944 assert_eq!(buf, [0x15, 0x35, 0x00, 0x24, 0x00, 0x2A, 0x18, 0x18]);
950 }
951
952 fn nested_structure(levels: usize) -> Value {
957 let mut v = Value::Uint(0);
958 for _ in 0..levels {
959 v = Value::Structure(vec![(Tag::Anonymous, v)]);
960 }
961 v
962 }
963
964 #[test]
965 fn write_value_accepts_tree_at_max_depth() {
966 let value = nested_structure(MAX_DEPTH);
969 let mut buf = Vec::new();
970 let mut w = TlvWriter::new(&mut buf);
971 assert!(w.write_value(Tag::Anonymous, &value).is_ok());
972 }
973
974 #[test]
975 fn write_value_rejects_over_deep_tree() {
976 let value = nested_structure(MAX_DEPTH + 1);
979 let mut buf = Vec::new();
980 let mut w = TlvWriter::new(&mut buf);
981 assert!(matches!(
982 w.write_value(Tag::Anonymous, &value),
983 Err(Error::ContainerTooDeep)
984 ));
985 }
986
987 #[test]
988 fn write_value_over_deep_tree_roundtrips_with_reader_limit() {
989 let ok = nested_structure(MAX_DEPTH);
992 let mut buf = Vec::new();
993 TlvWriter::new(&mut buf)
994 .write_value(Tag::Anonymous, &ok)
995 .unwrap();
996 let (_, decoded) = crate::reader::TlvReader::new(&buf).read_value().unwrap();
997 assert_eq!(decoded, ok);
998 }
999}