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}