dbc_rs/dbc/
core.rs

1#[cfg(feature = "std")]
2use super::ValueDescriptionsMap;
3use crate::{Dbc, Nodes, Version, dbc::Messages};
4
5impl Dbc {
6    pub(crate) fn new(
7        version: Option<Version>,
8        nodes: Nodes,
9        messages: Messages,
10        #[cfg(feature = "std")] value_descriptions: ValueDescriptionsMap,
11    ) -> Self {
12        // Validation should have been done prior (by builder)
13        Self {
14            version,
15            nodes,
16            messages,
17            #[cfg(feature = "std")]
18            value_descriptions,
19        }
20    }
21
22    /// Get the version of the DBC file
23    ///
24    /// # Examples
25    ///
26    /// ```rust,no_run
27    /// use dbc_rs::Dbc;
28    ///
29    /// let dbc = Dbc::parse("VERSION \"1.0\"\n\nBU_: ECM\n\nBO_ 256 Engine : 8 ECM")?;
30    /// if let Some(version) = dbc.version() {
31    ///     // Version is available
32    ///     let _ = version.as_str();
33    /// }
34    /// # Ok::<(), dbc_rs::Error>(())
35    /// ```
36    #[inline]
37    #[must_use]
38    pub fn version(&self) -> Option<&Version> {
39        self.version.as_ref()
40    }
41
42    /// Get a reference to the nodes collection
43    ///
44    /// # Examples
45    ///
46    /// ```rust,no_run
47    /// use dbc_rs::Dbc;
48    ///
49    /// let dbc = Dbc::parse("VERSION \"1.0\"\n\nBU_: ECM TCM\n\nBO_ 256 Engine : 8 ECM")?;
50    /// let nodes = dbc.nodes();
51    /// assert_eq!(nodes.len(), 2);
52    /// // Iterate over nodes
53    /// let mut iter = nodes.iter();
54    /// assert_eq!(iter.next(), Some("ECM"));
55    /// assert_eq!(iter.next(), Some("TCM"));
56    /// assert_eq!(iter.next(), None);
57    /// # Ok::<(), dbc_rs::Error>(())
58    /// ```
59    #[inline]
60    #[must_use]
61    pub fn nodes(&self) -> &Nodes {
62        &self.nodes
63    }
64
65    /// Get a reference to the messages collection
66    ///
67    /// # Examples
68    ///
69    /// ```rust,no_run
70    /// use dbc_rs::Dbc;
71    ///
72    /// let dbc = Dbc::parse("VERSION \"1.0\"\n\nBU_: ECM\n\nBO_ 256 Engine : 8 ECM")?;
73    /// let messages = dbc.messages();
74    /// assert_eq!(messages.len(), 1);
75    /// let message = messages.at(0).unwrap();
76    /// assert_eq!(message.name(), "Engine");
77    /// assert_eq!(message.id(), 256);
78    /// # Ok::<(), dbc_rs::Error>(())
79    /// ```
80    #[inline]
81    #[must_use]
82    pub fn messages(&self) -> &Messages {
83        &self.messages
84    }
85
86    /// Get value descriptions for a specific signal
87    ///
88    /// Value descriptions map numeric signal values to human-readable text.
89    /// Returns `None` if the signal has no value descriptions.
90    ///
91    /// **Global Value Descriptions**: According to the Vector DBC specification,
92    /// a message_id of `-1` (0xFFFFFFFF) in a `VAL_` statement means the value
93    /// descriptions apply to all signals with that name in ANY message. This
94    /// method will first check for a message-specific entry, then fall back to
95    /// a global entry if one exists.
96    ///
97    /// # Examples
98    ///
99    /// ```rust,no_run
100    /// # use dbc_rs::Dbc;
101    /// # let dbc = Dbc::parse(r#"VERSION "1.0"\n\nBU_: ECM\n\nBO_ 100 Engine : 8 ECM\n SG_ Gear : 0|8@1+ (1,0) [0|5] "" *\n\nVAL_ 100 Gear 0 "Park" 1 "Reverse" ;"#)?;
102    /// if let Some(value_descriptions) = dbc.value_descriptions_for_signal(100, "Gear") {
103    ///     if let Some(desc) = value_descriptions.get(0) {
104    ///         println!("Value 0 means: {}", desc);
105    ///     }
106    /// }
107    /// # Ok::<(), dbc_rs::Error>(())
108    /// ```
109    /// Get a reference to the value descriptions list
110    ///
111    /// # Examples
112    ///
113    /// ```rust,no_run
114    /// use dbc_rs::Dbc;
115    ///
116    /// let dbc = Dbc::parse(r#"VERSION "1.0"
117    ///
118    /// BU_: ECM
119    ///
120    /// BO_ 100 Engine : 8 ECM
121    ///  SG_ Gear : 0|8@1+ (1,0) [0|5] "" *
122    ///
123    /// VAL_ 100 Gear 0 "Park" 1 "Drive" ;"#)?;
124    /// let value_descriptions_list = dbc.value_descriptions();
125    /// assert_eq!(value_descriptions_list.len(), 1);
126    /// # Ok::<(), dbc_rs::Error>(())
127    /// ```
128    #[cfg(feature = "std")]
129    #[inline]
130    #[must_use]
131    pub fn value_descriptions(&self) -> &ValueDescriptionsMap {
132        &self.value_descriptions
133    }
134
135    #[cfg(feature = "std")]
136    #[must_use]
137    pub fn value_descriptions_for_signal(
138        &self,
139        message_id: u32,
140        signal_name: &str,
141    ) -> Option<&crate::value_descriptions::ValueDescriptions> {
142        self.value_descriptions.for_signal(message_id, signal_name)
143    }
144}
145
146#[cfg(test)]
147mod tests {
148    use crate::Dbc;
149
150    #[test]
151    fn test_version() {
152        let dbc = Dbc::parse(
153            r#"VERSION "1.0"
154
155BU_: ECM
156
157BO_ 256 Engine : 8 ECM
158"#,
159        )
160        .unwrap();
161        assert_eq!(dbc.version().map(|v| v.as_str()), Some("1.0"));
162    }
163
164    #[test]
165    fn test_nodes() {
166        let dbc = Dbc::parse(
167            r#"VERSION "1.0"
168
169BU_: ECM TCM
170
171BO_ 256 Engine : 8 ECM
172"#,
173        )
174        .unwrap();
175        assert_eq!(dbc.nodes().len(), 2);
176        assert!(dbc.nodes().contains("ECM"));
177        assert!(dbc.nodes().contains("TCM"));
178    }
179
180    #[test]
181    fn test_messages() {
182        let dbc = Dbc::parse(
183            r#"VERSION "1.0"
184
185BU_: ECM
186
187BO_ 256 Engine : 8 ECM
188"#,
189        )
190        .unwrap();
191        assert_eq!(dbc.messages().len(), 1);
192        let message = dbc.messages().at(0).unwrap();
193        assert_eq!(message.name(), "Engine");
194        assert_eq!(message.id(), 256);
195    }
196}