dbc_rs/dbc/builder/
build.rs1use super::DbcBuilder;
2use crate::{
3 Dbc, Message, Nodes, Result, Version,
4 dbc::{Messages, Validate},
5};
6use std::collections::BTreeMap;
7
8impl DbcBuilder {
9 #[must_use = "validation result should be checked"]
26 pub fn validate(self) -> Result<()> {
27 let (_version, nodes, messages, value_descriptions) = {
31 let version = self.version.build()?;
32 let nodes = self.nodes.build()?;
33 let messages: std::vec::Vec<Message> = self
34 .messages
35 .into_iter()
36 .map(|builder| builder.build())
37 .collect::<Result<std::vec::Vec<_>>>()?;
38 let mut value_descriptions_map: BTreeMap<
39 (Option<u32>, String),
40 crate::value_descriptions::ValueDescriptions,
41 > = BTreeMap::new();
42 for ((message_id, signal_name), vd_builder) in self.value_descriptions {
43 let vd: crate::value_descriptions::ValueDescriptions = vd_builder.build()?;
44 value_descriptions_map.insert((message_id, signal_name), vd);
45 }
46 let value_descriptions =
47 crate::dbc::ValueDescriptionsMap::from_map(value_descriptions_map);
48 (version, nodes, messages, value_descriptions)
49 };
50
51 Validate::validate(&nodes, &messages, Some(&value_descriptions))?;
53
54 Ok(())
55 }
56
57 fn extract_fields(
58 self,
59 ) -> Result<(Version, Nodes, Messages, crate::dbc::ValueDescriptionsMap)> {
60 let version = self.version.build()?;
62
63 let nodes = self.nodes.build()?;
65
66 let messages_vec: std::vec::Vec<Message> = self
69 .messages
70 .into_iter()
71 .map(|builder| builder.build())
72 .collect::<Result<std::vec::Vec<_>>>()?;
73 let messages = Messages::new(&messages_vec)?;
74
75 let mut value_descriptions_map: BTreeMap<
77 (Option<u32>, String),
78 crate::value_descriptions::ValueDescriptions,
79 > = BTreeMap::new();
80 for ((message_id, signal_name), vd_builder) in self.value_descriptions {
81 let vd: crate::value_descriptions::ValueDescriptions = vd_builder.build()?;
82 value_descriptions_map.insert((message_id, signal_name), vd);
83 }
84 let value_descriptions = crate::dbc::ValueDescriptionsMap::from_map(value_descriptions_map);
85
86 Ok((version, nodes, messages, value_descriptions))
87 }
88
89 pub fn build(self) -> Result<Dbc> {
106 let (version, nodes, messages, value_descriptions) = self.extract_fields()?;
107 let messages_slice: std::vec::Vec<Message> = messages.iter().cloned().collect();
110 Validate::validate(&nodes, &messages_slice, Some(&value_descriptions))?;
111 Ok(Dbc::new(Some(version), nodes, messages, value_descriptions))
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 #![allow(clippy::float_cmp)]
118 use super::DbcBuilder;
119 use crate::{
120 ByteOrder, MessageBuilder, NodesBuilder, ReceiversBuilder, SignalBuilder, VersionBuilder,
121 };
122
123 #[test]
124 fn test_dbc_builder_valid() {
125 let version = VersionBuilder::new().version("1.0");
126 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
127 let signal = SignalBuilder::new()
128 .name("RPM")
129 .start_bit(0)
130 .length(16)
131 .byte_order(ByteOrder::BigEndian)
132 .unsigned(true)
133 .factor(1.0)
134 .offset(0.0)
135 .min(0.0)
136 .max(100.0)
137 .receivers(ReceiversBuilder::new().none());
138 let message = MessageBuilder::new()
139 .id(256)
140 .name("EngineData")
141 .dlc(8)
142 .sender("ECM")
143 .add_signal(signal);
144
145 let dbc = DbcBuilder::new()
146 .version(version)
147 .nodes(nodes)
148 .add_message(message)
149 .build()
150 .unwrap();
151
152 assert_eq!(dbc.messages().len(), 1);
153 assert_eq!(dbc.messages().at(0).unwrap().id(), 256);
154 }
155
156 #[test]
157 fn test_dbc_builder_missing_version() {
158 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
159 let signal = SignalBuilder::new()
160 .name("RPM")
161 .start_bit(0)
162 .length(16)
163 .byte_order(ByteOrder::BigEndian)
164 .unsigned(true)
165 .factor(1.0)
166 .offset(0.0)
167 .min(0.0)
168 .max(100.0)
169 .receivers(ReceiversBuilder::new().none());
170 let message = MessageBuilder::new()
171 .id(256)
172 .name("EngineData")
173 .dlc(8)
174 .sender("ECM")
175 .add_signal(signal);
176
177 let result = DbcBuilder::new().nodes(nodes).add_message(message).build();
178 assert!(result.is_ok());
180 let dbc = result.unwrap();
181 assert_eq!(dbc.version().unwrap().as_str(), "");
182 }
183
184 #[test]
185 fn test_dbc_builder_missing_nodes() {
186 let version = VersionBuilder::new().version("1.0");
189 let signal = SignalBuilder::new()
190 .name("RPM")
191 .start_bit(0)
192 .length(16)
193 .byte_order(ByteOrder::BigEndian)
194 .unsigned(true)
195 .factor(1.0)
196 .offset(0.0)
197 .min(0.0)
198 .max(100.0)
199 .receivers(ReceiversBuilder::new().none());
200 let message = MessageBuilder::new()
201 .id(256)
202 .name("EngineData")
203 .dlc(8)
204 .sender("ECM")
205 .add_signal(signal);
206
207 let result = DbcBuilder::new().version(version).add_message(message).build();
209 assert!(result.is_ok());
210 let dbc = result.unwrap();
211 assert!(dbc.nodes().is_empty());
212 }
213
214 #[test]
215 fn test_dbc_builder_validate_missing_version() {
216 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
217 let result = DbcBuilder::new().nodes(nodes).validate();
219 assert!(result.is_ok());
220 }
221
222 #[test]
223 fn test_dbc_builder_validate_missing_nodes() {
224 let version = VersionBuilder::new().version("1.0");
226 let result = DbcBuilder::new().version(version).validate();
227 assert!(result.is_ok());
229 }
230
231 #[test]
232 fn test_dbc_builder_validate_valid() {
233 let version = VersionBuilder::new().version("1.0");
234 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
235 let signal = SignalBuilder::new()
236 .name("RPM")
237 .start_bit(0)
238 .length(16)
239 .byte_order(ByteOrder::BigEndian)
240 .unsigned(true)
241 .factor(1.0)
242 .offset(0.0)
243 .min(0.0)
244 .max(100.0)
245 .receivers(ReceiversBuilder::new().none());
246 let message = MessageBuilder::new()
247 .id(256)
248 .name("EngineData")
249 .dlc(8)
250 .sender("ECM")
251 .add_signal(signal);
252
253 let builder = DbcBuilder::new().version(version).nodes(nodes).add_message(message);
256 let result = builder.validate();
257 assert!(result.is_ok());
258 }
259}