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}