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}