can_socket/
frame.rs

1use crate::CanId;
2use crate::error;
3
4/// A CAN frame as transmitted over a CAN socket.
5#[derive(Copy, Clone)]
6#[repr(transparent)]
7pub struct CanFrame {
8	pub(crate) inner: crate::sys::CanFrame,
9}
10
11impl CanFrame {
12	/// Create a new data from with the given CAN ID and data payload.
13	///
14	/// To create a new data frame with a potentially invalid ID or data payload,
15	/// use [`Self::try_new()`].
16	#[inline]
17	pub fn new(id: impl Into<CanId>, data: impl Into<CanData>) -> Self {
18		Self {
19			inner: crate::sys::CanFrame::new(id, &data.into())
20		}
21	}
22
23	/// Create a new data from with the given CAN ID and data payload.
24	///
25	/// Will report an error if the ID or data is invalid.
26	///
27	/// You should normally prefer [`Self::new()`] if you can guarantee that the ID and data are valid.
28	#[inline]
29	pub fn try_new<Id, Data>(id: Id, data: Data) -> Result<Self, error::TryNewCanFrameError>
30	where
31		Id: TryInto<CanId>,
32		error::TryNewCanFrameError: From<Id::Error>,
33		Data: TryInto<CanData>,
34		error::TryNewCanFrameError: From<Data::Error>,
35	{
36		Ok(Self::new(id.try_into()?, data.try_into()?))
37	}
38
39	/// Create a new remote transmission request (RTR) frame with a data length code of 0.
40	///
41	/// To set a different data length code, you can call [`Self::set_data_length_code()`]
42	/// or [`Self::with_data_length_code()`] after constructing the RTR frame.
43	#[inline]
44	pub fn new_rtr(id: impl Into<CanId>) -> Self {
45		Self {
46			inner: crate::sys::CanFrame::new_rtr(id),
47		}
48	}
49
50	/// Get the CAN ID of the frame.
51	#[inline]
52	pub fn id(&self) -> CanId {
53		self.inner.id()
54	}
55
56	/// Check if this frame is a remote transmission request (an RTR frame).
57	///
58	/// RTR frames represent a request to transmit a value over the CAN bus.
59	/// However, an application could decide to use RTR frames differently.
60	///
61	/// RTR frames have no associated data.
62	#[inline]
63	pub fn is_rtr(&self) -> bool {
64		self.inner.is_rtr()
65	}
66
67	/// Get the data of the frame.
68	///
69	/// Returns `None` for RTR frames and `Some(data)` for data frames.
70	#[inline]
71	pub fn data(&self) -> Option<CanData> {
72		self.inner.data()
73	}
74
75	/// Set the data length code of the frame.
76	///
77	/// If the data length code is higher than the current data length,
78	/// the extra data bytes that become available will have a value of `0`.
79	///
80	/// If the data length code is in the range 9 to 15 (inclusive), the actual data length of the frame will be set to 8.
81	/// However, if the CAN controller supports it, it may preserve the given data length code in the frame header.
82	#[inline]
83	pub fn set_data_length_code(&mut self, dlc: u8) -> Result<(), error::InvalidDataLengthCode> {
84		self.inner.set_data_length_code(dlc)
85			.map_err(|()| error::InvalidDataLengthCode { value: dlc })
86	}
87
88	/// Create a copy the frame with a modified data length code.
89	///
90	/// If the data length code is higher than the current data length,
91	/// the extra data bytes that become available will have a value of `0`.
92	///
93	/// If the data length code is in the range 9 to 15 (inclusive), the actual data length of the frame will be set to 8.
94	/// However, if the CAN controller supports it, it may preserve the given data length code in the frame header.
95	#[inline]
96	#[must_use = "this function returns a new frame, it does not modify self"]
97	pub fn with_data_length_code(mut self, dlc: u8) -> Result<Self, error::InvalidDataLengthCode> {
98		self.set_data_length_code(dlc)?;
99		Ok(self)
100	}
101
102	/// Get the data length code of the frame (it may be higher than the number of data bytes in the frame).
103	///
104	/// If this is an RTR frame, it is often used to indicate how much bytes are expected in the response data frame.
105	/// However, the application is free to use the data length code for a different purpose.
106	///
107	/// The CAN controller may preserve data length codes with a value above 8 (but at most 15).
108	/// The data length should normally be assumed to be 8 bytes,
109	/// and application is free to interpret the additional values according to it's own logic.
110	/// Note that your CAN controller or driver may not preserve data length codes above `8`.
111	#[inline]
112	pub fn data_length_code(&self) -> u8 {
113		self.inner.data_length_code()
114	}
115}
116
117impl std::fmt::Debug for CanFrame {
118	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119		let mut debug = f.debug_struct("CanFrame");
120		debug
121			.field("id", &format_args!("{:?}", self.id()))
122			.field("is_rtr", &self.is_rtr())
123			.field("data_length_code", &self.data_length_code());
124		if !self.is_rtr() {
125			debug.field("data", &format_args!("{:02X?}", self.data()));
126		}
127		debug.finish()
128	}
129}
130
131/// The data payload of a CAN frame.
132///
133/// Can hold up to 8 bytes.
134#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
135pub struct CanData {
136	pub(crate) data: [u8; 8],
137	pub(crate) len: u8,
138}
139
140impl CanData {
141	/// Construct a CAN data object from a supported fixed size array.
142	///
143	/// Also allows construction from any other type if it implements [`Into<CanData>`].
144	pub fn new(data: impl Into<CanData>) -> Self {
145		data.into()
146	}
147
148	/// Construct a CAN data object from a supported fixed size array.
149	///
150	/// Also allows construction from any other type if it implements [`Into<CanData>`].
151	pub fn try_new<E>(data: impl TryInto<CanData, Error = E>) -> Result<Self, E> {
152		data.try_into()
153	}
154
155	/// Get the data as a slice of bytes.
156	#[inline]
157	pub fn as_slice(&self) -> &[u8] {
158		&self.data[..self.len.into()]
159	}
160
161	/// Get the data as a mutable slice of bytes.
162	#[inline]
163	pub fn as_slice_mut(&mut self) -> &mut [u8] {
164		&mut self.data[..self.len.into()]
165	}
166}
167
168impl std::fmt::Debug for CanData {
169	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
170		std::fmt::Debug::fmt(self.as_slice(), f)
171	}
172}
173impl std::ops::Deref for CanData {
174	type Target = [u8];
175
176	fn deref(&self) -> &Self::Target {
177		self.as_slice()
178	}
179}
180
181impl std::ops::DerefMut for CanData {
182	fn deref_mut(&mut self) -> &mut Self::Target {
183		self.as_slice_mut()
184	}
185}
186
187impl std::borrow::Borrow<[u8]> for CanData {
188	fn borrow(&self) -> &[u8] {
189		self.as_slice()
190	}
191}
192
193impl std::borrow::BorrowMut<[u8]> for CanData {
194	fn borrow_mut(&mut self) -> &mut [u8] {
195		self.as_slice_mut()
196	}
197}
198
199impl AsRef<[u8]> for CanData {
200	fn as_ref(&self) -> &[u8] {
201		self.as_slice()
202	}
203}
204
205impl AsMut<[u8]> for CanData {
206	fn as_mut(&mut self) -> &mut [u8] {
207		self.as_slice_mut()
208	}
209}
210
211impl PartialEq<[u8]> for CanData {
212	fn eq(&self, other: &[u8]) -> bool {
213		self.as_slice() == other
214	}
215}
216
217impl PartialEq<CanData> for [u8] {
218	fn eq(&self, other: &CanData) -> bool {
219		self == other.as_slice()
220	}
221}
222
223macro_rules! impl_from_array {
224	($n:literal) => {
225		impl From<[u8; $n]> for CanData {
226			fn from(value: [u8; $n]) -> Self {
227				let mut data = [0; 8];
228				data[..value.len()].copy_from_slice(&value);
229				Self {
230					data,
231					len: $n,
232				}
233			}
234		}
235
236		impl<'a> From<&'a [u8; $n]> for CanData {
237			fn from(value: &'a [u8; $n]) -> Self {
238				let mut data = [0; 8];
239				data[..value.len()].copy_from_slice(value);
240				Self {
241					data,
242					len: $n,
243				}
244			}
245		}
246
247		impl TryFrom<CanData> for [u8; $n] {
248			type Error = core::array::TryFromSliceError;
249
250			fn try_from(other: CanData) -> Result<Self, Self::Error> {
251				other.as_slice().try_into()
252			}
253		}
254
255		impl<'a> TryFrom<&'a CanData> for [u8; $n] {
256			type Error = core::array::TryFromSliceError;
257
258			fn try_from(other: &'a CanData) -> Result<Self, Self::Error> {
259				other.as_slice().try_into()
260			}
261		}
262
263		impl PartialEq<[u8; $n]> for CanData {
264			fn eq(&self, other: &[u8; $n]) -> bool {
265				if self.len == $n {
266					&self.data[..$n] == other
267				} else {
268					false
269				}
270			}
271		}
272
273		impl PartialEq<CanData> for [u8; $n] {
274			fn eq(&self, other: &CanData) -> bool {
275				other == self
276			}
277		}
278	}
279}
280
281impl_from_array!(0);
282impl_from_array!(1);
283impl_from_array!(2);
284impl_from_array!(3);
285impl_from_array!(4);
286impl_from_array!(5);
287impl_from_array!(6);
288impl_from_array!(7);
289impl_from_array!(8);
290
291impl TryFrom<&[u8]> for CanData {
292	type Error = error::TryIntoCanDataError;
293
294	fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
295		if value.len() > 8 {
296			Err(error::TryIntoCanDataError {
297				len: value.len(),
298			})
299		} else {
300			let mut data = [0; 8];
301			data[..value.len()].copy_from_slice(value);
302			Ok(Self {
303				data,
304				len: value.len() as u8,
305			})
306		}
307	}
308}
309
310impl TryFrom<&Vec<u8>> for CanData {
311	type Error = error::TryIntoCanDataError;
312
313	fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
314		value.as_slice().try_into()
315	}
316}
317
318impl TryFrom<&Box<[u8]>> for CanData {
319	type Error = error::TryIntoCanDataError;
320
321	fn try_from(value: &Box<[u8]>) -> Result<Self, Self::Error> {
322		let value: &[u8] = value;
323		value.try_into()
324	}
325}
326
327
328#[cfg(test)]
329mod test {
330	use super::*;
331	use assert2::assert;
332	use crate::can_id;
333
334	#[test]
335	fn can_frame_is_copy() {
336		let frame = CanFrame::new(1u8, [1, 2, 3, 4]);
337		let copy = frame;
338		assert!(copy.id() == can_id!(1));
339		assert!(copy.data() == Some(CanData::new([1, 2, 3, 4])));
340	}
341
342	#[test]
343	fn can_data_from_array() {
344		assert!(CanData::from([1]) == [1]);
345		assert!(CanData::from([1, 2]) == [1, 2]);
346		assert!(CanData::from([1, 2, 3]) == [1, 2, 3]);
347		assert!(CanData::from([1, 2, 3, 4, 5]) == [1, 2, 3, 4, 5]);
348		assert!(CanData::from([1, 2, 3, 4, 5, 6]) == [1, 2, 3, 4, 5, 6]);
349		assert!(CanData::from([1, 2, 3, 4, 5, 6, 7]) == [1, 2, 3, 4, 5, 6, 7]);
350		assert!(CanData::from([1, 2, 3, 4, 5, 6, 7, 8]) == [1, 2, 3, 4, 5, 6, 7, 8]);
351
352		assert!(CanData::from([1, 2]) != [1]);
353		assert!(CanData::from([1]) != [1, 2]);
354	}
355}