dbc_rs/value_descriptions/
impls.rs

1use super::ValueDescriptions;
2use crate::compat::ValueDescEntries;
3
4impl ValueDescriptions {
5    /// Create ValueDescriptions from a Vec of (value, description) pairs
6    pub(crate) fn new(entries: ValueDescEntries) -> Self {
7        // Validation should have been done prior (by builder or parse)
8        Self { entries }
9    }
10
11    /// Get the description for a numeric value
12    ///
13    /// # Examples
14    ///
15    /// ```rust,no_run
16    /// # use dbc_rs::Dbc;
17    /// # 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" ;"#)?;
18    /// # let message = dbc.messages().iter().next().unwrap();
19    /// # let signal = message.signals().iter().next().unwrap();
20    /// if let Some(value_descriptions) = dbc.value_descriptions_for_signal(message.id(), signal.name()) {
21    ///     if let Some(desc) = value_descriptions.get(0) {
22    ///         println!("Value 0: {}", desc);
23    ///     }
24    /// }
25    /// # Ok::<(), dbc_rs::Error>(())
26    /// ```
27    #[must_use = "return value should be used"]
28    pub fn get(&self, value: u64) -> Option<&str> {
29        for (v, desc) in &self.entries {
30            if *v == value {
31                return Some(desc.as_ref());
32            }
33        }
34        None
35    }
36
37    /// Returns the number of value descriptions.
38    ///
39    /// # Examples
40    ///
41    /// ```rust,no_run
42    /// # use dbc_rs::Dbc;
43    /// # 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" 2 "Neutral" ;"#)?;
44    /// # let message = dbc.messages().iter().next().unwrap();
45    /// # let signal = message.signals().iter().next().unwrap();
46    /// if let Some(value_descriptions) = dbc.value_descriptions_for_signal(message.id(), signal.name()) {
47    ///     assert_eq!(value_descriptions.len(), 3);
48    /// }
49    /// # Ok::<(), dbc_rs::Error>(())
50    /// ```
51    #[must_use = "return value should be used"]
52    pub fn len(&self) -> usize {
53        self.entries.len()
54    }
55
56    /// Returns `true` if there are no value descriptions.
57    ///
58    /// # Examples
59    ///
60    /// ```rust,no_run
61    /// # use dbc_rs::Dbc;
62    /// # 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" ;"#)?;
63    /// # let message = dbc.messages().iter().next().unwrap();
64    /// # let signal = message.signals().iter().next().unwrap();
65    /// if let Some(value_descriptions) = dbc.value_descriptions_for_signal(message.id(), signal.name()) {
66    ///     assert!(!value_descriptions.is_empty());
67    /// }
68    /// # Ok::<(), dbc_rs::Error>(())
69    /// ```
70    #[must_use = "return value should be used"]
71    pub fn is_empty(&self) -> bool {
72        self.entries.is_empty()
73    }
74
75    /// Get a value description by index.
76    ///
77    /// Returns `None` if the index is out of bounds.
78    ///
79    /// # Arguments
80    ///
81    /// * `index` - The zero-based index of the value description
82    ///
83    /// # Examples
84    ///
85    /// ```rust,no_run
86    /// # use dbc_rs::Dbc;
87    /// # 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" ;"#)?;
88    /// # let message = dbc.messages().iter().next().unwrap();
89    /// # let signal = message.signals().iter().next().unwrap();
90    /// if let Some(value_descriptions) = dbc.value_descriptions_for_signal(message.id(), signal.name()) {
91    ///     if let Some((value, description)) = value_descriptions.at(0) {
92    ///         println!("Value {}: {}", value, description);
93    ///     }
94    /// }
95    /// # Ok::<(), dbc_rs::Error>(())
96    /// ```
97    #[must_use = "return value should be used"]
98    pub fn at(&self, index: usize) -> Option<(u64, &str)> {
99        self.entries.get(index).map(|(value, desc)| (*value, desc.as_str()))
100    }
101
102    /// Iterate over all value descriptions
103    ///
104    /// # Examples
105    ///
106    /// ```rust,no_run
107    /// # use dbc_rs::Dbc;
108    /// # 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" ;"#)?;
109    /// # let message = dbc.messages().iter().next().unwrap();
110    /// # let signal = message.signals().iter().next().unwrap();
111    /// if let Some(value_descriptions) = dbc.value_descriptions_for_signal(message.id(), signal.name()) {
112    ///     for (value, description) in value_descriptions.iter() {
113    ///         println!("{} -> {}", value, description);
114    ///     }
115    /// }
116    /// # Ok::<(), dbc_rs::Error>(())
117    /// ```
118    #[inline]
119    #[must_use = "iterator is lazy and does nothing unless consumed"]
120    pub fn iter(&self) -> impl Iterator<Item = (u64, &str)> + '_ {
121        self.entries.iter().map(|(value, desc)| (*value, desc.as_str()))
122    }
123}
124
125#[cfg(test)]
126mod tests {
127    use super::*;
128    use crate::MAX_NAME_SIZE;
129    use crate::compat::{String, Vec};
130
131    fn create_test_entries() -> ValueDescEntries {
132        let mut entries: Vec<(u64, String<{ MAX_NAME_SIZE }>), 64> = Vec::new();
133        let _ = entries.push((0, String::try_from("Park").unwrap()));
134        let _ = entries.push((1, String::try_from("Reverse").unwrap()));
135        let _ = entries.push((2, String::try_from("Neutral").unwrap()));
136        let _ = entries.push((3, String::try_from("Drive").unwrap()));
137        entries
138    }
139
140    #[test]
141    fn test_value_descriptions_get() {
142        let vd = ValueDescriptions::new(create_test_entries());
143
144        assert_eq!(vd.get(0), Some("Park"));
145        assert_eq!(vd.get(1), Some("Reverse"));
146        assert_eq!(vd.get(2), Some("Neutral"));
147        assert_eq!(vd.get(3), Some("Drive"));
148        assert_eq!(vd.get(4), None);
149        assert_eq!(vd.get(100), None);
150    }
151
152    #[test]
153    fn test_value_descriptions_len() {
154        let vd = ValueDescriptions::new(create_test_entries());
155        assert_eq!(vd.len(), 4);
156    }
157
158    #[test]
159    fn test_value_descriptions_is_empty() {
160        let vd = ValueDescriptions::new(create_test_entries());
161        assert!(!vd.is_empty());
162
163        let empty_entries: ValueDescEntries = Vec::new();
164        let empty_vd = ValueDescriptions::new(empty_entries);
165        assert!(empty_vd.is_empty());
166    }
167
168    #[test]
169    fn test_value_descriptions_at() {
170        let vd = ValueDescriptions::new(create_test_entries());
171
172        assert_eq!(vd.at(0), Some((0, "Park")));
173        assert_eq!(vd.at(1), Some((1, "Reverse")));
174        assert_eq!(vd.at(2), Some((2, "Neutral")));
175        assert_eq!(vd.at(3), Some((3, "Drive")));
176        assert_eq!(vd.at(4), None);
177        assert_eq!(vd.at(100), None);
178    }
179
180    #[test]
181    fn test_value_descriptions_iter() {
182        let vd = ValueDescriptions::new(create_test_entries());
183
184        let mut collected: Vec<(u64, &str), 64> = Vec::new();
185        for item in vd.iter() {
186            let _ = collected.push(item);
187        }
188        assert_eq!(collected.len(), 4);
189        assert_eq!(collected[0], (0, "Park"));
190        assert_eq!(collected[1], (1, "Reverse"));
191        assert_eq!(collected[2], (2, "Neutral"));
192        assert_eq!(collected[3], (3, "Drive"));
193    }
194
195    #[test]
196    fn test_value_descriptions_empty_iter() {
197        let empty_entries: ValueDescEntries = Vec::new();
198        let vd = ValueDescriptions::new(empty_entries);
199
200        let mut collected: Vec<(u64, &str), 64> = Vec::new();
201        for item in vd.iter() {
202            let _ = collected.push(item);
203        }
204        assert!(collected.is_empty());
205    }
206}