awdl_frame_parser/tlvs/sync_elect/channel_sequence_tlv/
mod.rs

1pub mod channel;
2pub mod channel_sequence;
3
4use core::num::NonZeroU8;
5
6use channel::*;
7use channel_sequence::*;
8
9use scroll::{
10    ctx::{MeasureWith, TryFromCtx, TryIntoCtx},
11    Pread, Pwrite,
12};
13
14use crate::tlvs::{AWDLTLVType, AwdlTlv};
15
16#[derive(Clone, Debug, PartialEq, Eq)]
17pub struct ChannelSequenceTLV {
18    /// The amount of AWs spent on one channel.
19    pub step_count: NonZeroU8,
20
21    /// The channels.
22    pub channel_sequence: ChannelSequence,
23}
24impl AwdlTlv for ChannelSequenceTLV {
25    const TLV_TYPE: AWDLTLVType = AWDLTLVType::ChannelSequence;
26}
27impl Default for ChannelSequenceTLV {
28    fn default() -> Self {
29        ChannelSequenceTLV {
30            step_count: NonZeroU8::new(3).unwrap(),
31            channel_sequence: Default::default(),
32        }
33    }
34}
35impl MeasureWith<()> for ChannelSequenceTLV {
36    fn measure_with(&self, ctx: &()) -> usize {
37        9 + self.channel_sequence.measure_with(ctx)
38    }
39}
40impl<'a> TryFromCtx<'a> for ChannelSequenceTLV {
41    type Error = scroll::Error;
42    fn try_from_ctx(from: &'a [u8], _ctx: ()) -> Result<(Self, usize), Self::Error> {
43        let mut offset = 0;
44
45        let channel_count = from.gread::<u8>(&mut offset)? + 1;
46        if channel_count != 16 {
47            return Err(scroll::Error::BadInput {
48                size: offset,
49                msg: "Channel sequence length wasn't 16.",
50            });
51        }
52        let channel_encoding = ChannelEncoding::from_bits(from.gread(&mut offset)?);
53        offset += 1; // Skip duplicate count
54        let step_count = NonZeroU8::new(from.gread::<u8>(&mut offset)?.checked_add(1).ok_or(
55            scroll::Error::BadInput {
56                size: offset,
57                msg: "step_count caused overflow",
58            },
59        )?)
60        .unwrap();
61        offset += 2;
62        let channel_sequence = from.gread_with(&mut offset, channel_encoding)?;
63
64        Ok((
65            Self {
66                step_count,
67                channel_sequence,
68            },
69            offset,
70        ))
71    }
72}
73impl TryIntoCtx for ChannelSequenceTLV {
74    type Error = scroll::Error;
75    fn try_into_ctx(self, buf: &mut [u8], _ctx: ()) -> Result<usize, Self::Error> {
76        let mut offset = 0;
77
78        buf.gwrite(16u8 - 1, &mut offset)?;
79        buf.gwrite(
80            self.channel_sequence.channel_encoding().into_bits(),
81            &mut offset,
82        )?;
83        offset += 1;
84        buf.gwrite(self.step_count.get() - 1, &mut offset)?;
85        buf.gwrite(0xffffu16, &mut offset)?;
86        buf.gwrite(self.channel_sequence, &mut offset)?;
87        offset += 3;
88        Ok(offset)
89    }
90}
91#[cfg(test)]
92#[test]
93fn test_channel_sequence_tlv() {
94    use alloc::vec;
95
96    let bytes = &include_bytes!("../../../../test_bins/channel_sequence_tlv.bin")[3..];
97
98    let channel_sequence_tlv = bytes.pread::<ChannelSequenceTLV>(0).unwrap();
99    assert_eq!(
100        channel_sequence_tlv,
101        ChannelSequenceTLV {
102            step_count: NonZeroU8::new(4).unwrap(),
103            channel_sequence: ChannelSequence::fixed_channel_sequence(Channel::OpClass {
104                channel: 0x6,
105                opclass: 0x51
106            },),
107        }
108    );
109    let mut buf = vec![0x00; channel_sequence_tlv.measure_with(&())];
110    buf.as_mut_slice().pwrite(channel_sequence_tlv, 0).unwrap();
111    assert_eq!(buf, bytes);
112}