emcyphal_data_types/
optimized.rs

1// This file is copied and modified from canadensis_data_types crate.
2
3use emcyphal_core::SubjectId;
4use emcyphal_encoding::{DeserializeError, ReadCursor, WriteCursor};
5use heapless::Vec;
6
7const SUBJECT_ID_SPARSE_LIST_DISCRIMINANT: u8 = 1;
8
9/// A fixed-capacity list of subject IDs that is compatible with
10/// `uavcan.node.port.SubjectIDList.1.0`
11#[derive(Debug, Clone, Default, PartialEq, Eq)]
12pub struct SubjectIdList<const N: usize>(pub Vec<SubjectId, N>);
13
14impl<const N: usize> SubjectIdList<N> {
15    // N must be less than 256 as defined in the DSDL
16    const _ASSERT_SIZE: usize = 256 - N - 1;
17
18    pub fn new() -> Self {
19        SubjectIdList(Vec::new())
20    }
21}
22
23impl<const N: usize> emcyphal_encoding::DataType for SubjectIdList<N> {
24    const EXTENT_BYTES: Option<u32> =
25        crate::uavcan::node::port::subject_id_list_1_0::SubjectIDList::EXTENT_BYTES;
26}
27impl<const N: usize> emcyphal_encoding::Message for SubjectIdList<N> {}
28impl<const N: usize> emcyphal_encoding::Serialize for SubjectIdList<N> {
29    fn size_bits(&self) -> usize {
30        // 8 bits of union discriminant, 8 bits of length, 16 bits for each ID
31        8 + 8 + self.0.len() * 16
32    }
33
34    fn serialize(&self, cursor: &mut WriteCursor<'_>) {
35        // Discriminant
36        cursor.write_aligned_u8(SUBJECT_ID_SPARSE_LIST_DISCRIMINANT);
37        // Length
38        cursor.write_aligned_u8(self.0.len() as u8);
39        for &value in &self.0 {
40            cursor.write_aligned_u16(value.into())
41        }
42    }
43}
44impl<const N: usize> emcyphal_encoding::Deserialize for SubjectIdList<N> {
45    fn deserialize(cursor: &mut ReadCursor<'_>) -> Result<Self, DeserializeError>
46    where
47        Self: Sized,
48    {
49        let discriminant = cursor.read_aligned_u8();
50        if discriminant != SUBJECT_ID_SPARSE_LIST_DISCRIMINANT {
51            // Not a sparse list
52            return Err(DeserializeError::UnionTag);
53        }
54        let length = cursor.read_aligned_u8();
55        if usize::from(length) > N {
56            return Err(DeserializeError::ArrayLength);
57        }
58        let mut ids = Vec::new();
59        for _ in 0..length {
60            // Push can't fail because of the above length check
61            let _ = ids.push(SubjectId::from_u16_truncating(cursor.read_aligned_u16()));
62        }
63        Ok(SubjectIdList(ids))
64    }
65}