veecle_os_data_support_can/
frame.rs1use tinyvec::ArrayVec;
2
3use crate::id::{Id, PackedId};
4
5#[derive(Clone, Copy, serde::Serialize, serde::Deserialize)]
7pub struct Frame {
8 id: PackedId,
10 data: ArrayVec<[u8; 8]>,
11}
12
13mod sealed {
14 pub trait Sealed {}
18 impl Sealed for [u8; 0] {}
19 impl Sealed for [u8; 1] {}
20 impl Sealed for [u8; 2] {}
21 impl Sealed for [u8; 3] {}
22 impl Sealed for [u8; 4] {}
23 impl Sealed for [u8; 5] {}
24 impl Sealed for [u8; 6] {}
25 impl Sealed for [u8; 7] {}
26 impl Sealed for [u8; 8] {}
27}
28
29pub trait FrameSize: sealed::Sealed {}
31impl FrameSize for [u8; 0] {}
32impl FrameSize for [u8; 1] {}
33impl FrameSize for [u8; 2] {}
34impl FrameSize for [u8; 3] {}
35impl FrameSize for [u8; 4] {}
36impl FrameSize for [u8; 5] {}
37impl FrameSize for [u8; 6] {}
38impl FrameSize for [u8; 7] {}
39impl FrameSize for [u8; 8] {}
40
41impl Frame {
42 pub fn new<const N: usize>(id: impl Into<Id>, data: [u8; N]) -> Self
46 where
47 [u8; N]: FrameSize,
48 {
49 Self::new_checked(id, &data).expect("the const generic guarantees it's ok")
50 }
51
52 pub fn new_checked(id: impl Into<Id>, data: &[u8]) -> Option<Self> {
56 let id = PackedId::from(id.into());
57 let data = ArrayVec::try_from(data).ok()?;
58 Some(Self { id, data })
59 }
60
61 pub fn id(&self) -> Id {
63 self.id.into()
64 }
65
66 pub fn data(&self) -> &[u8] {
68 &self.data
69 }
70}
71
72impl Default for Frame {
73 fn default() -> Self {
74 Self::new(crate::StandardId::new(0).unwrap(), [])
75 }
76}
77
78impl veecle_os_runtime::Storable for Frame {
79 type DataType = Self;
80}
81
82impl core::fmt::Debug for Frame {
83 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
84 write!(f, "Frame {{ id: {:?}, data: '", self.id())?;
85 for byte in self.data() {
86 write!(f, "{byte:02x}")?;
87 }
88 f.write_str("' }")?;
89
90 Ok(())
91 }
92}
93
94#[cfg(test)]
95#[cfg_attr(coverage_nightly, coverage(off))]
96mod tests {
97 use crate::Frame;
98
99 #[test]
100 fn test_deserialize_frame_standard() {
101 let json = r#"{"id":{"Standard":291},"data":[1,2,3,4]}"#;
102 let frame: Frame = serde_json::from_str(json).unwrap();
103 assert_eq!(frame.id(), crate::StandardId::new(0x123).unwrap().into());
104 assert_eq!(frame.data(), &[1, 2, 3, 4]);
105 assert_eq!(json, serde_json::to_string(&frame).unwrap());
106 }
107
108 #[test]
109 fn test_deserialize_frame_extended() {
110 let json = r#"{"id":{"Extended":74565},"data":[1,2,3,4]}"#;
111 let frame: Frame = serde_json::from_str(json).unwrap();
112 assert_eq!(frame.id(), crate::ExtendedId::new(74565).unwrap().into());
113 assert_eq!(frame.data(), &[1, 2, 3, 4]);
114 assert_eq!(json, serde_json::to_string(&frame).unwrap());
115 }
116
117 #[test]
119 fn test_debug() {
120 fn to_debug(value: impl core::fmt::Debug) -> std::string::String {
121 std::format!("{value:?}")
122 }
123
124 assert_eq!(
125 to_debug(Frame::new(crate::StandardId::new(0).unwrap(), [])),
126 "Frame { id: Standard(0x0), data: '' }"
127 );
128
129 assert_eq!(
130 to_debug(Frame::new(
131 crate::ExtendedId::new(0x153EAB12).unwrap(),
132 [0x04, 0xA2, 0xC2, 0xED, 0xCA, 0xE3, 0x88, 0x74]
133 )),
134 "Frame { id: Extended(0x153eab12), data: '04a2c2edcae38874' }"
135 );
136
137 assert_eq!(
138 to_debug(Frame::new(
139 crate::ExtendedId::new(0x1B56C72D).unwrap(),
140 [0x40, 0x71, 0xEF, 0x61]
141 )),
142 "Frame { id: Extended(0x1b56c72d), data: '4071ef61' }"
143 );
144 }
145}