awdl_frame_parser/tlvs/sync_elect/
sync_tree_tlv.rs1use core::fmt::Display;
2
3use mac_parser::MACAddress;
4use scroll::{
5 ctx::{MeasureWith, TryFromCtx, TryIntoCtx},
6 Pread, Pwrite,
7};
8
9use crate::tlvs::{AWDLTLVType, AwdlTlv};
10
11#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
12pub struct ReadMACIterator<'a> {
13 bytes: &'a [u8],
14 offset: usize,
15}
16impl<'a> ReadMACIterator<'a> {
17 pub const fn new(bytes: &'a [u8]) -> Self {
18 Self { bytes, offset: 0 }
19 }
20}
21impl Iterator for ReadMACIterator<'_> {
22 type Item = MACAddress;
23 fn next(&mut self) -> Option<Self::Item> {
24 self.bytes.gread(&mut self.offset).ok()
25 }
26}
27impl ExactSizeIterator for ReadMACIterator<'_> {
28 fn len(&self) -> usize {
29 self.bytes.len() / 6
30 }
31}
32impl Display for ReadMACIterator<'_> {
33 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
34 f.debug_list().entries(*self).finish()
35 }
36}
37
38#[derive(Clone, Copy, Debug, Default, Hash)]
39pub struct SyncTreeTLV<I> {
43 pub tree: I,
45}
46impl<I> AwdlTlv for SyncTreeTLV<I> {
47 const TLV_TYPE: AWDLTLVType = AWDLTLVType::SynchronizationTree;
48}
49impl<LhsIterator, RhsIterator> PartialEq<SyncTreeTLV<RhsIterator>> for SyncTreeTLV<LhsIterator>
50where
51 LhsIterator: IntoIterator<Item = MACAddress> + Clone,
52 RhsIterator: IntoIterator<Item = MACAddress> + Clone,
53{
54 fn eq(&self, other: &SyncTreeTLV<RhsIterator>) -> bool {
55 self.tree.clone().into_iter().eq(other.tree.clone())
56 }
57}
58impl<I: IntoIterator<Item = MACAddress> + Clone> Eq for SyncTreeTLV<I> {}
59impl<I> MeasureWith<()> for SyncTreeTLV<I>
60where
61 I: ExactSizeIterator,
62{
63 fn measure_with(&self, _ctx: &()) -> usize {
64 self.tree.len() * 6
65 }
66}
67impl<'a> TryFromCtx<'a> for SyncTreeTLV<ReadMACIterator<'a>> {
68 type Error = scroll::Error;
69 fn try_from_ctx(from: &'a [u8], _ctx: ()) -> Result<(Self, usize), Self::Error> {
70 Ok((
71 Self {
72 tree: ReadMACIterator::new(from),
73 },
74 from.len() / 6,
75 ))
76 }
77}
78impl<I> TryIntoCtx for SyncTreeTLV<I>
79where
80 I: IntoIterator<Item = MACAddress>,
81{
82 type Error = scroll::Error;
83 fn try_into_ctx(self, buf: &mut [u8], _ctx: ()) -> Result<usize, Self::Error> {
84 let mut offset = 0;
85 for address in self.tree {
86 buf.gwrite(address.as_slice(), &mut offset)?;
87 }
88 Ok(offset)
89 }
90}
91
92pub type DefaultSyncTreeTLV<'a> = SyncTreeTLV<ReadMACIterator<'a>>;
94
95#[cfg(test)]
96#[test]
97fn test_sync_tree_tlv() {
98 use alloc::vec;
99 use mac_parser::ZERO;
100 use scroll::Pread;
101
102 let bytes = &include_bytes!("../../../test_bins/sync_tree_tlv.bin")[3..];
103
104 let sync_tree_tlv = bytes.pread::<SyncTreeTLV<_>>(0).unwrap();
105 assert_eq!(
106 sync_tree_tlv,
107 SyncTreeTLV {
108 tree: [MACAddress::new([0xbe, 0x70, 0xf3, 0x17, 0x21, 0xf2]), ZERO]
109 }
110 );
111
112 let mut buf = vec![0x00; sync_tree_tlv.measure_with(&())];
113 buf.pwrite(sync_tree_tlv, 0).unwrap();
114 assert_eq!(buf, bytes);
115}