host-can 0.1.5

Host library for CAN adapters
Documentation
use crate::id::Id;
pub use embedded_can::Frame;

type CanPdu = [u8; 8];

/// A standard CAN 2.0 frame
/// (NOTE: this will change to an enum w/standard, fd, error, etc.)
#[derive(Copy, Clone, Debug)]
pub struct CanFrame {
    id: Id,
    dlc: u8,
    data: CanPdu,
}

impl PartialEq for CanFrame {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id
            && self.dlc == other.dlc
            && self.data[..self.dlc as usize]
                == other.data[..other.dlc as usize]
    }
}

impl Frame for CanFrame {
    fn new(id: impl Into<Id>, data: &[u8]) -> Option<Self> {
        let len = data.len();
        if len > std::mem::size_of::<CanPdu>() {
            return None;
        }
        let mut bytes = [0u8; 8];
        bytes[..len].copy_from_slice(data);
        Some(CanFrame {
            id: id.into(),
            dlc: len as u8,
            data: bytes,
        })
    }

    fn new_remote(_: impl Into<Id>, _: usize) -> Option<Self> {
        None
    }

    fn is_extended(&self) -> bool {
        match self.id {
            embedded_can::Id::Extended(_) => true,
            embedded_can::Id::Standard(_) => false,
        }
    }

    fn is_remote_frame(&self) -> bool {
        false
    }

    fn id(&self) -> embedded_can::Id {
        self.id
    }

    fn dlc(&self) -> usize {
        self.dlc as usize
    }

    fn data(&self) -> &[u8] {
        &self.data[..self.dlc as usize]
    }
}

// TODO: CanFdFrame

#[cfg(test)]
mod test {
    use crate::id;

    use super::CanFrame;
    use embedded_can::Frame;

    #[test]
    fn frame_eq() {
        let std_123_dlc_3a =
            CanFrame::new(id::new_standard(0x123).unwrap(), &[0, 10, 20])
                .unwrap();
        let std_123_dlc_3b =
            CanFrame::new(id::new_standard(0x123).unwrap(), &[0, 10, 20])
                .unwrap();
        let std_123_dlc_2 =
            CanFrame::new(id::new_standard(0x123).unwrap(), &[0, 10]).unwrap();
        let std_456_dlc_3 =
            CanFrame::new(id::new_standard(0x456).unwrap(), &[0, 10, 20])
                .unwrap();
        let ext_123_dlc_3a =
            CanFrame::new(id::new_extended(0x123).unwrap(), &[0, 10, 20])
                .unwrap();
        let ext_123_dlc_3b =
            CanFrame::new(id::new_extended(0x123).unwrap(), &[0, 10, 20])
                .unwrap();
        let ext_123_dlc_2 =
            CanFrame::new(id::new_extended(0x123).unwrap(), &[0, 10]).unwrap();
        let ext_456_dlc_3 =
            CanFrame::new(id::new_extended(0x123).unwrap(), &[0, 10, 20])
                .unwrap();

        // standard
        assert_eq!(std_123_dlc_3a, std_123_dlc_3b);
        assert_ne!(std_123_dlc_3a, std_123_dlc_2);
        assert_ne!(std_123_dlc_2, std_456_dlc_3);

        // standard != extended, even if IDs match
        assert_ne!(std_123_dlc_3a, ext_123_dlc_3a);

        // extended
        assert_eq!(ext_123_dlc_3a, ext_123_dlc_3b);
        assert_ne!(ext_123_dlc_3a, ext_123_dlc_2);
        assert_ne!(ext_123_dlc_2, ext_456_dlc_3);
    }
}