1use num_traits::ToBytes;
19
20use crate::error::{Error, ErrorCode};
21use crate::utils::storage::WriteBuf;
22
23use super::{TLVControl, TLVTag, TLVTagType, TLVValue, TLVValueType};
24
25pub trait TLVWrite {
40 type Position: PartialEq + Copy;
41
42 fn tlv(&mut self, tag: &TLVTag, value: &TLVValue) -> Result<(), Error> {
44 self.raw_value(tag, value.value_type(), &[])?;
45
46 match value {
47 TLVValue::Str8l(a) => self.write_raw_data((a.len() as u8).to_le_bytes()),
48 TLVValue::Str16l(a) => self.write_raw_data((a.len() as u16).to_le_bytes()),
49 TLVValue::Str32l(a) => self.write_raw_data((a.len() as u32).to_le_bytes()),
50 TLVValue::Str64l(a) => self.write_raw_data((a.len() as u64).to_le_bytes()),
51 TLVValue::Utf8l(a) => self.write_raw_data((a.len() as u8).to_le_bytes()),
52 TLVValue::Utf16l(a) => self.write_raw_data((a.len() as u16).to_le_bytes()),
53 TLVValue::Utf32l(a) => self.write_raw_data((a.len() as u32).to_le_bytes()),
54 TLVValue::Utf64l(a) => self.write_raw_data((a.len() as u64).to_le_bytes()),
55 _ => Ok(()),
56 }?;
57
58 match value {
59 TLVValue::S8(a) => self.write_raw_data(a.to_le_bytes()),
60 TLVValue::S16(a) => self.write_raw_data(a.to_le_bytes()),
61 TLVValue::S32(a) => self.write_raw_data(a.to_le_bytes()),
62 TLVValue::S64(a) => self.write_raw_data(a.to_le_bytes()),
63 TLVValue::U8(a) => self.write_raw_data(a.to_le_bytes()),
64 TLVValue::U16(a) => self.write_raw_data(a.to_le_bytes()),
65 TLVValue::U32(a) => self.write_raw_data(a.to_le_bytes()),
66 TLVValue::U64(a) => self.write_raw_data(a.to_le_bytes()),
67 TLVValue::False => Ok(()),
68 TLVValue::True => Ok(()),
69 TLVValue::F32(a) => self.write_raw_data(a.to_le_bytes()),
70 TLVValue::F64(a) => self.write_raw_data(a.to_le_bytes()),
71 TLVValue::Utf8l(a)
72 | TLVValue::Utf16l(a)
73 | TLVValue::Utf32l(a)
74 | TLVValue::Utf64l(a) => self.write_raw_data(a.as_bytes().iter().copied()),
75 TLVValue::Str8l(a)
76 | TLVValue::Str16l(a)
77 | TLVValue::Str32l(a)
78 | TLVValue::Str64l(a) => self.write_raw_data(a.iter().copied()),
79 TLVValue::Null
80 | TLVValue::Struct
81 | TLVValue::Array
82 | TLVValue::List
83 | TLVValue::EndCnt => Ok(()),
84 }
85 }
86
87 fn i8(&mut self, tag: &TLVTag, data: i8) -> Result<(), Error> {
89 self.raw_value(tag, TLVValueType::S8, &data.to_le_bytes())
90 }
91
92 fn u8(&mut self, tag: &TLVTag, data: u8) -> Result<(), Error> {
94 self.raw_value(tag, TLVValueType::U8, &data.to_le_bytes())
95 }
96
97 fn i16(&mut self, tag: &TLVTag, data: i16) -> Result<(), Error> {
99 if data >= i8::MIN as i16 && data <= i8::MAX as i16 {
100 self.i8(tag, data as i8)
101 } else {
102 self.raw_value(tag, TLVValueType::S16, &data.to_le_bytes())
103 }
104 }
105
106 fn u16(&mut self, tag: &TLVTag, data: u16) -> Result<(), Error> {
108 if data <= u8::MAX as u16 {
109 self.u8(tag, data as u8)
110 } else {
111 self.raw_value(tag, TLVValueType::U16, &data.to_le_bytes())
112 }
113 }
114
115 fn i32(&mut self, tag: &TLVTag, data: i32) -> Result<(), Error> {
117 if data >= i16::MIN as i32 && data <= i16::MAX as i32 {
118 self.i16(tag, data as i16)
119 } else {
120 self.raw_value(tag, TLVValueType::S32, &data.to_le_bytes())
121 }
122 }
123
124 fn u32(&mut self, tag: &TLVTag, data: u32) -> Result<(), Error> {
126 if data <= u16::MAX as u32 {
127 self.u16(tag, data as u16)
128 } else {
129 self.raw_value(tag, TLVValueType::U32, &data.to_le_bytes())
130 }
131 }
132
133 fn i64(&mut self, tag: &TLVTag, data: i64) -> Result<(), Error> {
135 if data >= i32::MIN as i64 && data <= i32::MAX as i64 {
136 self.i32(tag, data as i32)
137 } else {
138 self.raw_value(tag, TLVValueType::S64, &data.to_le_bytes())
139 }
140 }
141
142 fn u64(&mut self, tag: &TLVTag, data: u64) -> Result<(), Error> {
144 if data <= u32::MAX as u64 {
145 self.u32(tag, data as u32)
146 } else {
147 self.raw_value(tag, TLVValueType::U64, &data.to_le_bytes())
148 }
149 }
150
151 fn f32(&mut self, tag: &TLVTag, data: f32) -> Result<(), Error> {
153 self.raw_value(tag, TLVValueType::F32, &data.to_le_bytes())
154 }
155
156 fn f64(&mut self, tag: &TLVTag, data: f64) -> Result<(), Error> {
158 self.raw_value(tag, TLVValueType::F64, &data.to_le_bytes())
159 }
160
161 fn str(&mut self, tag: &TLVTag, data: &[u8]) -> Result<(), Error> {
166 self.stri(tag, data.len(), data.iter().copied())
167 }
168
169 fn str_cb(
182 &mut self,
183 _tag: &TLVTag,
184 _cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
185 ) -> Result<(), Error> {
186 unimplemented!("str_cb not implemented for this TLVWrite instance");
187 }
188
189 fn stri<I>(&mut self, tag: &TLVTag, len: usize, data: I) -> Result<(), Error>
198 where
199 I: IntoIterator<Item = u8>,
200 {
201 if len <= u8::MAX as usize {
202 self.raw_value(tag, TLVValueType::Str8l, &(len as u8).to_le_bytes())?;
203 } else if len <= u16::MAX as usize {
204 self.raw_value(tag, TLVValueType::Str16l, &(len as u16).to_le_bytes())?;
205 } else if len <= u32::MAX as usize {
206 self.raw_value(tag, TLVValueType::Str32l, &(len as u32).to_le_bytes())?;
207 } else {
208 self.raw_value(tag, TLVValueType::Str64l, &(len as u64).to_le_bytes())?;
209 }
210
211 self.write_raw_data(data)
212 }
213
214 fn utf8(&mut self, tag: &TLVTag, data: &str) -> Result<(), Error> {
219 self.utf8i(tag, data.len(), data.as_bytes().iter().copied())
220 }
221
222 fn utf8i<I>(&mut self, tag: &TLVTag, len: usize, data: I) -> Result<(), Error>
233 where
234 I: IntoIterator<Item = u8>,
235 {
236 if len <= u8::MAX as usize {
237 self.raw_value(tag, TLVValueType::Utf8l, &(len as u8).to_le_bytes())?;
238 } else if len <= u16::MAX as usize {
239 self.raw_value(tag, TLVValueType::Utf16l, &(len as u16).to_le_bytes())?;
240 } else if len <= u32::MAX as usize {
241 self.raw_value(tag, TLVValueType::Utf32l, &(len as u32).to_le_bytes())?;
242 } else {
243 self.raw_value(tag, TLVValueType::Utf64l, &(len as u64).to_le_bytes())?;
244 }
245
246 self.write_raw_data(data)
247 }
248
249 fn utf8_cb(
262 &mut self,
263 _tag: &TLVTag,
264 _cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
265 ) -> Result<(), Error> {
266 unimplemented!("utf8_cb not implemented for this TLVWrite instance");
267 }
268
269 fn start_struct(&mut self, tag: &TLVTag) -> Result<(), Error> {
274 self.raw_value(tag, TLVValueType::Struct, &[])
275 }
276
277 fn start_array(&mut self, tag: &TLVTag) -> Result<(), Error> {
282 self.raw_value(tag, TLVValueType::Array, &[])
283 }
284
285 fn start_list(&mut self, tag: &TLVTag) -> Result<(), Error> {
290 self.raw_value(tag, TLVValueType::List, &[])
291 }
292
293 fn start_container(&mut self, tag: &TLVTag, container_type: TLVValueType) -> Result<(), Error> {
298 if !container_type.is_container() {
299 Err(ErrorCode::TLVTypeMismatch)?;
300 }
301
302 self.raw_value(tag, container_type, &[])
303 }
304
305 fn end_container(&mut self) -> Result<(), Error> {
310 self.write(TLVControl::new(TLVTagType::Anonymous, TLVValueType::EndCnt).as_raw())
311 }
312
313 fn null(&mut self, tag: &TLVTag) -> Result<(), Error> {
315 self.raw_value(tag, TLVValueType::Null, &[])
316 }
317
318 fn bool(&mut self, tag: &TLVTag, val: bool) -> Result<(), Error> {
320 self.raw_value(
321 tag,
322 if val {
323 TLVValueType::True
324 } else {
325 TLVValueType::False
326 },
327 &[],
328 )
329 }
330
331 fn raw_value(
333 &mut self,
334 tag: &TLVTag,
335 value_type: TLVValueType,
336 value_payload: &[u8],
337 ) -> Result<(), Error> {
338 self.write(TLVControl::new(tag.tag_type(), value_type).as_raw())?;
339
340 match tag {
341 TLVTag::Anonymous => Ok(()),
342 TLVTag::Context(v) => self.write_raw_data(v.to_le_bytes()),
343 TLVTag::CommonPrf16(v) | TLVTag::ImplPrf16(v) => self.write_raw_data(v.to_le_bytes()),
344 TLVTag::CommonPrf32(v) | TLVTag::ImplPrf32(v) => self.write_raw_data(v.to_le_bytes()),
345 TLVTag::FullQual48 {
346 vendor_id,
347 profile,
348 tag,
349 } => {
350 self.write_raw_data(vendor_id.to_le_bytes())?;
351 self.write_raw_data(profile.to_le_bytes())?;
352 self.write_raw_data(tag.to_le_bytes())
353 }
354 TLVTag::FullQual64 {
355 vendor_id,
356 profile,
357 tag,
358 } => {
359 self.write_raw_data(vendor_id.to_le_bytes())?;
360 self.write_raw_data(profile.to_le_bytes())?;
361 self.write_raw_data(tag.to_le_bytes())
362 }
363 }?;
364
365 self.write_raw_data(value_payload.iter().copied())
366 }
367
368 fn write_raw_data<I>(&mut self, bytes: I) -> Result<(), Error>
370 where
371 I: IntoIterator<Item = u8>,
372 {
373 for byte in bytes {
374 self.write(byte)?;
375 }
376
377 Ok(())
378 }
379
380 fn write(&mut self, byte: u8) -> Result<(), Error>;
382
383 fn get_tail(&self) -> Self::Position {
387 unimplemented!("get_tail not implemented for this TLVWrite instance");
388 }
389
390 fn rewind_to(&mut self, _pos: Self::Position) {
394 unimplemented!("rewind_to not implemented for this TLVWrite instance");
395 }
396
397 fn available_space(&mut self) -> &mut [u8] {
403 unimplemented!("available_space not implemented for this TLVWrite instance");
404 }
405}
406
407impl<T> TLVWrite for &mut T
408where
409 T: TLVWrite,
410{
411 type Position = T::Position;
412
413 fn write(&mut self, byte: u8) -> Result<(), Error> {
414 (**self).write(byte)
415 }
416
417 fn get_tail(&self) -> Self::Position {
418 (**self).get_tail()
419 }
420
421 fn rewind_to(&mut self, pos: Self::Position) {
422 (**self).rewind_to(pos)
423 }
424
425 fn available_space(&mut self) -> &mut [u8] {
426 (**self).available_space()
427 }
428
429 fn str_cb(
430 &mut self,
431 tag: &TLVTag,
432 cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
433 ) -> Result<(), Error> {
434 (**self).str_cb(tag, cb)
435 }
436
437 fn utf8_cb(
438 &mut self,
439 tag: &TLVTag,
440 cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
441 ) -> Result<(), Error> {
442 (**self).utf8_cb(tag, cb)
443 }
444}
445
446impl TLVWrite for WriteBuf<'_> {
447 type Position = usize;
448
449 fn write(&mut self, byte: u8) -> Result<(), Error> {
450 WriteBuf::append(self, &[byte])
451 }
452
453 fn get_tail(&self) -> Self::Position {
454 WriteBuf::get_tail(self)
455 }
456
457 fn rewind_to(&mut self, pos: Self::Position) {
458 WriteBuf::rewind_tail_to(self, pos)
459 }
460
461 fn available_space(&mut self) -> &mut [u8] {
462 WriteBuf::empty_as_mut_slice(self)
463 }
464
465 fn str_cb(
466 &mut self,
467 tag: &TLVTag,
468 cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
469 ) -> Result<(), Error> {
470 WriteBuf::str_cb(self, tag, cb)
471 }
472
473 fn utf8_cb(
474 &mut self,
475 tag: &TLVTag,
476 cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
477 ) -> Result<(), Error> {
478 WriteBuf::utf8_cb(self, tag, cb)
479 }
480}
481
482impl WriteBuf<'_> {
483 pub fn str_cb(
496 &mut self,
497 tag: &TLVTag,
498 cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
499 ) -> Result<(), Error> {
500 let control_offset = self.get_tail();
501 self.raw_value(tag, TLVValueType::Str16l, &0_u16.to_le_bytes())?;
502
503 let value_offset = self.get_tail();
504
505 let len = self.append_with_buf(cb)?;
506
507 Self::finalize_len_header(
508 self,
509 control_offset,
510 value_offset,
511 len,
512 tag.tag_type(),
513 TLVValueType::Str8l,
514 );
515
516 Ok(())
517 }
518
519 pub fn utf8_cb(
531 &mut self,
532 tag: &TLVTag,
533 cb: impl FnOnce(&mut [u8]) -> Result<usize, Error>,
534 ) -> Result<(), Error> {
535 let control_offset = self.get_tail();
536 self.raw_value(tag, TLVValueType::Utf16l, &0_u16.to_le_bytes())?;
537
538 let value_offset = self.get_tail();
539
540 let len = self.append_with_buf(cb)?;
541
542 Self::finalize_len_header(
543 self,
544 control_offset,
545 value_offset,
546 len,
547 tag.tag_type(),
548 TLVValueType::Utf8l,
549 );
550
551 Ok(())
552 }
553
554 fn finalize_len_header(
567 this: &mut WriteBuf<'_>,
568 control_offset: usize,
569 value_offset: usize,
570 len: usize,
571 tag_type: TLVTagType,
572 short_value_type: TLVValueType,
573 ) {
574 if len <= u8::MAX as usize {
575 this.buf[control_offset] = TLVControl::new(tag_type, short_value_type).as_raw();
577 this.buf[value_offset - 2] = len as u8;
578 this.buf
579 .copy_within(value_offset..value_offset + len, value_offset - 1);
580 this.rewind_tail_to(this.get_tail() - 1);
581 } else if len <= u16::MAX as usize {
582 this.buf[value_offset - 2..value_offset].copy_from_slice(&(len as u16).to_le_bytes());
584 } else {
585 panic!("Callback wrote more data than the reserved header can encode");
587 }
588 }
589}
590
591#[cfg(test)]
592mod tests {
593 use core::f32;
594
595 use super::{TLVTag, TLVWrite};
596 use crate::{tlv::TLVValue, utils::storage::WriteBuf};
597
598 #[test]
599 fn test_write_success() {
600 let mut buf = [0; 20];
601 let mut tw = WriteBuf::new(&mut buf);
602
603 tw.start_struct(&TLVTag::Anonymous).unwrap();
604 tw.u8(&TLVTag::Anonymous, 12).unwrap();
605 tw.u8(&TLVTag::Context(1), 13).unwrap();
606 tw.u16(&TLVTag::Anonymous, 0x1212).unwrap();
607 tw.u16(&TLVTag::Context(2), 0x1313).unwrap();
608 tw.start_array(&TLVTag::Context(3)).unwrap();
609 tw.bool(&TLVTag::Anonymous, true).unwrap();
610 tw.end_container().unwrap();
611 tw.end_container().unwrap();
612 assert_eq!(
613 buf,
614 [21, 4, 12, 36, 1, 13, 5, 0x12, 0x012, 37, 2, 0x13, 0x13, 54, 3, 9, 24, 24, 0, 0]
615 );
616 }
617
618 #[test]
619 fn test_write_overflow() {
620 let mut buf = [0; 6];
621 let mut tw = WriteBuf::new(&mut buf);
622
623 tw.u8(&TLVTag::Anonymous, 12).unwrap();
624 tw.u8(&TLVTag::Context(1), 13).unwrap();
625 if tw.u16(&TLVTag::Anonymous, 12).is_ok() {
626 panic!("This should have returned error")
627 }
628 if tw.u16(&TLVTag::Context(2), 13).is_ok() {
629 panic!("This should have returned error")
630 }
631 assert_eq!(buf, [4, 12, 36, 1, 13, 4]);
632 }
633
634 #[test]
635 fn test_put_str8() {
636 let mut buf = [0; 20];
637 let mut tw = WriteBuf::new(&mut buf);
638
639 tw.u8(&TLVTag::Context(1), 13).unwrap();
640 tw.str(&TLVTag::Anonymous, &[10, 11, 12, 13, 14]).unwrap();
641 tw.u16(&TLVTag::Context(2), 0x1313).unwrap();
642 tw.str(&TLVTag::Context(3), &[20, 21, 22]).unwrap();
643 assert_eq!(
644 buf,
645 [36, 1, 13, 16, 5, 10, 11, 12, 13, 14, 37, 2, 0x13, 0x13, 48, 3, 3, 20, 21, 22]
646 );
647 }
648
649 #[test]
650 fn test_matter_spec_examples() {
651 let mut buf = [0; 200];
652 let mut tw = WriteBuf::new(&mut buf);
653
654 tw.bool(&TLVTag::Anonymous, false).unwrap();
657 assert_eq!(&[0x08], tw.as_slice());
658
659 tw.reset();
662 tw.bool(&TLVTag::Anonymous, true).unwrap();
663 assert_eq!(&[0x09], tw.as_slice());
664
665 tw.reset();
668 tw.i8(&TLVTag::Anonymous, 42).unwrap();
669 assert_eq!(&[0x00, 0x2a], tw.as_slice());
670
671 tw.reset();
674 tw.i32(&TLVTag::Anonymous, -17).unwrap();
675 assert_eq!(&[0x00, 0xef], tw.as_slice());
676
677 tw.reset();
680 tw.u8(&TLVTag::Anonymous, 42).unwrap();
681 assert_eq!(&[0x04, 0x2a], tw.as_slice());
682
683 tw.reset();
686 tw.i16(&TLVTag::Anonymous, 422).unwrap();
687 assert_eq!(&[0x01, 0xa6, 0x01], tw.as_slice());
688
689 tw.reset();
692 tw.i32(&TLVTag::Anonymous, -170000).unwrap();
693 assert_eq!(&[0x02, 0xf0, 0x67, 0xfd, 0xff], tw.as_slice());
694
695 tw.reset();
698 tw.i64(&TLVTag::Anonymous, 40000000000).unwrap();
699 assert_eq!(
700 &[0x03, 0x00, 0x90, 0x2f, 0x50, 0x09, 0x00, 0x00, 0x00],
701 tw.as_slice()
702 );
703
704 tw.reset();
707 tw.utf8(&TLVTag::Anonymous, "Hello!").unwrap();
708 assert_eq!(
709 &[0x0c, 0x06, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21],
710 tw.as_slice()
711 );
712
713 tw.reset();
716 tw.utf8i(
717 &TLVTag::Anonymous,
718 "Tschüs".len(),
719 "Tschüs".as_bytes().iter().copied(),
720 )
721 .unwrap();
722 assert_eq!(
723 &[0x0c, 0x07, 0x54, 0x73, 0x63, 0x68, 0xc3, 0xbc, 0x73],
724 tw.as_slice()
725 );
726
727 tw.reset();
730 tw.str(&TLVTag::Anonymous, &[0x00, 0x01, 0x02, 0x03, 0x04])
731 .unwrap();
732 assert_eq!(&[0x10, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04], tw.as_slice());
733
734 tw.reset();
737 tw.tlv(&TLVTag::Anonymous, &TLVValue::Null).unwrap();
738 assert_eq!(&[0x14], tw.as_slice());
739
740 tw.reset();
743 tw.tlv(&TLVTag::Anonymous, &TLVValue::F32(0.0)).unwrap();
744 assert_eq!(&[0x0a, 0x00, 0x00, 0x00, 0x00], tw.as_slice());
745
746 tw.reset();
749 tw.f32(&TLVTag::Anonymous, 1.0 / 3.0).unwrap();
750 assert_eq!(&[0x0a, 0xab, 0xaa, 0xaa, 0x3e], tw.as_slice());
751
752 tw.reset();
755 tw.f32(&TLVTag::Anonymous, 17.9).unwrap();
756 assert_eq!(&[0x0a, 0x33, 0x33, 0x8f, 0x41], tw.as_slice());
757
758 tw.reset();
761 tw.f32(&TLVTag::Anonymous, f32::INFINITY).unwrap();
762 assert_eq!(&[0x0a, 0x00, 0x00, 0x80, 0x7f], tw.as_slice());
763
764 tw.reset();
767 tw.f32(&TLVTag::Anonymous, f32::NEG_INFINITY).unwrap();
768 assert_eq!(&[0x0a, 0x00, 0x00, 0x80, 0xff], tw.as_slice());
769
770 tw.reset();
773 tw.f64(&TLVTag::Anonymous, 0.0).unwrap();
774 assert_eq!(
775 &[0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
776 tw.as_slice()
777 );
778
779 tw.reset();
782 tw.f64(&TLVTag::Anonymous, 1.0 / 3.0).unwrap();
783 assert_eq!(
784 &[0x0b, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x3f],
785 tw.as_slice()
786 );
787
788 tw.reset();
791 tw.f64(&TLVTag::Anonymous, 17.9).unwrap();
792 assert_eq!(
793 &[0x0b, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x31, 0x40],
794 tw.as_slice()
795 );
796
797 tw.reset();
800 tw.f64(&TLVTag::Anonymous, f64::INFINITY).unwrap();
801 assert_eq!(
802 &[0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f],
803 tw.as_slice()
804 );
805
806 tw.reset();
809 tw.f64(&TLVTag::Anonymous, f64::NEG_INFINITY).unwrap();
810 assert_eq!(
811 &[0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff],
812 tw.as_slice()
813 );
814
815 tw.reset();
818 tw.start_struct(&TLVTag::Anonymous).unwrap();
819 tw.end_container().unwrap();
820 assert_eq!(&[0x15, 0x18], tw.as_slice());
821
822 tw.reset();
825 tw.start_array(&TLVTag::Anonymous).unwrap();
826 tw.end_container().unwrap();
827 assert_eq!(&[0x16, 0x18], tw.as_slice());
828
829 tw.reset();
832 tw.start_list(&TLVTag::Anonymous).unwrap();
833 tw.end_container().unwrap();
834 assert_eq!(&[0x17, 0x18], tw.as_slice());
835
836 tw.reset();
839 tw.start_struct(&TLVTag::Anonymous).unwrap();
840 tw.i8(&TLVTag::Context(0), 42).unwrap();
841 tw.i32(&TLVTag::Context(1), -17).unwrap();
842 tw.end_container().unwrap();
843 assert_eq!(
844 &[0x15, 0x20, 0x00, 0x2a, 0x20, 0x01, 0xef, 0x18],
845 tw.as_slice()
846 );
847
848 tw.reset();
851 tw.start_array(&TLVTag::Anonymous).unwrap();
852 for i in 0..5 {
853 tw.i8(&TLVTag::Anonymous, i as i8).unwrap();
854 }
855 tw.end_container().unwrap();
856 assert_eq!(
857 &[0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x18],
858 tw.as_slice()
859 );
860
861 tw.reset();
864 tw.start_list(&TLVTag::Anonymous).unwrap();
865 tw.i64(&TLVTag::Anonymous, 1).unwrap();
866 tw.i16(&TLVTag::Context(0), 42).unwrap();
867 tw.i8(&TLVTag::Anonymous, 2).unwrap();
868 tw.i8(&TLVTag::Anonymous, 3).unwrap();
869 tw.i32(&TLVTag::Context(0), -17).unwrap();
870 tw.end_container().unwrap();
871 assert_eq!(
872 &[0x17, 0x00, 0x01, 0x20, 0x00, 0x2a, 0x00, 0x02, 0x00, 0x03, 0x20, 0x00, 0xef, 0x18],
873 tw.as_slice()
874 );
875
876 tw.reset();
879 tw.start_array(&TLVTag::Anonymous).unwrap();
880 tw.i64(&TLVTag::Anonymous, 42).unwrap();
881 tw.i64(&TLVTag::Anonymous, -170000).unwrap();
882 tw.start_struct(&TLVTag::Anonymous).unwrap();
883 tw.end_container().unwrap();
884 tw.f32(&TLVTag::Anonymous, 17.9).unwrap();
885 tw.utf8(&TLVTag::Anonymous, "Hello!").unwrap();
886 tw.end_container().unwrap();
887 assert_eq!(
888 &[
889 0x16, 0x00, 0x2a, 0x02, 0xf0, 0x67, 0xfd, 0xff, 0x15, 0x18, 0x0a, 0x33, 0x33, 0x8f,
890 0x41, 0x0c, 0x06, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21, 0x18,
891 ],
892 tw.as_slice()
893 );
894
895 tw.reset();
898 tw.u64(&TLVTag::Anonymous, 42).unwrap();
899 assert_eq!(&[0x04, 0x2a], tw.as_slice());
900
901 tw.reset();
904 tw.u64(&TLVTag::Context(1), 42).unwrap();
905 assert_eq!(&[0x24, 0x01, 0x2a], tw.as_slice());
906
907 tw.reset();
910 tw.u64(&TLVTag::CommonPrf16(1), 42).unwrap();
911 assert_eq!(&[0x44, 0x01, 0x00, 0x2a], tw.as_slice());
912
913 tw.reset();
916 tw.u64(&TLVTag::CommonPrf32(100000), 42).unwrap();
917 assert_eq!(&[0x64, 0xa0, 0x86, 0x01, 0x00, 0x2a], tw.as_slice());
918
919 tw.reset();
923 tw.u64(
924 &TLVTag::FullQual48 {
925 vendor_id: 65521,
926 profile: 57069,
927 tag: 1,
928 },
929 42,
930 )
931 .unwrap();
932 assert_eq!(
933 &[0xc4, 0xf1, 0xff, 0xed, 0xde, 0x01, 0x00, 0x2a],
934 tw.as_slice()
935 );
936
937 tw.reset();
941 tw.u64(
942 &TLVTag::FullQual64 {
943 vendor_id: 65521,
944 profile: 57069,
945 tag: 2857762541,
946 },
947 42,
948 )
949 .unwrap();
950 assert_eq!(
951 &[0xe4, 0xf1, 0xff, 0xed, 0xde, 0xed, 0xfe, 0x55, 0xaa, 0x2a],
952 tw.as_slice()
953 );
954
955 tw.reset();
960 tw.start_struct(&TLVTag::FullQual48 {
961 vendor_id: 65521,
962 profile: 57069,
963 tag: 1,
964 })
965 .unwrap();
966 tw.u64(
967 &TLVTag::FullQual48 {
968 vendor_id: 65521,
969 profile: 57069,
970 tag: 43605,
971 },
972 42,
973 )
974 .unwrap();
975 tw.end_container().unwrap();
976 assert_eq!(
977 &[
978 0xd5, 0xf1, 0xff, 0xed, 0xde, 0x01, 0x00, 0xc4, 0xf1, 0xff, 0xed, 0xde, 0x55, 0xaa,
979 0x2a, 0x18,
980 ],
981 tw.as_slice()
982 );
983 }
984}