awdl_frame_parser/tlvs/sync_elect/
election_parameters_tlv.rs

1use mac_parser::MACAddress;
2use scroll::{
3    ctx::{MeasureWith, SizeWith, TryFromCtx, TryIntoCtx},
4    Endian, Pread, Pwrite,
5};
6
7use crate::tlvs::{AWDLTLVType, AwdlTlv};
8
9#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
10/// A TLV describing the election parameters of a peer.
11pub struct ElectionParametersTLV {
12    /// Unknown
13    pub flags: u8,
14
15    /// Unknown
16    pub id: u16,
17
18    /// Distance to the mesh master
19    pub distance_to_master: u8,
20
21    /// Address of the master
22    pub master_address: MACAddress,
23
24    /// Self metric of the master
25    pub master_metric: u32,
26
27    /// Own self metric
28    pub self_metric: u32,
29}
30impl ElectionParametersTLV {
31    pub const fn size_in_bytes() -> usize {
32        21
33    }
34}
35impl AwdlTlv for ElectionParametersTLV {
36    const TLV_TYPE: AWDLTLVType = AWDLTLVType::ElectionParameters;
37}
38impl SizeWith for ElectionParametersTLV {
39    fn size_with(_ctx: &()) -> usize {
40        Self::size_in_bytes()
41    }
42}
43impl MeasureWith<()> for ElectionParametersTLV {
44    fn measure_with(&self, _ctx: &()) -> usize {
45        Self::size_in_bytes()
46    }
47}
48impl<'a> TryFromCtx<'a> for ElectionParametersTLV {
49    type Error = scroll::Error;
50    fn try_from_ctx(from: &'a [u8], _ctx: ()) -> Result<(Self, usize), Self::Error> {
51        let mut offset = 0;
52
53        let flags = from.gread(&mut offset)?;
54        let id = from.gread_with(&mut offset, Endian::Little)?;
55        let distance_to_master = from.gread(&mut offset)?;
56        offset += 1;
57        let master_address = MACAddress::new(from.gread(&mut offset)?);
58        let master_metric = from.gread_with(&mut offset, Endian::Little)?;
59        let self_metric = from.gread_with(&mut offset, Endian::Little)?;
60
61        offset += 2;
62
63        Ok((
64            Self {
65                flags,
66                id,
67                distance_to_master,
68                master_address,
69                master_metric,
70                self_metric,
71            },
72            offset,
73        ))
74    }
75}
76impl TryIntoCtx for ElectionParametersTLV {
77    type Error = scroll::Error;
78    fn try_into_ctx(self, buf: &mut [u8], _ctx: ()) -> Result<usize, Self::Error> {
79        let mut offset = 0;
80        buf.gwrite(self.flags, &mut offset)?;
81        buf.gwrite_with(self.id, &mut offset, Endian::Little)?;
82        buf.gwrite(self.distance_to_master, &mut offset)?;
83        offset += 1;
84        buf.gwrite(self.master_address.as_slice(), &mut offset)?;
85        buf.gwrite_with(self.master_metric, &mut offset, Endian::Little)?;
86        buf.gwrite_with(self.self_metric, &mut offset, Endian::Little)?;
87
88        offset += 2;
89
90        Ok(offset)
91    }
92}
93
94#[cfg(test)]
95#[test]
96fn test_election_parameters_tlv() {
97    let bytes = &include_bytes!("../../../test_bins/election_parameters_tlv.bin")[3..];
98
99    let election_parameters_tlv = bytes.pread::<ElectionParametersTLV>(0).unwrap();
100
101    assert_eq!(
102        election_parameters_tlv,
103        ElectionParametersTLV {
104            flags: 0x00,
105            id: 0x00,
106            distance_to_master: 0x02,
107            master_address: [0x3a, 0xb4, 0x08, 0x6e, 0x66, 0x3d].into(),
108            master_metric: 541,
109            self_metric: 60
110        }
111    );
112    let mut buf = [0x00; ElectionParametersTLV::size_in_bytes()];
113    buf.pwrite(election_parameters_tlv, 0).unwrap();
114    assert_eq!(buf, bytes);
115}