dbc_rs/message/
impls.rs

1use super::{Message, Signals};
2use crate::compat::Name;
3
4impl Message {
5    pub(crate) fn new(id: u32, name: Name, dlc: u8, sender: Name, signals: Signals) -> Self {
6        // Validation should have been done prior (by builder or parse)
7        Self {
8            id,
9            name,
10            dlc,
11            sender,
12            signals,
13        }
14    }
15
16    /// Returns the CAN message ID.
17    ///
18    /// This returns the raw CAN ID as it would appear on the bus (11-bit or 29-bit).
19    /// For extended (29-bit) IDs, the internal flag bit is stripped.
20    /// Use [`is_extended()`](Self::is_extended) to check if this is an extended ID.
21    ///
22    /// # Examples
23    ///
24    /// ```rust,no_run
25    /// use dbc_rs::Dbc;
26    ///
27    /// let dbc = Dbc::parse(r#"VERSION "1.0"\n\nBU_: ECM\n\nBO_ 256 EngineData : 8 ECM"#)?;
28    /// let message = dbc.messages().at(0).unwrap();
29    /// assert_eq!(message.id(), 256);
30    /// # Ok::<(), dbc_rs::Error>(())
31    /// ```
32    #[inline]
33    #[must_use = "return value should be used"]
34    pub fn id(&self) -> u32 {
35        self.id & Self::MAX_EXTENDED_ID
36    }
37
38    /// Returns the raw internal ID including any extended ID flag.
39    ///
40    /// This is primarily for internal use. Most users should use [`id()`](Self::id) instead.
41    #[inline]
42    #[must_use = "return value should be used"]
43    pub(crate) fn id_with_flag(&self) -> u32 {
44        self.id
45    }
46
47    /// Returns `true` if this message uses an extended (29-bit) CAN ID.
48    ///
49    /// Standard CAN uses 11-bit identifiers (0-2047), while extended CAN uses 29-bit
50    /// identifiers (0-536870911).
51    ///
52    /// # Examples
53    ///
54    /// ```rust,no_run
55    /// use dbc_rs::Dbc;
56    ///
57    /// // Standard 11-bit ID
58    /// let dbc = Dbc::parse(r#"VERSION "1.0"\n\nBU_: ECM\n\nBO_ 256 EngineData : 8 ECM"#)?;
59    /// let message = dbc.messages().at(0).unwrap();
60    /// assert!(!message.is_extended());
61    ///
62    /// // Extended 29-bit ID (with flag bit set: 0x80000000 | 0x18DAF115)
63    /// let dbc = Dbc::parse(r#"VERSION "1.0"\n\nBU_: ECM\n\nBO_ 2564485397 OBD2 : 8 ECM"#)?;
64    /// let message = dbc.messages().at(0).unwrap();
65    /// assert!(message.is_extended());
66    /// assert_eq!(message.id(), 0x18DAF115);
67    /// # Ok::<(), dbc_rs::Error>(())
68    /// ```
69    #[inline]
70    #[must_use = "return value should be used"]
71    pub fn is_extended(&self) -> bool {
72        (self.id & Self::EXTENDED_ID_FLAG) != 0
73    }
74
75    /// Returns the message name.
76    ///
77    /// # Examples
78    ///
79    /// ```rust,no_run
80    /// use dbc_rs::Dbc;
81    ///
82    /// let dbc = Dbc::parse(r#"VERSION "1.0"\n\nBU_: ECM\n\nBO_ 256 EngineData : 8 ECM"#)?;
83    /// let message = dbc.messages().at(0).unwrap();
84    /// assert_eq!(message.name(), "EngineData");
85    /// # Ok::<(), dbc_rs::Error>(())
86    /// ```
87    #[inline]
88    #[must_use = "return value should be used"]
89    pub fn name(&self) -> &str {
90        self.name.as_str()
91    }
92
93    /// Returns the Data Length Code (DLC) in bytes.
94    ///
95    /// DLC specifies the size of the message payload. For classic CAN, this is 1-8 bytes.
96    /// For CAN FD, this can be up to 64 bytes.
97    ///
98    /// # Examples
99    ///
100    /// ```rust,no_run
101    /// use dbc_rs::Dbc;
102    ///
103    /// let dbc = Dbc::parse(r#"VERSION "1.0"\n\nBU_: ECM\n\nBO_ 256 EngineData : 8 ECM"#)?;
104    /// let message = dbc.messages().at(0).unwrap();
105    /// assert_eq!(message.dlc(), 8);
106    /// # Ok::<(), dbc_rs::Error>(())
107    /// ```
108    #[inline]
109    #[must_use = "return value should be used"]
110    pub fn dlc(&self) -> u8 {
111        self.dlc
112    }
113
114    /// Get the sender node name for this message.
115    ///
116    /// The sender is the node that transmits this message on the CAN bus.
117    ///
118    /// # Examples
119    ///
120    /// ```rust,no_run
121    /// use dbc_rs::Dbc;
122    ///
123    /// let dbc = Dbc::parse(r#"VERSION "1.0"
124    ///
125    /// BU_: ECM TCM
126    ///
127    /// BO_ 256 Engine : 8 ECM
128    ///  SG_ RPM : 0|16@1+ (0.25,0) [0|8000] "rpm" *
129    /// "#)?;
130    ///
131    /// let message = dbc.messages().iter().next().unwrap();
132    /// assert_eq!(message.sender(), "ECM");
133    /// # Ok::<(), dbc_rs::Error>(())
134    /// ```
135    #[inline]
136    #[must_use = "return value should be used"]
137    pub fn sender(&self) -> &str {
138        self.sender.as_str()
139    }
140
141    /// Returns a reference to the signals collection for this message.
142    ///
143    /// The [`Signals`] collection provides methods to iterate, search, and access signals by index.
144    ///
145    /// # Examples
146    ///
147    /// ```rust,no_run
148    /// use dbc_rs::Dbc;
149    ///
150    /// let dbc = Dbc::parse(r#"VERSION "1.0"
151    ///
152    /// BU_: ECM
153    ///
154    /// BO_ 256 Engine : 8 ECM
155    ///  SG_ RPM : 0|16@1+ (0.25,0) [0|8000] "rpm" ECM
156    ///  SG_ Torque : 16|16@1+ (0.1,0) [0|500] "Nm" ECM
157    /// "#)?;
158    ///
159    /// let message = dbc.messages().find("Engine").unwrap();
160    /// let signals = message.signals();
161    /// assert_eq!(signals.len(), 2);
162    /// assert!(signals.find("RPM").is_some());
163    /// # Ok::<(), dbc_rs::Error>(())
164    /// ```
165    #[inline]
166    #[must_use = "return value should be used"]
167    pub fn signals(&self) -> &Signals {
168        &self.signals
169    }
170}
171
172#[cfg(test)]
173mod tests {
174    use super::*;
175    use crate::{Parser, Signal};
176
177    #[test]
178    fn test_message_getters_edge_cases() {
179        // Test with minimum values
180        let data = b"BO_ 0 A : 1 B";
181        let mut parser = Parser::new(data).unwrap();
182        let signals: &[Signal] = &[];
183        let message = Message::parse(&mut parser, signals).unwrap();
184
185        assert_eq!(message.id(), 0);
186        assert_eq!(message.name(), "A");
187        assert_eq!(message.dlc(), 1);
188        assert_eq!(message.sender(), "B");
189    }
190}