can_types/message.rs
1// Copyright (c) 2024 Nathan H. Keough
2//
3// This work is dual-licensed under MIT OR Apache 2.0 (or any later version).
4// You may choose between one of them if you use this work.
5//
6// For further detail, please refer to the individual licenses located at the root of this crate.
7
8use crate::{
9 conversion::Conversion,
10 identifier::{Id, IsProtocol},
11 payload::{Data, IsDataUnit, Name, Pdu},
12 protocol::j1939::identifier::J1939,
13};
14
15/// Represents a CAN message with its associated identifier ([`Id`]) and protocol data unit ([`Pdu`]).
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
17pub struct Message<P: IsProtocol, U: IsDataUnit> {
18 id: Id<P>,
19 pdu: Pdu<U>,
20}
21
22impl Message<J1939, Data> {
23 /// Constructs a new Message from its parts: a 29-bit J1939 identifier and pdu containing 64 bits of generic data.
24 ///
25 /// # Arguments
26 /// - `id`: An [`Id<J1939>`] representing the 29-bit identifier of the message.
27 /// - `pdu`: A [`Pdu<Data>`] containing the payload or content of the message.
28 ///
29 /// # Returns
30 /// A new [`Message`] instance initialized with the provided parts.
31 #[inline]
32 #[must_use]
33 pub fn from_parts(id: Id<J1939>, pdu: Pdu<Data>) -> Self {
34 Self { id, pdu }
35 }
36
37 /// Destructures the [`Message`] into its parts: a 29-bit J1939 identifier and pdu containing 64 bits of generic data.
38 ///
39 /// # Returns
40 /// A tuple containing:
41 /// - An [`Id<J1939>`] representing the 29-bit identifier.
42 /// - A [`Pdu<Data>`] containing the payload or content of the message.
43 #[inline]
44 #[must_use]
45 pub fn into_parts(self) -> (Id<J1939>, Pdu<Data>) {
46 (self.id, self.pdu)
47 }
48
49 /// Constructs a new [`Message`] from raw bit representations of its components.
50 /// # Errors
51 /// - If failed to construct the identifier field from bits
52 /// - If failed to construct the pdu field from bits
53 #[inline]
54 pub fn try_from_bits(hex_id: u32, hex_pdu: u64) -> Result<Self, anyhow::Error> {
55 let id = Id::<J1939>::from_bits(hex_id);
56 let pdu = Pdu::<Data>::try_from_bits(hex_pdu)?;
57
58 Ok(Self { id, pdu })
59 }
60
61 /// Constructs a new [`Message`] from hexadecimal string representations of its components.
62 /// # Errors
63 /// - If failed to construct the identifier field from hex
64 /// - If failed to construct the pdu field from hex
65 #[inline]
66 pub fn try_from_hex(hex_id: &str, hex_pdu: &str) -> Result<Self, anyhow::Error> {
67 let id = Id::<J1939>::try_from_hex(hex_id)?;
68 let pdu = Pdu::<Data>::try_from_hex(hex_pdu)?;
69
70 Ok(Self { id, pdu })
71 }
72
73 /// Constructs a new [`Message`] from raw bit representations of its components.
74 ///
75 /// # Arguments
76 /// - `hex_id`: A `u32` representing the hexadecimal encoded 29-bit J1939 identifier.
77 /// - `hex_pdu`: A `u64` representing the hexadecimal encoded pdu.
78 ///
79 /// # Returns
80 /// A new [`Message`] instance initialized with the decoded components.
81 #[inline]
82 #[must_use]
83 pub fn from_bits(hex_id: u32, hex_pdu: u64) -> Self {
84 let id = Id::<J1939>::from_bits(hex_id);
85 let pdu = Pdu::<Data>::from_bits(hex_pdu);
86
87 Self { id, pdu }
88 }
89
90 /// Constructs a new [`Message`] from hexadecimal string representations of its components.
91 ///
92 /// # Arguments
93 /// - `hex_id`: A `&str` representing the hexadecimal encoded 29-bit J1939 identifier.
94 /// - `hex_pdu`: A `&str` representing the hexadecimal encoded pdu.
95 ///
96 /// # Returns
97 /// A new [`Message`] instance initialized with the decoded components.
98 #[inline]
99 #[must_use]
100 pub fn from_hex(hex_id: &str, hex_pdu: &str) -> Self {
101 let id = Id::<J1939>::from_hex(hex_id);
102 let pdu = Pdu::<Data>::from_hex(hex_pdu);
103
104 Self { id, pdu }
105 }
106
107 /// Retrieves the 29-bit J1939 identifier from the message.
108 ///
109 /// # Returns
110 /// The [`Id<J1939>`] bitfield associated with the message.
111 #[inline]
112 #[must_use]
113 pub fn id(&self) -> Id<J1939> {
114 self.id
115 }
116
117 /// Retrieves the pdu from the message.
118 ///
119 /// # Returns
120 /// The [`Pdu<Data>`] bitfield associated with the message.
121 #[inline]
122 #[must_use]
123 pub fn pdu(&self) -> Pdu<Data> {
124 self.pdu
125 }
126}
127
128impl Message<J1939, Name> {
129 /// Constructs a new [`Message`] from its parts: an identifier and pdu.
130 ///
131 /// # Arguments
132 /// - `id`: An [`Id<J1939>`] representing the 29-bit identifier of the message.
133 /// - `pdu`: A [`Pdu<Data>`] containing the payload or content of the message.
134 ///
135 /// # Returns
136 /// A new [`Message`] instance initialized with the provided parts.
137 #[inline]
138 #[must_use]
139 pub fn from_parts(id: Id<J1939>, pdu: Pdu<Name>) -> Self {
140 Self { id, pdu }
141 }
142
143 /// Destructures the [`Message`] into its parts: an identifier and pdu.
144 ///
145 /// # Returns
146 /// A tuple containing:
147 /// - An [`Id<J1939>`] representing the 29-bit identifier.
148 /// - A [`Pdu<Data>`] containing the payload or content of the message.
149 #[inline]
150 #[must_use]
151 pub fn into_parts(self) -> (Id<J1939>, Pdu<Name>) {
152 (self.id, self.pdu)
153 }
154
155 /// Constructs a new [`Message`] from raw bit representations of its components.
156 /// # Errors
157 /// - If failed to construct the identifier field from bits
158 /// - If failed to construct the pdu field from bits
159 #[inline]
160 pub fn try_from_bits(hex_id: u32, hex_pdu: u64) -> Result<Self, anyhow::Error> {
161 let id = Id::<J1939>::try_from_bits(hex_id)?;
162 let pdu = Pdu::<Name>::try_from_bits(hex_pdu)?;
163
164 Ok(Self { id, pdu })
165 }
166
167 /// Constructs a new [`Message`] from hexadecimal string representations of its components.
168 /// # Errors
169 /// - If failed to construct the identifier field from hex
170 /// - If failed to construct the pdu field from hex
171 #[inline]
172 pub fn try_from_hex(hex_id: &str, hex_pdu: &str) -> Result<Self, anyhow::Error> {
173 let id = Id::<J1939>::try_from_hex(hex_id)?;
174 let pdu = Pdu::<Name>::try_from_hex(hex_pdu)?;
175
176 Ok(Self { id, pdu })
177 }
178
179 /// Constructs a new [`Message`] from raw bit representations of its components.
180 ///
181 /// # Arguments
182 /// - `hex_id`: A `u32` representing the hexadecimal encoded 29-bit identifier.
183 /// - `hex_pdu`: A `u64` representing the hexadecimal encoded pdu.
184 ///
185 /// # Returns
186 /// A new [`Message`] instance initialized with the decoded components.
187 #[inline]
188 #[must_use]
189 pub fn from_bits(hex_id: u32, hex_pdu: u64) -> Self {
190 let id = Id::<J1939>::from_bits(hex_id);
191 let pdu = Pdu::<Name>::from_bits(hex_pdu);
192
193 Self { id, pdu }
194 }
195
196 /// Constructs a new [`Message`] from hexadecimal string representations of its components.
197 ///
198 /// # Arguments
199 /// - `hex_id`: A `&str` representing the hexadecimal encoded 29-bit identifier.
200 /// - `hex_pdu`: A `&str` representing the hexadecimal encoded pdu.
201 ///
202 /// # Returns
203 /// A new [`Message`] instance initialized with the decoded components.
204 #[inline]
205 #[must_use]
206 pub fn from_hex(hex_id: &str, hex_pdu: &str) -> Self {
207 let id = Id::<J1939>::from_hex(hex_id);
208 let pdu = Pdu::<Name>::from_hex(hex_pdu);
209
210 Self { id, pdu }
211 }
212
213 /// Retrieves the 29-bit identifier from the message.
214 ///
215 /// # Returns
216 /// The [`Id<J1939>`] bitfield associated with the message.
217 #[inline]
218 #[must_use]
219 pub fn id(&self) -> Id<J1939> {
220 self.id
221 }
222
223 /// Retrieves the pdu from the message.
224 ///
225 /// # Returns
226 /// The [`Pdu<Data>`] bitfield associated with the message.
227 #[inline]
228 #[must_use]
229 pub fn pdu(&self) -> Pdu<Name> {
230 self.pdu
231 }
232}
233
234impl From<Message<J1939, Data>> for Message<J1939, Name> {
235 fn from(value: Message<J1939, Data>) -> Self {
236 Self {
237 id: value.id(),
238 pdu: value.pdu().into(),
239 }
240 }
241}
242
243impl From<Message<J1939, Name>> for Message<J1939, Data> {
244 fn from(value: Message<J1939, Name>) -> Self {
245 Self {
246 id: value.id(),
247 pdu: value.pdu().into(),
248 }
249 }
250}