dbc_rs/dbc/
dbc_builder.rs1use crate::{
2 Dbc, Message, Nodes, Version,
3 error::{Error, Result, messages},
4};
5
6#[derive(Debug, Default)]
43pub struct DbcBuilder {
44 version: Option<Version<'static>>,
45 nodes: Option<Nodes<'static>>,
46 messages: Vec<Message<'static>>,
47}
48
49impl DbcBuilder {
50 pub fn new() -> Self {
60 Self::default()
61 }
62
63 #[must_use]
75 pub fn version(mut self, version: Version<'static>) -> Self {
76 self.version = Some(version);
77 self
78 }
79
80 #[must_use]
92 pub fn nodes(mut self, nodes: Nodes<'static>) -> Self {
93 self.nodes = Some(nodes);
94 self
95 }
96
97 #[must_use]
116 pub fn add_message(mut self, message: Message<'static>) -> Self {
117 self.messages.push(message);
118 self
119 }
120
121 #[must_use]
138 pub fn add_messages(mut self, messages: impl IntoIterator<Item = Message<'static>>) -> Self {
139 self.messages.extend(messages);
140 self
141 }
142
143 #[must_use]
159 pub fn messages(mut self, messages: Vec<Message<'static>>) -> Self {
160 self.messages = messages;
161 self
162 }
163
164 #[must_use]
175 pub fn clear_messages(mut self) -> Self {
176 self.messages.clear();
177 self
178 }
179
180 fn extract_fields(self) -> Result<(Version<'static>, Nodes<'static>, Vec<Message<'static>>)> {
181 let version = self
182 .version
183 .ok_or_else(|| Error::Dbc(messages::DBC_VERSION_REQUIRED.to_string()))?;
184 let nodes = self.nodes.unwrap_or_default();
186 Ok((version, nodes, self.messages))
187 }
188
189 #[must_use = "validation result should be checked"]
206 pub fn validate(self) -> Result<Self> {
207 let (version, nodes, messages) = self.extract_fields()?;
208 let messages_options: Vec<Option<Message<'static>>> =
210 messages.into_iter().map(Some).collect();
211 let messages_options_slice: &[Option<Message<'static>>] = &messages_options;
212 Dbc::validate(
213 Some(&version),
214 &nodes,
215 messages_options_slice,
216 messages_options_slice.len(),
217 )
218 .map_err(|e| match e {
219 crate::error::ParseError::Version(msg) => Error::Dbc(String::from(msg)),
220 _ => Error::from(e),
221 })?;
222 Ok(Self {
223 version: Some(version),
224 nodes: Some(nodes),
225 messages: messages_options.into_iter().map(|opt| opt.unwrap()).collect(),
226 })
227 }
228
229 pub fn build(self) -> Result<Dbc<'static>> {
246 let (version, nodes, messages) = self.extract_fields()?;
247 let messages_options: Vec<Option<Message<'static>>> =
249 messages.into_iter().map(Some).collect();
250 let messages_options_slice: &[Option<Message<'static>>] = &messages_options;
251 Dbc::validate(
253 Some(&version),
254 &nodes,
255 messages_options_slice,
256 messages_options_slice.len(),
257 )
258 .map_err(|e| match e {
259 crate::error::ParseError::Version(msg) => Error::Dbc(String::from(msg)),
260 _ => Error::from(e),
261 })?;
262 let messages: Vec<Message<'static>> =
264 messages_options.into_iter().map(|opt| opt.unwrap()).collect();
265 let messages_boxed: Box<[Message<'static>]> = messages.into_boxed_slice();
267 let messages_slice: &'static [Message<'static>] = Box::leak(messages_boxed);
268 Ok(Dbc::new(Some(version), nodes, messages_slice))
269 }
270}
271
272#[cfg(test)]
273mod tests {
274 #![allow(clippy::float_cmp)]
275 use super::DbcBuilder;
276 use crate::{ByteOrder, Error, Parser, Version, error::lang, nodes::NodesBuilder};
277 use crate::{MessageBuilder, ReceiversBuilder, SignalBuilder};
278
279 #[test]
280 fn test_dbc_builder_valid() {
281 let mut parser = Parser::new(b"VERSION \"1.0\"").unwrap();
282 let version = Version::parse(&mut parser).unwrap();
283 let nodes = NodesBuilder::new().add_node("ECM").build().unwrap();
284 let signal = SignalBuilder::new()
285 .name("RPM")
286 .start_bit(0)
287 .length(16)
288 .byte_order(ByteOrder::BigEndian)
289 .unsigned(true)
290 .factor(1.0)
291 .offset(0.0)
292 .min(0.0)
293 .max(100.0)
294 .receivers(ReceiversBuilder::new().none().build().unwrap())
295 .build()
296 .unwrap();
297 let message = MessageBuilder::new()
298 .id(256)
299 .name("EngineData")
300 .dlc(8)
301 .sender("ECM")
302 .add_signal(signal)
303 .build()
304 .unwrap();
305
306 let dbc = DbcBuilder::new()
307 .version(version)
308 .nodes(nodes)
309 .add_message(message)
310 .build()
311 .unwrap();
312
313 assert_eq!(dbc.messages().len(), 1);
314 assert_eq!(dbc.messages().at(0).unwrap().id(), 256);
315 }
316
317 #[test]
318 fn test_dbc_builder_missing_version() {
319 let nodes = NodesBuilder::new().add_node("ECM").build().unwrap();
320 let signal = SignalBuilder::new()
321 .name("RPM")
322 .start_bit(0)
323 .length(16)
324 .byte_order(ByteOrder::BigEndian)
325 .unsigned(true)
326 .factor(1.0)
327 .offset(0.0)
328 .min(0.0)
329 .max(100.0)
330 .receivers(ReceiversBuilder::new().none().build().unwrap())
331 .build()
332 .unwrap();
333 let message = MessageBuilder::new()
334 .id(256)
335 .name("EngineData")
336 .dlc(8)
337 .sender("ECM")
338 .add_signal(signal)
339 .build()
340 .unwrap();
341
342 let result = DbcBuilder::new().nodes(nodes).add_message(message).build();
343 assert!(result.is_err());
344 match result.unwrap_err() {
345 Error::Dbc(msg) => assert!(msg.contains(lang::DBC_VERSION_REQUIRED)),
346 _ => panic!("Expected Dbc error"),
347 }
348 }
349
350 #[test]
351 fn test_dbc_builder_missing_nodes() {
352 let mut parser = Parser::new(b"VERSION \"1.0\"").unwrap();
355 let version = Version::parse(&mut parser).unwrap();
356 let signal = SignalBuilder::new()
357 .name("RPM")
358 .start_bit(0)
359 .length(16)
360 .byte_order(ByteOrder::BigEndian)
361 .unsigned(true)
362 .factor(1.0)
363 .offset(0.0)
364 .min(0.0)
365 .max(100.0)
366 .receivers(ReceiversBuilder::new().none().build().unwrap())
367 .build()
368 .unwrap();
369 let message = MessageBuilder::new()
370 .id(256)
371 .name("EngineData")
372 .dlc(8)
373 .sender("ECM")
374 .add_signal(signal)
375 .build()
376 .unwrap();
377
378 let result = DbcBuilder::new().version(version).add_message(message).build();
380 assert!(result.is_ok());
381 let dbc = result.unwrap();
382 assert!(dbc.nodes().is_empty());
383 }
384
385 #[test]
386 fn test_dbc_builder_add_messages() {
387 let mut parser = Parser::new(b"VERSION \"1.0\"").unwrap();
388 let version = Version::parse(&mut parser).unwrap();
389 let nodes = NodesBuilder::new().add_node("ECM").build().unwrap();
390 let signal = SignalBuilder::new()
391 .name("RPM")
392 .start_bit(0)
393 .length(16)
394 .byte_order(ByteOrder::BigEndian)
395 .unsigned(true)
396 .factor(1.0)
397 .offset(0.0)
398 .min(0.0)
399 .max(100.0)
400 .receivers(ReceiversBuilder::new().none().build().unwrap())
401 .build()
402 .unwrap();
403 let message1 = MessageBuilder::new()
404 .id(256)
405 .name("EngineData")
406 .dlc(8)
407 .sender("ECM")
408 .add_signal(signal.clone())
409 .build()
410 .unwrap();
411 let message2 = MessageBuilder::new()
412 .id(512)
413 .name("BrakeData")
414 .dlc(4)
415 .sender("ECM")
416 .add_signal(signal)
417 .build()
418 .unwrap();
419
420 let dbc = DbcBuilder::new()
421 .version(version)
422 .nodes(nodes)
423 .add_messages(vec![message1, message2])
424 .build()
425 .unwrap();
426
427 assert_eq!(dbc.messages().len(), 2);
428 }
429
430 #[test]
431 fn test_dbc_builder_messages() {
432 let mut parser = Parser::new(b"VERSION \"1.0\"").unwrap();
433 let version = Version::parse(&mut parser).unwrap();
434 let nodes = NodesBuilder::new().add_node("ECM").build().unwrap();
435 let signal = SignalBuilder::new()
436 .name("RPM")
437 .start_bit(0)
438 .length(16)
439 .byte_order(ByteOrder::BigEndian)
440 .unsigned(true)
441 .factor(1.0)
442 .offset(0.0)
443 .min(0.0)
444 .max(100.0)
445 .receivers(ReceiversBuilder::new().none().build().unwrap())
446 .build()
447 .unwrap();
448 let message1 = MessageBuilder::new()
449 .id(256)
450 .name("EngineData")
451 .dlc(8)
452 .sender("ECM")
453 .add_signal(signal.clone())
454 .build()
455 .unwrap();
456 let message2 = MessageBuilder::new()
457 .id(512)
458 .name("BrakeData")
459 .dlc(4)
460 .sender("ECM")
461 .add_signal(signal)
462 .build()
463 .unwrap();
464
465 let dbc = DbcBuilder::new()
466 .version(version)
467 .nodes(nodes)
468 .messages(vec![message1, message2])
469 .build()
470 .unwrap();
471
472 assert_eq!(dbc.messages().len(), 2);
473 }
474
475 #[test]
476 fn test_dbc_builder_clear_messages() {
477 let mut parser = Parser::new(b"VERSION \"1.0\"").unwrap();
478 let version = Version::parse(&mut parser).unwrap();
479 let nodes = NodesBuilder::new().add_node("ECM").build().unwrap();
480 let signal = SignalBuilder::new()
481 .name("RPM")
482 .start_bit(0)
483 .length(16)
484 .byte_order(ByteOrder::BigEndian)
485 .unsigned(true)
486 .factor(1.0)
487 .offset(0.0)
488 .min(0.0)
489 .max(100.0)
490 .receivers(ReceiversBuilder::new().none().build().unwrap())
491 .build()
492 .unwrap();
493 let message = MessageBuilder::new()
494 .id(256)
495 .name("EngineData")
496 .dlc(8)
497 .sender("ECM")
498 .add_signal(signal)
499 .build()
500 .unwrap();
501
502 let dbc = DbcBuilder::new()
503 .version(version)
504 .nodes(nodes)
505 .add_message(message)
506 .clear_messages()
507 .build()
508 .unwrap();
509
510 assert_eq!(dbc.messages().len(), 0);
511 }
512
513 #[test]
514 fn test_dbc_builder_validate_missing_version() {
515 let nodes = NodesBuilder::new().add_node("ECM").build().unwrap();
516 let result = DbcBuilder::new().nodes(nodes).validate();
517 assert!(result.is_err());
518 match result.unwrap_err() {
519 Error::Dbc(msg) => assert!(msg.contains(lang::DBC_VERSION_REQUIRED)),
520 _ => panic!("Expected Dbc error"),
521 }
522 }
523
524 #[test]
525 fn test_dbc_builder_validate_missing_nodes() {
526 let mut parser = Parser::new(b"VERSION \"1.0\"").unwrap();
528 let version = Version::parse(&mut parser).unwrap();
529 let result = DbcBuilder::new().version(version).validate();
530 assert!(result.is_ok());
532 }
533
534 #[test]
535 fn test_dbc_builder_validate_valid() {
536 let mut parser = Parser::new(b"VERSION \"1.0\"").unwrap();
537 let version = Version::parse(&mut parser).unwrap();
538 let nodes = NodesBuilder::new().add_node("ECM").build().unwrap();
539 let signal = SignalBuilder::new()
540 .name("RPM")
541 .start_bit(0)
542 .length(16)
543 .byte_order(ByteOrder::BigEndian)
544 .unsigned(true)
545 .factor(1.0)
546 .offset(0.0)
547 .min(0.0)
548 .max(100.0)
549 .receivers(ReceiversBuilder::new().none().build().unwrap())
550 .build()
551 .unwrap();
552 let message = MessageBuilder::new()
553 .id(256)
554 .name("EngineData")
555 .dlc(8)
556 .sender("ECM")
557 .add_signal(signal)
558 .build()
559 .unwrap();
560
561 let result =
562 DbcBuilder::new().version(version).nodes(nodes).add_message(message).validate();
563 assert!(result.is_ok());
564 let validated = result.unwrap();
566 let dbc = validated.build().unwrap();
567 assert_eq!(dbc.messages().len(), 1);
568 }
569}