1use num_traits::ToBytes;
19
20use crate::error::{Error, ErrorCode};
21use crate::utils::storage::WriteBuf;
22
23use super::{TLVControl, TLVTag, TLVTagType, TLVValue, TLVValueType, ToTLV};
24
25pub trait TLVWrite {
40 type Position: PartialEq + Copy;
41
42 fn write_ctx<T: ToTLV>(&mut self, ctx: u8, value: &T) -> Result<(), Error>
51 where
52 Self: Sized,
53 {
54 value.to_tlv(&TLVTag::Context(ctx), self)
55 }
56
57 fn tlv(&mut self, tag: &TLVTag, value: &TLVValue) -> Result<(), Error> {
59 self.raw_value(tag, value.value_type(), &[])?;
60
61 match value {
62 TLVValue::Str8l(a) => self.write_raw_data((a.len() as u8).to_le_bytes()),
63 TLVValue::Str16l(a) => self.write_raw_data((a.len() as u16).to_le_bytes()),
64 TLVValue::Str32l(a) => self.write_raw_data((a.len() as u32).to_le_bytes()),
65 TLVValue::Str64l(a) => self.write_raw_data((a.len() as u64).to_le_bytes()),
66 TLVValue::Utf8l(a) => self.write_raw_data((a.len() as u8).to_le_bytes()),
67 TLVValue::Utf16l(a) => self.write_raw_data((a.len() as u16).to_le_bytes()),
68 TLVValue::Utf32l(a) => self.write_raw_data((a.len() as u32).to_le_bytes()),
69 TLVValue::Utf64l(a) => self.write_raw_data((a.len() as u64).to_le_bytes()),
70 _ => Ok(()),
71 }?;
72
73 match value {
74 TLVValue::S8(a) => self.write_raw_data(a.to_le_bytes()),
75 TLVValue::S16(a) => self.write_raw_data(a.to_le_bytes()),
76 TLVValue::S32(a) => self.write_raw_data(a.to_le_bytes()),
77 TLVValue::S64(a) => self.write_raw_data(a.to_le_bytes()),
78 TLVValue::U8(a) => self.write_raw_data(a.to_le_bytes()),
79 TLVValue::U16(a) => self.write_raw_data(a.to_le_bytes()),
80 TLVValue::U32(a) => self.write_raw_data(a.to_le_bytes()),
81 TLVValue::U64(a) => self.write_raw_data(a.to_le_bytes()),
82 TLVValue::False => Ok(()),
83 TLVValue::True => Ok(()),
84 TLVValue::F32(a) => self.write_raw_data(a.to_le_bytes()),
85 TLVValue::F64(a) => self.write_raw_data(a.to_le_bytes()),
86 TLVValue::Utf8l(a)
87 | TLVValue::Utf16l(a)
88 | TLVValue::Utf32l(a)
89 | TLVValue::Utf64l(a) => self.write_raw_data(a.as_bytes().iter().copied()),
90 TLVValue::Str8l(a)
91 | TLVValue::Str16l(a)
92 | TLVValue::Str32l(a)
93 | TLVValue::Str64l(a) => self.write_raw_data(a.iter().copied()),
94 TLVValue::Null
95 | TLVValue::Struct
96 | TLVValue::Array
97 | TLVValue::List
98 | TLVValue::EndCnt => Ok(()),
99 }
100 }
101
102 fn i8(&mut self, tag: &TLVTag, data: i8) -> Result<(), Error> {
104 self.raw_value(tag, TLVValueType::S8, &data.to_le_bytes())
105 }
106
107 fn u8(&mut self, tag: &TLVTag, data: u8) -> Result<(), Error> {
109 self.raw_value(tag, TLVValueType::U8, &data.to_le_bytes())
110 }
111
112 fn i16(&mut self, tag: &TLVTag, data: i16) -> Result<(), Error> {
114 if data >= i8::MIN as i16 && data <= i8::MAX as i16 {
115 self.i8(tag, data as i8)
116 } else {
117 self.raw_value(tag, TLVValueType::S16, &data.to_le_bytes())
118 }
119 }
120
121 fn u16(&mut self, tag: &TLVTag, data: u16) -> Result<(), Error> {
123 if data <= u8::MAX as u16 {
124 self.u8(tag, data as u8)
125 } else {
126 self.raw_value(tag, TLVValueType::U16, &data.to_le_bytes())
127 }
128 }
129
130 fn i32(&mut self, tag: &TLVTag, data: i32) -> Result<(), Error> {
132 if data >= i16::MIN as i32 && data <= i16::MAX as i32 {
133 self.i16(tag, data as i16)
134 } else {
135 self.raw_value(tag, TLVValueType::S32, &data.to_le_bytes())
136 }
137 }
138
139 fn u32(&mut self, tag: &TLVTag, data: u32) -> Result<(), Error> {
141 if data <= u16::MAX as u32 {
142 self.u16(tag, data as u16)
143 } else {
144 self.raw_value(tag, TLVValueType::U32, &data.to_le_bytes())
145 }
146 }
147
148 fn i64(&mut self, tag: &TLVTag, data: i64) -> Result<(), Error> {
150 if data >= i32::MIN as i64 && data <= i32::MAX as i64 {
151 self.i32(tag, data as i32)
152 } else {
153 self.raw_value(tag, TLVValueType::S64, &data.to_le_bytes())
154 }
155 }
156
157 fn u64(&mut self, tag: &TLVTag, data: u64) -> Result<(), Error> {
159 if data <= u32::MAX as u64 {
160 self.u32(tag, data as u32)
161 } else {
162 self.raw_value(tag, TLVValueType::U64, &data.to_le_bytes())
163 }
164 }
165
166 fn f32(&mut self, tag: &TLVTag, data: f32) -> Result<(), Error> {
168 self.raw_value(tag, TLVValueType::F32, &data.to_le_bytes())
169 }
170
171 fn f64(&mut self, tag: &TLVTag, data: f64) -> Result<(), Error> {
173 self.raw_value(tag, TLVValueType::F64, &data.to_le_bytes())
174 }
175
176 fn str(&mut self, tag: &TLVTag, data: &[u8]) -> Result<(), Error> {
181 self.stri(tag, data.len(), data.iter().copied())
182 }
183
184 fn str_cb(
197 &mut self,
198 _tag: &TLVTag,
199 _cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
200 ) -> Result<(), Error> {
201 unimplemented!("str_cb not implemented for this TLVWrite instance");
202 }
203
204 fn stri<I>(&mut self, tag: &TLVTag, len: usize, data: I) -> Result<(), Error>
213 where
214 I: IntoIterator<Item = u8>,
215 {
216 if len <= u8::MAX as usize {
217 self.raw_value(tag, TLVValueType::Str8l, &(len as u8).to_le_bytes())?;
218 } else if len <= u16::MAX as usize {
219 self.raw_value(tag, TLVValueType::Str16l, &(len as u16).to_le_bytes())?;
220 } else if len <= u32::MAX as usize {
221 self.raw_value(tag, TLVValueType::Str32l, &(len as u32).to_le_bytes())?;
222 } else {
223 self.raw_value(tag, TLVValueType::Str64l, &(len as u64).to_le_bytes())?;
224 }
225
226 self.write_raw_data(data)
227 }
228
229 fn utf8(&mut self, tag: &TLVTag, data: &str) -> Result<(), Error> {
234 self.utf8i(tag, data.len(), data.as_bytes().iter().copied())
235 }
236
237 fn utf8i<I>(&mut self, tag: &TLVTag, len: usize, data: I) -> Result<(), Error>
248 where
249 I: IntoIterator<Item = u8>,
250 {
251 if len <= u8::MAX as usize {
252 self.raw_value(tag, TLVValueType::Utf8l, &(len as u8).to_le_bytes())?;
253 } else if len <= u16::MAX as usize {
254 self.raw_value(tag, TLVValueType::Utf16l, &(len as u16).to_le_bytes())?;
255 } else if len <= u32::MAX as usize {
256 self.raw_value(tag, TLVValueType::Utf32l, &(len as u32).to_le_bytes())?;
257 } else {
258 self.raw_value(tag, TLVValueType::Utf64l, &(len as u64).to_le_bytes())?;
259 }
260
261 self.write_raw_data(data)
262 }
263
264 fn utf8_cb(
277 &mut self,
278 _tag: &TLVTag,
279 _cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
280 ) -> Result<(), Error> {
281 unimplemented!("utf8_cb not implemented for this TLVWrite instance");
282 }
283
284 fn start_struct(&mut self, tag: &TLVTag) -> Result<(), Error> {
289 self.raw_value(tag, TLVValueType::Struct, &[])
290 }
291
292 fn start_array(&mut self, tag: &TLVTag) -> Result<(), Error> {
297 self.raw_value(tag, TLVValueType::Array, &[])
298 }
299
300 fn start_list(&mut self, tag: &TLVTag) -> Result<(), Error> {
305 self.raw_value(tag, TLVValueType::List, &[])
306 }
307
308 fn start_container(&mut self, tag: &TLVTag, container_type: TLVValueType) -> Result<(), Error> {
313 if !container_type.is_container() {
314 Err(ErrorCode::TLVTypeMismatch)?;
315 }
316
317 self.raw_value(tag, container_type, &[])
318 }
319
320 fn end_container(&mut self) -> Result<(), Error> {
325 self.write(TLVControl::new(TLVTagType::Anonymous, TLVValueType::EndCnt).as_raw())
326 }
327
328 fn null(&mut self, tag: &TLVTag) -> Result<(), Error> {
330 self.raw_value(tag, TLVValueType::Null, &[])
331 }
332
333 fn bool(&mut self, tag: &TLVTag, val: bool) -> Result<(), Error> {
335 self.raw_value(
336 tag,
337 if val {
338 TLVValueType::True
339 } else {
340 TLVValueType::False
341 },
342 &[],
343 )
344 }
345
346 fn raw_value(
348 &mut self,
349 tag: &TLVTag,
350 value_type: TLVValueType,
351 value_payload: &[u8],
352 ) -> Result<(), Error> {
353 self.write(TLVControl::new(tag.tag_type(), value_type).as_raw())?;
354
355 match tag {
356 TLVTag::Anonymous => Ok(()),
357 TLVTag::Context(v) => self.write_raw_data(v.to_le_bytes()),
358 TLVTag::CommonPrf16(v) | TLVTag::ImplPrf16(v) => self.write_raw_data(v.to_le_bytes()),
359 TLVTag::CommonPrf32(v) | TLVTag::ImplPrf32(v) => self.write_raw_data(v.to_le_bytes()),
360 TLVTag::FullQual48 {
361 vendor_id,
362 profile,
363 tag,
364 } => {
365 self.write_raw_data(vendor_id.to_le_bytes())?;
366 self.write_raw_data(profile.to_le_bytes())?;
367 self.write_raw_data(tag.to_le_bytes())
368 }
369 TLVTag::FullQual64 {
370 vendor_id,
371 profile,
372 tag,
373 } => {
374 self.write_raw_data(vendor_id.to_le_bytes())?;
375 self.write_raw_data(profile.to_le_bytes())?;
376 self.write_raw_data(tag.to_le_bytes())
377 }
378 }?;
379
380 self.write_raw_data(value_payload.iter().copied())
381 }
382
383 fn write_raw_data<I>(&mut self, bytes: I) -> Result<(), Error>
385 where
386 I: IntoIterator<Item = u8>,
387 {
388 for byte in bytes {
389 self.write(byte)?;
390 }
391
392 Ok(())
393 }
394
395 fn write(&mut self, byte: u8) -> Result<(), Error>;
397
398 fn get_tail(&self) -> Self::Position {
402 unimplemented!("get_tail not implemented for this TLVWrite instance");
403 }
404
405 fn rewind_to(&mut self, _pos: Self::Position) {
409 unimplemented!("rewind_to not implemented for this TLVWrite instance");
410 }
411
412 fn available_space(&mut self) -> &mut [u8] {
418 unimplemented!("available_space not implemented for this TLVWrite instance");
419 }
420}
421
422impl<T> TLVWrite for &mut T
423where
424 T: TLVWrite,
425{
426 type Position = T::Position;
427
428 fn write(&mut self, byte: u8) -> Result<(), Error> {
429 (**self).write(byte)
430 }
431
432 fn get_tail(&self) -> Self::Position {
433 (**self).get_tail()
434 }
435
436 fn rewind_to(&mut self, pos: Self::Position) {
437 (**self).rewind_to(pos)
438 }
439
440 fn available_space(&mut self) -> &mut [u8] {
441 (**self).available_space()
442 }
443
444 fn str_cb(
445 &mut self,
446 tag: &TLVTag,
447 cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
448 ) -> Result<(), Error> {
449 (**self).str_cb(tag, cb)
450 }
451
452 fn utf8_cb(
453 &mut self,
454 tag: &TLVTag,
455 cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
456 ) -> Result<(), Error> {
457 (**self).utf8_cb(tag, cb)
458 }
459}
460
461impl TLVWrite for WriteBuf<'_> {
462 type Position = usize;
463
464 fn write(&mut self, byte: u8) -> Result<(), Error> {
465 WriteBuf::append(self, &[byte])
466 }
467
468 fn get_tail(&self) -> Self::Position {
469 WriteBuf::get_tail(self)
470 }
471
472 fn rewind_to(&mut self, pos: Self::Position) {
473 WriteBuf::rewind_tail_to(self, pos)
474 }
475
476 fn available_space(&mut self) -> &mut [u8] {
477 WriteBuf::empty_as_mut_slice(self)
478 }
479
480 fn str_cb(
481 &mut self,
482 tag: &TLVTag,
483 cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
484 ) -> Result<(), Error> {
485 WriteBuf::str_cb(self, tag, cb)
486 }
487
488 fn utf8_cb(
489 &mut self,
490 tag: &TLVTag,
491 cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
492 ) -> Result<(), Error> {
493 WriteBuf::utf8_cb(self, tag, cb)
494 }
495}
496
497impl WriteBuf<'_> {
498 pub fn str_cb(
511 &mut self,
512 tag: &TLVTag,
513 cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
514 ) -> Result<(), Error> {
515 let control_offset = self.get_tail();
516 self.raw_value(tag, TLVValueType::Str16l, &0_u16.to_le_bytes())?;
517
518 let value_offset = self.get_tail();
519
520 let len = self.append_with_buf(cb)?;
521
522 Self::finalize_len_header(
523 self,
524 control_offset,
525 value_offset,
526 len,
527 tag.tag_type(),
528 TLVValueType::Str8l,
529 );
530
531 Ok(())
532 }
533
534 pub fn utf8_cb(
546 &mut self,
547 tag: &TLVTag,
548 cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
549 ) -> Result<(), Error> {
550 let control_offset = self.get_tail();
551 self.raw_value(tag, TLVValueType::Utf16l, &0_u16.to_le_bytes())?;
552
553 let value_offset = self.get_tail();
554
555 let len = self.append_with_buf(cb)?;
556
557 Self::finalize_len_header(
558 self,
559 control_offset,
560 value_offset,
561 len,
562 tag.tag_type(),
563 TLVValueType::Utf8l,
564 );
565
566 Ok(())
567 }
568
569 fn finalize_len_header(
582 this: &mut WriteBuf<'_>,
583 control_offset: usize,
584 value_offset: usize,
585 len: usize,
586 tag_type: TLVTagType,
587 short_value_type: TLVValueType,
588 ) {
589 if len <= u8::MAX as usize {
590 this.buf[control_offset] = TLVControl::new(tag_type, short_value_type).as_raw();
592 this.buf[value_offset - 2] = len as u8;
593 this.buf
594 .copy_within(value_offset..value_offset + len, value_offset - 1);
595 this.rewind_tail_to(this.get_tail() - 1);
596 } else if len <= u16::MAX as usize {
597 this.buf[value_offset - 2..value_offset].copy_from_slice(&(len as u16).to_le_bytes());
599 } else {
600 panic!("Callback wrote more data than the reserved header can encode");
602 }
603 }
604}
605
606#[cfg(test)]
607mod tests {
608 use core::f32;
609
610 use super::{TLVTag, TLVWrite};
611 use crate::{tlv::TLVValue, utils::storage::WriteBuf};
612
613 #[test]
614 fn test_write_success() {
615 let mut buf = [0; 20];
616 let mut tw = WriteBuf::new(&mut buf);
617
618 tw.start_struct(&TLVTag::Anonymous).unwrap();
619 tw.u8(&TLVTag::Anonymous, 12).unwrap();
620 tw.u8(&TLVTag::Context(1), 13).unwrap();
621 tw.u16(&TLVTag::Anonymous, 0x1212).unwrap();
622 tw.u16(&TLVTag::Context(2), 0x1313).unwrap();
623 tw.start_array(&TLVTag::Context(3)).unwrap();
624 tw.bool(&TLVTag::Anonymous, true).unwrap();
625 tw.end_container().unwrap();
626 tw.end_container().unwrap();
627 assert_eq!(
628 buf,
629 [21, 4, 12, 36, 1, 13, 5, 0x12, 0x012, 37, 2, 0x13, 0x13, 54, 3, 9, 24, 24, 0, 0]
630 );
631 }
632
633 #[test]
634 fn test_write_overflow() {
635 let mut buf = [0; 6];
636 let mut tw = WriteBuf::new(&mut buf);
637
638 tw.u8(&TLVTag::Anonymous, 12).unwrap();
639 tw.u8(&TLVTag::Context(1), 13).unwrap();
640 if tw.u16(&TLVTag::Anonymous, 12).is_ok() {
641 panic!("This should have returned error")
642 }
643 if tw.u16(&TLVTag::Context(2), 13).is_ok() {
644 panic!("This should have returned error")
645 }
646 assert_eq!(buf, [4, 12, 36, 1, 13, 4]);
647 }
648
649 #[test]
650 fn test_put_str8() {
651 let mut buf = [0; 20];
652 let mut tw = WriteBuf::new(&mut buf);
653
654 tw.u8(&TLVTag::Context(1), 13).unwrap();
655 tw.str(&TLVTag::Anonymous, &[10, 11, 12, 13, 14]).unwrap();
656 tw.u16(&TLVTag::Context(2), 0x1313).unwrap();
657 tw.str(&TLVTag::Context(3), &[20, 21, 22]).unwrap();
658 assert_eq!(
659 buf,
660 [36, 1, 13, 16, 5, 10, 11, 12, 13, 14, 37, 2, 0x13, 0x13, 48, 3, 3, 20, 21, 22]
661 );
662 }
663
664 #[test]
665 fn test_matter_spec_examples() {
666 let mut buf = [0; 200];
667 let mut tw = WriteBuf::new(&mut buf);
668
669 tw.bool(&TLVTag::Anonymous, false).unwrap();
672 assert_eq!(&[0x08], tw.as_slice());
673
674 tw.reset();
677 tw.bool(&TLVTag::Anonymous, true).unwrap();
678 assert_eq!(&[0x09], tw.as_slice());
679
680 tw.reset();
683 tw.i8(&TLVTag::Anonymous, 42).unwrap();
684 assert_eq!(&[0x00, 0x2a], tw.as_slice());
685
686 tw.reset();
689 tw.i32(&TLVTag::Anonymous, -17).unwrap();
690 assert_eq!(&[0x00, 0xef], tw.as_slice());
691
692 tw.reset();
695 tw.u8(&TLVTag::Anonymous, 42).unwrap();
696 assert_eq!(&[0x04, 0x2a], tw.as_slice());
697
698 tw.reset();
701 tw.i16(&TLVTag::Anonymous, 422).unwrap();
702 assert_eq!(&[0x01, 0xa6, 0x01], tw.as_slice());
703
704 tw.reset();
707 tw.i32(&TLVTag::Anonymous, -170000).unwrap();
708 assert_eq!(&[0x02, 0xf0, 0x67, 0xfd, 0xff], tw.as_slice());
709
710 tw.reset();
713 tw.i64(&TLVTag::Anonymous, 40000000000).unwrap();
714 assert_eq!(
715 &[0x03, 0x00, 0x90, 0x2f, 0x50, 0x09, 0x00, 0x00, 0x00],
716 tw.as_slice()
717 );
718
719 tw.reset();
722 tw.utf8(&TLVTag::Anonymous, "Hello!").unwrap();
723 assert_eq!(
724 &[0x0c, 0x06, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21],
725 tw.as_slice()
726 );
727
728 tw.reset();
731 tw.utf8i(
732 &TLVTag::Anonymous,
733 "Tschüs".len(),
734 "Tschüs".as_bytes().iter().copied(),
735 )
736 .unwrap();
737 assert_eq!(
738 &[0x0c, 0x07, 0x54, 0x73, 0x63, 0x68, 0xc3, 0xbc, 0x73],
739 tw.as_slice()
740 );
741
742 tw.reset();
745 tw.str(&TLVTag::Anonymous, &[0x00, 0x01, 0x02, 0x03, 0x04])
746 .unwrap();
747 assert_eq!(&[0x10, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04], tw.as_slice());
748
749 tw.reset();
752 tw.tlv(&TLVTag::Anonymous, &TLVValue::Null).unwrap();
753 assert_eq!(&[0x14], tw.as_slice());
754
755 tw.reset();
758 tw.tlv(&TLVTag::Anonymous, &TLVValue::F32(0.0)).unwrap();
759 assert_eq!(&[0x0a, 0x00, 0x00, 0x00, 0x00], tw.as_slice());
760
761 tw.reset();
764 tw.f32(&TLVTag::Anonymous, 1.0 / 3.0).unwrap();
765 assert_eq!(&[0x0a, 0xab, 0xaa, 0xaa, 0x3e], tw.as_slice());
766
767 tw.reset();
770 tw.f32(&TLVTag::Anonymous, 17.9).unwrap();
771 assert_eq!(&[0x0a, 0x33, 0x33, 0x8f, 0x41], tw.as_slice());
772
773 tw.reset();
776 tw.f32(&TLVTag::Anonymous, f32::INFINITY).unwrap();
777 assert_eq!(&[0x0a, 0x00, 0x00, 0x80, 0x7f], tw.as_slice());
778
779 tw.reset();
782 tw.f32(&TLVTag::Anonymous, f32::NEG_INFINITY).unwrap();
783 assert_eq!(&[0x0a, 0x00, 0x00, 0x80, 0xff], tw.as_slice());
784
785 tw.reset();
788 tw.f64(&TLVTag::Anonymous, 0.0).unwrap();
789 assert_eq!(
790 &[0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
791 tw.as_slice()
792 );
793
794 tw.reset();
797 tw.f64(&TLVTag::Anonymous, 1.0 / 3.0).unwrap();
798 assert_eq!(
799 &[0x0b, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x3f],
800 tw.as_slice()
801 );
802
803 tw.reset();
806 tw.f64(&TLVTag::Anonymous, 17.9).unwrap();
807 assert_eq!(
808 &[0x0b, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x31, 0x40],
809 tw.as_slice()
810 );
811
812 tw.reset();
815 tw.f64(&TLVTag::Anonymous, f64::INFINITY).unwrap();
816 assert_eq!(
817 &[0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f],
818 tw.as_slice()
819 );
820
821 tw.reset();
824 tw.f64(&TLVTag::Anonymous, f64::NEG_INFINITY).unwrap();
825 assert_eq!(
826 &[0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff],
827 tw.as_slice()
828 );
829
830 tw.reset();
833 tw.start_struct(&TLVTag::Anonymous).unwrap();
834 tw.end_container().unwrap();
835 assert_eq!(&[0x15, 0x18], tw.as_slice());
836
837 tw.reset();
840 tw.start_array(&TLVTag::Anonymous).unwrap();
841 tw.end_container().unwrap();
842 assert_eq!(&[0x16, 0x18], tw.as_slice());
843
844 tw.reset();
847 tw.start_list(&TLVTag::Anonymous).unwrap();
848 tw.end_container().unwrap();
849 assert_eq!(&[0x17, 0x18], tw.as_slice());
850
851 tw.reset();
854 tw.start_struct(&TLVTag::Anonymous).unwrap();
855 tw.i8(&TLVTag::Context(0), 42).unwrap();
856 tw.i32(&TLVTag::Context(1), -17).unwrap();
857 tw.end_container().unwrap();
858 assert_eq!(
859 &[0x15, 0x20, 0x00, 0x2a, 0x20, 0x01, 0xef, 0x18],
860 tw.as_slice()
861 );
862
863 tw.reset();
866 tw.start_array(&TLVTag::Anonymous).unwrap();
867 for i in 0..5 {
868 tw.i8(&TLVTag::Anonymous, i as i8).unwrap();
869 }
870 tw.end_container().unwrap();
871 assert_eq!(
872 &[0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x18],
873 tw.as_slice()
874 );
875
876 tw.reset();
879 tw.start_list(&TLVTag::Anonymous).unwrap();
880 tw.i64(&TLVTag::Anonymous, 1).unwrap();
881 tw.i16(&TLVTag::Context(0), 42).unwrap();
882 tw.i8(&TLVTag::Anonymous, 2).unwrap();
883 tw.i8(&TLVTag::Anonymous, 3).unwrap();
884 tw.i32(&TLVTag::Context(0), -17).unwrap();
885 tw.end_container().unwrap();
886 assert_eq!(
887 &[0x17, 0x00, 0x01, 0x20, 0x00, 0x2a, 0x00, 0x02, 0x00, 0x03, 0x20, 0x00, 0xef, 0x18],
888 tw.as_slice()
889 );
890
891 tw.reset();
894 tw.start_array(&TLVTag::Anonymous).unwrap();
895 tw.i64(&TLVTag::Anonymous, 42).unwrap();
896 tw.i64(&TLVTag::Anonymous, -170000).unwrap();
897 tw.start_struct(&TLVTag::Anonymous).unwrap();
898 tw.end_container().unwrap();
899 tw.f32(&TLVTag::Anonymous, 17.9).unwrap();
900 tw.utf8(&TLVTag::Anonymous, "Hello!").unwrap();
901 tw.end_container().unwrap();
902 assert_eq!(
903 &[
904 0x16, 0x00, 0x2a, 0x02, 0xf0, 0x67, 0xfd, 0xff, 0x15, 0x18, 0x0a, 0x33, 0x33, 0x8f,
905 0x41, 0x0c, 0x06, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21, 0x18,
906 ],
907 tw.as_slice()
908 );
909
910 tw.reset();
913 tw.u64(&TLVTag::Anonymous, 42).unwrap();
914 assert_eq!(&[0x04, 0x2a], tw.as_slice());
915
916 tw.reset();
919 tw.u64(&TLVTag::Context(1), 42).unwrap();
920 assert_eq!(&[0x24, 0x01, 0x2a], tw.as_slice());
921
922 tw.reset();
925 tw.u64(&TLVTag::CommonPrf16(1), 42).unwrap();
926 assert_eq!(&[0x44, 0x01, 0x00, 0x2a], tw.as_slice());
927
928 tw.reset();
931 tw.u64(&TLVTag::CommonPrf32(100000), 42).unwrap();
932 assert_eq!(&[0x64, 0xa0, 0x86, 0x01, 0x00, 0x2a], tw.as_slice());
933
934 tw.reset();
938 tw.u64(
939 &TLVTag::FullQual48 {
940 vendor_id: 65521,
941 profile: 57069,
942 tag: 1,
943 },
944 42,
945 )
946 .unwrap();
947 assert_eq!(
948 &[0xc4, 0xf1, 0xff, 0xed, 0xde, 0x01, 0x00, 0x2a],
949 tw.as_slice()
950 );
951
952 tw.reset();
956 tw.u64(
957 &TLVTag::FullQual64 {
958 vendor_id: 65521,
959 profile: 57069,
960 tag: 2857762541,
961 },
962 42,
963 )
964 .unwrap();
965 assert_eq!(
966 &[0xe4, 0xf1, 0xff, 0xed, 0xde, 0xed, 0xfe, 0x55, 0xaa, 0x2a],
967 tw.as_slice()
968 );
969
970 tw.reset();
975 tw.start_struct(&TLVTag::FullQual48 {
976 vendor_id: 65521,
977 profile: 57069,
978 tag: 1,
979 })
980 .unwrap();
981 tw.u64(
982 &TLVTag::FullQual48 {
983 vendor_id: 65521,
984 profile: 57069,
985 tag: 43605,
986 },
987 42,
988 )
989 .unwrap();
990 tw.end_container().unwrap();
991 assert_eq!(
992 &[
993 0xd5, 0xf1, 0xff, 0xed, 0xde, 0x01, 0x00, 0xc4, 0xf1, 0xff, 0xed, 0xde, 0x55, 0xaa,
994 0x2a, 0x18,
995 ],
996 tw.as_slice()
997 );
998 }
999}