dbc_rs/message/
core.rs

1use super::{Message, Signals};
2use crate::{Signal, compat::String};
3
4impl Message {
5    #[cfg(feature = "std")]
6    pub(crate) fn new(
7        id: u32,
8        name: String<{ crate::MAX_NAME_SIZE }>,
9        dlc: u8,
10        sender: String<{ crate::MAX_NAME_SIZE }>,
11        signals: impl Into<Signals>,
12    ) -> Self {
13        // Validation should have been done prior (by builder or parse)
14        Self {
15            id,
16            name,
17            dlc,
18            sender,
19            signals: signals.into(),
20        }
21    }
22
23    pub(crate) fn new_from_signals(
24        id: u32,
25        name: &str,
26        dlc: u8,
27        sender: &str,
28        signals: &[Signal],
29    ) -> Self {
30        // Validation should have been done prior (by builder or parse)
31        let name_str: String<{ crate::MAX_NAME_SIZE }> = String::try_from(name)
32            .map_err(|_| crate::Error::Validation(crate::Error::MAX_NAME_SIZE_EXCEEDED))
33            .unwrap();
34        let sender_str: String<{ crate::MAX_NAME_SIZE }> = String::try_from(sender)
35            .map_err(|_| crate::Error::Validation(crate::Error::MAX_NAME_SIZE_EXCEEDED))
36            .unwrap();
37        Self {
38            id,
39            name: name_str,
40            dlc,
41            sender: sender_str,
42            signals: Signals::from_slice(signals),
43        }
44    }
45
46    /// Returns the CAN message ID.
47    ///
48    /// # Examples
49    ///
50    /// ```rust,no_run
51    /// use dbc_rs::Dbc;
52    ///
53    /// let dbc = Dbc::parse(r#"VERSION "1.0"\n\nBU_: ECM\n\nBO_ 256 EngineData : 8 ECM"#)?;
54    /// let message = dbc.messages().at(0).unwrap();
55    /// assert_eq!(message.id(), 256);
56    /// # Ok::<(), dbc_rs::Error>(())
57    /// ```
58    #[inline]
59    #[must_use = "return value should be used"]
60    pub fn id(&self) -> u32 {
61        self.id
62    }
63
64    /// Returns the message name.
65    ///
66    /// # Examples
67    ///
68    /// ```rust,no_run
69    /// use dbc_rs::Dbc;
70    ///
71    /// let dbc = Dbc::parse(r#"VERSION "1.0"\n\nBU_: ECM\n\nBO_ 256 EngineData : 8 ECM"#)?;
72    /// let message = dbc.messages().at(0).unwrap();
73    /// assert_eq!(message.name(), "EngineData");
74    /// # Ok::<(), dbc_rs::Error>(())
75    /// ```
76    #[inline]
77    #[must_use = "return value should be used"]
78    pub fn name(&self) -> &str {
79        self.name.as_str()
80    }
81
82    /// Returns the Data Length Code (DLC) in bytes.
83    ///
84    /// DLC specifies the size of the message payload. For classic CAN, this is 1-8 bytes.
85    /// For CAN FD, this can be up to 64 bytes.
86    ///
87    /// # Examples
88    ///
89    /// ```rust,no_run
90    /// use dbc_rs::Dbc;
91    ///
92    /// let dbc = Dbc::parse(r#"VERSION "1.0"\n\nBU_: ECM\n\nBO_ 256 EngineData : 8 ECM"#)?;
93    /// let message = dbc.messages().at(0).unwrap();
94    /// assert_eq!(message.dlc(), 8);
95    /// # Ok::<(), dbc_rs::Error>(())
96    /// ```
97    #[inline]
98    #[must_use = "return value should be used"]
99    pub fn dlc(&self) -> u8 {
100        self.dlc
101    }
102
103    /// Get the sender node name for this message.
104    ///
105    /// The sender is the node that transmits this message on the CAN bus.
106    ///
107    /// # Examples
108    ///
109    /// ```rust,no_run
110    /// use dbc_rs::Dbc;
111    ///
112    /// let dbc = Dbc::parse(r#"VERSION "1.0"
113    ///
114    /// BU_: ECM TCM
115    ///
116    /// BO_ 256 Engine : 8 ECM
117    ///  SG_ RPM : 0|16@1+ (0.25,0) [0|8000] "rpm" *
118    /// "#)?;
119    ///
120    /// let message = dbc.messages().iter().next().unwrap();
121    /// assert_eq!(message.sender(), "ECM");
122    /// # Ok::<(), dbc_rs::Error>(())
123    /// ```
124    #[inline]
125    #[must_use = "return value should be used"]
126    pub fn sender(&self) -> &str {
127        self.sender.as_str()
128    }
129
130    /// Get a reference to the signals collection
131    #[inline]
132    #[must_use = "return value should be used"]
133    pub fn signals(&self) -> &Signals {
134        &self.signals
135    }
136}
137
138#[cfg(test)]
139mod tests {
140    use super::*;
141    use crate::{Parser, Signal};
142
143    #[test]
144    fn test_message_getters_edge_cases() {
145        // Test with minimum values
146        let data = b"BO_ 0 A : 1 B";
147        let mut parser = Parser::new(data).unwrap();
148        let signals: &[Signal] = &[];
149        let message = Message::parse(&mut parser, signals).unwrap();
150
151        assert_eq!(message.id(), 0);
152        assert_eq!(message.name(), "A");
153        assert_eq!(message.dlc(), 1);
154        assert_eq!(message.sender(), "B");
155    }
156}