1use crate::{BufsMut, EncodeSize, Error, Read, Write};
4use bytes::{Buf, BufMut};
5use paste::paste;
6
7macro_rules! impl_codec_for_tuple {
10 ($($index:literal),*) => {
11 paste! {
12 impl<$( [<T $index>]: EncodeSize ),*> EncodeSize for ( $( [<T $index>], )* ) {
13 #[inline]
14 fn encode_size(&self) -> usize {
15 0 $( + self.$index.encode_size() )*
16 }
17
18 #[inline]
19 fn encode_inline_size(&self) -> usize {
20 0 $( + self.$index.encode_inline_size() )*
21 }
22 }
23
24 impl<$( [<T $index>]: Write ),*> Write for ( $( [<T $index>], )* ) {
25 #[inline]
26 fn write(&self, buf: &mut impl BufMut) {
27 $( self.$index.write(buf); )*
28 }
29
30 #[inline]
31 fn write_bufs(&self, buf: &mut impl BufsMut) {
32 $( self.$index.write_bufs(buf); )*
33 }
34 }
35
36 impl <$( [<T $index>]: Read ),*> Read for ( $( [<T $index>], )* ) {
37 type Cfg = ( $( [<T $index>]::Cfg, )* );
38 #[inline]
39 fn read_cfg(buf: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
40 Ok(( $( [<T $index>]::read_cfg(buf, &cfg.$index)?, )* ))
41 }
42 }
43 }
44 };
45}
46
47impl_codec_for_tuple!(0);
49impl_codec_for_tuple!(0, 1);
50impl_codec_for_tuple!(0, 1, 2);
51impl_codec_for_tuple!(0, 1, 2, 3);
52impl_codec_for_tuple!(0, 1, 2, 3, 4);
53impl_codec_for_tuple!(0, 1, 2, 3, 4, 5);
54impl_codec_for_tuple!(0, 1, 2, 3, 4, 5, 6);
55impl_codec_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7);
56impl_codec_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8);
57impl_codec_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
58impl_codec_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
59impl_codec_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
60
61#[cfg(test)]
62mod tests {
63 use crate::{DecodeExt, Encode};
64
65 #[test]
66 fn test_tuple() {
67 let tuple_values = [(1u16, None), (1u16, Some(2u32))];
68 for value in tuple_values {
69 let encoded = value.encode();
70 let decoded = <(u16, Option<u32>)>::decode(encoded).unwrap();
71 assert_eq!(value, decoded);
72 }
73 }
74
75 #[test]
76 fn test_conformity() {
77 let t1 = (true, 0x42u8);
78 assert_eq!(t1.encode(), &[0x01, 0x42][..]);
79
80 let t2 = (0xABCDu16, false, 0xDEADBEEFu32);
81 assert_eq!(t2.encode(), &[0xAB, 0xCD, 0x00, 0xDE, 0xAD, 0xBE, 0xEF][..]);
82
83 let t3 = ((0x01u8, 0x02u8), 0x03u8); assert_eq!(t3.encode(), &[0x01, 0x02, 0x03][..]);
85
86 let t_option_some = (Some(0x1234u16), 0xFFu8);
87 assert_eq!(t_option_some.encode(), &[0x01, 0x12, 0x34, 0xFF][..]);
91
92 let t_option_none = (0xFFu8, Option::<u16>::None);
93 assert_eq!(t_option_none.encode(), &[0xFF, 0x00][..]);
96 }
97
98 #[cfg(feature = "arbitrary")]
99 mod conformance {
100 use crate::conformance::CodecConformance;
101
102 commonware_conformance::conformance_tests! {
103 CodecConformance<(u32, u32)>,
104 CodecConformance<(u32, u32, u32)>,
105 CodecConformance<(u32, u32, u32, u32)>,
106 CodecConformance<(u32, u32, u32, u32, u32)>,
107 CodecConformance<(u32, u32, u32, u32, u32, u32)>,
108 }
109 }
110}