1use crate::{
2 constants::{
3 CLASSIC_CAN_MAX_DLC, CLASSIC_CAN_MIN_LEN, DATA_OFFSET, DLC_OFFSET, EFF_FLAG, ERR_FLAG,
4 EXT_ID_MASK, RTR_FLAG, STD_ID_MASK,
5 },
6 error::CanError,
7 isotp::address::IsoTpAddressingMode,
8};
9use ace_core::AddressMode;
10use ace_proto::can::frame::classic::{CanFrame, CanFrameMut};
11
12pub trait CanFrameExt {
30 fn as_bytes(&self) -> &[u8];
31
32 fn id_word(&self) -> Option<u32> {
35 let b = self.as_bytes();
36 if b.len() < DATA_OFFSET {
37 return None;
38 }
39 Some(u32::from_be_bytes([b[0], b[1], b[2], b[3]]))
40 }
41
42 fn dlc(&self) -> Option<u8> {
43 self.as_bytes().get(DLC_OFFSET).copied()
44 }
45
46 fn data_bytes(&self) -> Option<&[u8]> {
47 let b = self.as_bytes();
48 let dlc = self.dlc()? as usize;
49 let end = DATA_OFFSET + dlc;
50 if b.len() < end {
51 return None;
52 }
53 Some(&b[DATA_OFFSET..end])
54 }
55
56 fn is_extended_frame(&self) -> bool {
61 self.id_word().map_or(false, |w| w & EFF_FLAG != 0)
62 }
63
64 fn is_rtr(&self) -> bool {
65 self.id_word().map_or(false, |w| w & RTR_FLAG != 0)
66 }
67
68 fn is_error_frame(&self) -> bool {
69 self.id_word().map_or(false, |w| w & ERR_FLAG != 0)
70 }
71
72 fn can_id(&self) -> Option<Result<ace_proto::can::id::CanId, CanError>> {
77 let word = self.id_word()?;
78 if word & EFF_FLAG != 0 {
79 let raw = word & EXT_ID_MASK;
80 Some(
81 ace_proto::can::id::ExtendedCanId::new(raw)
82 .map(ace_proto::can::id::CanId::Extended)
83 .map_err(CanError::from),
84 )
85 } else {
86 let raw = (word & STD_ID_MASK) as u16;
87 Some(
88 ace_proto::can::id::StandardCanId::new(raw)
89 .map(ace_proto::can::id::CanId::Standard)
90 .map_err(CanError::from),
91 )
92 }
93 }
94
95 fn validate(&self) -> Result<(), CanError> {
100 let b = self.as_bytes();
101
102 if b.len() < CLASSIC_CAN_MIN_LEN {
103 return Err(CanError::BufferTooShort {
104 expected: CLASSIC_CAN_MIN_LEN,
105 actual: b.len(),
106 });
107 }
108
109 let word = u32::from_be_bytes([b[0], b[1], b[2], b[3]]);
110
111 if word & RTR_FLAG != 0 && word & EFF_FLAG == 0 {
113 return Err(CanError::InvalidFlags);
114 }
115
116 let dlc = b[DLC_OFFSET];
117 if dlc > CLASSIC_CAN_MAX_DLC {
118 return Err(CanError::InvalidDlc(dlc));
119 }
120
121 let expected_len = DATA_OFFSET + dlc as usize;
122 if b.len() < expected_len {
123 return Err(CanError::BufferTooShort {
124 expected: expected_len,
125 actual: b.len(),
126 });
127 }
128
129 Ok(())
130 }
131
132 fn is_valid(&self) -> bool {
133 self.validate().is_ok()
134 }
135
136 fn pci_offset(mode: &AddressMode) -> usize {
142 match mode {
143 AddressMode::Physical => 0, AddressMode::Functional => 1, }
146 }
147
148 fn isotp_bytes(&self, mode: &IsoTpAddressingMode) -> Option<&[u8]> {
151 let data = self.data_bytes()?;
152 let offset = mode.pci_offset();
153 if data.len() <= offset {
154 return None;
155 }
156 Some(&data[offset..])
157 }
158 }
160
161impl<'a> CanFrameExt for CanFrame<'a> {
162 fn as_bytes(&self) -> &[u8] {
163 ace_proto::common::RawFrame::as_bytes(self)
164 }
165}
166
167impl<'a> CanFrameExt for CanFrameMut<'a> {
168 fn as_bytes(&self) -> &[u8] {
169 ace_proto::common::RawFrame::as_bytes(self)
170 }
171}
172
173pub trait CanFrameMutExt: CanFrameExt {
178 fn as_bytes_mut(&mut self) -> &mut [u8];
179
180 fn set_id_word(&mut self, word: u32) -> Result<(), CanError> {
181 let b = self.as_bytes_mut();
182 if b.len() < DATA_OFFSET {
183 return Err(CanError::BufferTooShort {
184 expected: DATA_OFFSET,
185 actual: b.len(),
186 });
187 }
188 b[0..4].copy_from_slice(&word.to_be_bytes());
189 Ok(())
190 }
191
192 fn set_standard_id(&mut self, id: &ace_proto::can::id::StandardCanId) -> Result<(), CanError> {
193 let word = id.value() as u32 & STD_ID_MASK;
194 self.set_id_word(word)
195 }
196
197 fn set_extended_id(&mut self, id: &ace_proto::can::id::ExtendedCanId) -> Result<(), CanError> {
198 let word = (id.value() & EXT_ID_MASK) | EFF_FLAG;
199 self.set_id_word(word)
200 }
201
202 fn set_dlc(&mut self, dlc: u8) -> Result<(), CanError> {
203 if dlc > CLASSIC_CAN_MAX_DLC {
204 return Err(CanError::InvalidDlc(dlc));
205 }
206 let b = self.as_bytes_mut();
207 if b.len() <= DLC_OFFSET {
208 return Err(CanError::BufferTooShort {
209 expected: DLC_OFFSET + 1,
210 actual: b.len(),
211 });
212 }
213 b[DLC_OFFSET] = dlc;
214 Ok(())
215 }
216
217 fn write_data(&mut self, data: &[u8]) -> Result<(), CanError> {
218 if data.len() > CLASSIC_CAN_MAX_DLC as usize {
219 return Err(CanError::InvalidDlc(data.len() as u8));
220 }
221 let b = self.as_bytes_mut();
222 let end = DATA_OFFSET + data.len();
223 if b.len() < end {
224 return Err(CanError::BufferTooShort {
225 expected: end,
226 actual: b.len(),
227 });
228 }
229 b[DATA_OFFSET..end].copy_from_slice(data);
230 b[DLC_OFFSET] = data.len() as u8;
231 Ok(())
232 }
233}
234
235impl<'a> CanFrameMutExt for CanFrameMut<'a> {
236 fn as_bytes_mut(&mut self) -> &mut [u8] {
237 ace_proto::common::RawFrameMut::as_bytes_mut(self)
238 }
239}
240
241