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