1use super::DbcBuilder;
2use crate::{
3 BitTiming, Dbc, ExtendedMultiplexing, MAX_EXTENDED_MULTIPLEXING, MAX_MESSAGES, MAX_NAME_SIZE,
4 Message, Nodes, Result, Version,
5 compat::{BTreeMap, String, Vec as CompatVec},
6 dbc::{Messages, Validate},
7};
8
9impl DbcBuilder {
10 #[must_use = "validation result should be checked"]
27 pub fn validate(self) -> Result<()> {
28 let (_version, nodes, messages, value_descriptions, extended_multiplexing) = {
32 let version = self.version.build()?;
33 let nodes = self.nodes.build()?;
34 let messages: std::vec::Vec<Message> = self
35 .messages
36 .into_iter()
37 .map(|builder| builder.build())
38 .collect::<Result<std::vec::Vec<_>>>()?;
39 let mut value_descriptions_map: BTreeMap<
40 (Option<u32>, String<{ MAX_NAME_SIZE }>),
41 crate::value_descriptions::ValueDescriptions,
42 { MAX_MESSAGES },
43 > = BTreeMap::new();
44 for ((message_id, signal_name), vd_builder) in self.value_descriptions {
45 let vd: crate::value_descriptions::ValueDescriptions = vd_builder.build()?;
46 let compat_signal_name = String::try_from(signal_name.as_str())
47 .map_err(|_| crate::Error::Validation(crate::Error::MAX_NAME_SIZE_EXCEEDED))?;
48 let _ = value_descriptions_map.insert((message_id, compat_signal_name), vd);
49 }
50 let value_descriptions = crate::dbc::ValueDescriptionsMap::new(value_descriptions_map);
51
52 let extended_multiplexing_vec: std::vec::Vec<ExtendedMultiplexing> = self
54 .extended_multiplexing
55 .into_iter()
56 .map(|builder| builder.build())
57 .collect::<Result<std::vec::Vec<_>>>()?;
58
59 (
60 version,
61 nodes,
62 messages,
63 value_descriptions,
64 extended_multiplexing_vec,
65 )
66 };
67
68 Validate::validate(
70 &nodes,
71 &messages,
72 Some(&value_descriptions),
73 Some(&extended_multiplexing),
74 )?;
75
76 Ok(())
77 }
78
79 #[allow(clippy::type_complexity)]
80 fn extract_fields(
81 self,
82 ) -> Result<(
83 Version,
84 Option<BitTiming>,
85 Nodes,
86 Messages,
87 crate::dbc::ValueDescriptionsMap,
88 CompatVec<ExtendedMultiplexing, { MAX_EXTENDED_MULTIPLEXING }>,
89 Option<std::string::String>,
90 )> {
91 let version = self.version.build()?;
93
94 let bit_timing = match self.bit_timing {
96 Some(builder) => {
97 let bt = builder.build()?;
98 if bt.is_empty() { None } else { Some(bt) }
99 }
100 None => None,
101 };
102
103 let nodes = self.nodes.build()?;
105
106 let messages_vec: std::vec::Vec<Message> = self
109 .messages
110 .into_iter()
111 .map(|builder| builder.build())
112 .collect::<Result<std::vec::Vec<_>>>()?;
113 let messages = Messages::new(&messages_vec)?;
114
115 let mut value_descriptions_map: BTreeMap<
117 (Option<u32>, String<{ MAX_NAME_SIZE }>),
118 crate::value_descriptions::ValueDescriptions,
119 { MAX_MESSAGES },
120 > = BTreeMap::new();
121 for ((message_id, signal_name), vd_builder) in self.value_descriptions {
122 let vd: crate::value_descriptions::ValueDescriptions = vd_builder.build()?;
123 let compat_signal_name = String::try_from(signal_name.as_str())
124 .map_err(|_| crate::Error::Validation(crate::Error::MAX_NAME_SIZE_EXCEEDED))?;
125 let _ = value_descriptions_map.insert((message_id, compat_signal_name), vd);
126 }
127 let value_descriptions = crate::dbc::ValueDescriptionsMap::new(value_descriptions_map);
128
129 let extended_multiplexing_vec: std::vec::Vec<ExtendedMultiplexing> = self
131 .extended_multiplexing
132 .into_iter()
133 .map(|builder| builder.build())
134 .collect::<Result<std::vec::Vec<_>>>()?;
135
136 let mut extended_multiplexing: CompatVec<
138 ExtendedMultiplexing,
139 { MAX_EXTENDED_MULTIPLEXING },
140 > = CompatVec::new();
141 for ext_mux in extended_multiplexing_vec {
142 extended_multiplexing
143 .push(ext_mux)
144 .map_err(|_| crate::Error::expected("too many extended multiplexing entries"))?;
145 }
146
147 Ok((
148 version,
149 bit_timing,
150 nodes,
151 messages,
152 value_descriptions,
153 extended_multiplexing,
154 self.comment,
155 ))
156 }
157
158 pub fn build(self) -> Result<Dbc> {
175 let (
176 version,
177 bit_timing,
178 nodes,
179 messages,
180 value_descriptions,
181 extended_multiplexing,
182 comment,
183 ) = self.extract_fields()?;
184 let messages_slice: std::vec::Vec<Message> = messages.iter().cloned().collect();
187 let extended_multiplexing_slice: std::vec::Vec<ExtendedMultiplexing> =
188 extended_multiplexing.iter().cloned().collect();
189 Validate::validate(
190 &nodes,
191 &messages_slice,
192 Some(&value_descriptions),
193 Some(&extended_multiplexing_slice),
194 )?;
195 Ok(Dbc::new(
196 Some(version),
197 bit_timing,
198 nodes,
199 messages,
200 value_descriptions,
201 extended_multiplexing,
202 comment.map(|c| c.into()),
203 ))
204 }
205}
206
207#[cfg(test)]
208mod tests {
209 #![allow(clippy::float_cmp)]
210 use super::DbcBuilder;
211 use crate::{
212 ByteOrder, ExtendedMultiplexingBuilder, MessageBuilder, NodesBuilder, ReceiversBuilder,
213 SignalBuilder, ValueDescriptionsBuilder, VersionBuilder,
214 };
215
216 #[test]
217 fn test_dbc_builder_valid() {
218 let version = VersionBuilder::new().version("1.0");
219 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
220 let signal = SignalBuilder::new()
221 .name("RPM")
222 .start_bit(0)
223 .length(16)
224 .byte_order(ByteOrder::BigEndian)
225 .unsigned(true)
226 .factor(1.0)
227 .offset(0.0)
228 .min(0.0)
229 .max(100.0)
230 .receivers(ReceiversBuilder::new().none());
231 let message = MessageBuilder::new()
232 .id(256)
233 .name("EngineData")
234 .dlc(8)
235 .sender("ECM")
236 .add_signal(signal);
237
238 let dbc = DbcBuilder::new()
239 .version(version)
240 .nodes(nodes)
241 .add_message(message)
242 .build()
243 .unwrap();
244
245 assert_eq!(dbc.messages().len(), 1);
246 assert_eq!(dbc.messages().at(0).unwrap().id(), 256);
247 }
248
249 #[test]
250 fn test_dbc_builder_missing_version() {
251 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
252 let signal = SignalBuilder::new()
253 .name("RPM")
254 .start_bit(0)
255 .length(16)
256 .byte_order(ByteOrder::BigEndian)
257 .unsigned(true)
258 .factor(1.0)
259 .offset(0.0)
260 .min(0.0)
261 .max(100.0)
262 .receivers(ReceiversBuilder::new().none());
263 let message = MessageBuilder::new()
264 .id(256)
265 .name("EngineData")
266 .dlc(8)
267 .sender("ECM")
268 .add_signal(signal);
269
270 let result = DbcBuilder::new().nodes(nodes).add_message(message).build();
271 assert!(result.is_ok());
273 let dbc = result.unwrap();
274 assert_eq!(dbc.version().unwrap().as_str(), "");
275 }
276
277 #[test]
278 fn test_dbc_builder_missing_nodes() {
279 let version = VersionBuilder::new().version("1.0");
282 let signal = SignalBuilder::new()
283 .name("RPM")
284 .start_bit(0)
285 .length(16)
286 .byte_order(ByteOrder::BigEndian)
287 .unsigned(true)
288 .factor(1.0)
289 .offset(0.0)
290 .min(0.0)
291 .max(100.0)
292 .receivers(ReceiversBuilder::new().none());
293 let message = MessageBuilder::new()
294 .id(256)
295 .name("EngineData")
296 .dlc(8)
297 .sender("ECM")
298 .add_signal(signal);
299
300 let result = DbcBuilder::new().version(version).add_message(message).build();
302 assert!(result.is_ok());
303 let dbc = result.unwrap();
304 assert!(dbc.nodes().is_empty());
305 }
306
307 #[test]
308 fn test_dbc_builder_validate_missing_version() {
309 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
310 let result = DbcBuilder::new().nodes(nodes).validate();
312 assert!(result.is_ok());
313 }
314
315 #[test]
316 fn test_dbc_builder_validate_missing_nodes() {
317 let version = VersionBuilder::new().version("1.0");
319 let result = DbcBuilder::new().version(version).validate();
320 assert!(result.is_ok());
322 }
323
324 #[test]
325 fn test_dbc_builder_validate_valid() {
326 let version = VersionBuilder::new().version("1.0");
327 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
328 let signal = SignalBuilder::new()
329 .name("RPM")
330 .start_bit(0)
331 .length(16)
332 .byte_order(ByteOrder::BigEndian)
333 .unsigned(true)
334 .factor(1.0)
335 .offset(0.0)
336 .min(0.0)
337 .max(100.0)
338 .receivers(ReceiversBuilder::new().none());
339 let message = MessageBuilder::new()
340 .id(256)
341 .name("EngineData")
342 .dlc(8)
343 .sender("ECM")
344 .add_signal(signal);
345
346 let builder = DbcBuilder::new().version(version).nodes(nodes).add_message(message);
349 let result = builder.validate();
350 assert!(result.is_ok());
351 }
352
353 #[test]
358 fn test_dbc_builder_with_value_descriptions() {
359 let version = VersionBuilder::new().version("1.0");
360 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
361 let signal = SignalBuilder::new()
362 .name("Gear")
363 .start_bit(0)
364 .length(8)
365 .byte_order(ByteOrder::LittleEndian)
366 .unsigned(true)
367 .factor(1.0)
368 .offset(0.0)
369 .min(0.0)
370 .max(5.0)
371 .receivers(ReceiversBuilder::new().none());
372 let message = MessageBuilder::new()
373 .id(256)
374 .name("Transmission")
375 .dlc(8)
376 .sender("ECM")
377 .add_signal(signal);
378
379 let value_desc = ValueDescriptionsBuilder::new()
380 .add_entry(0, "Park")
381 .add_entry(1, "Reverse")
382 .add_entry(2, "Neutral")
383 .add_entry(3, "Drive");
384
385 let dbc = DbcBuilder::new()
386 .version(version)
387 .nodes(nodes)
388 .add_message(message)
389 .add_value_description(256, "Gear", value_desc)
390 .build()
391 .unwrap();
392
393 let vd = dbc.value_descriptions_for_signal(256, "Gear").unwrap();
395 assert_eq!(vd.get(0), Some("Park"));
396 assert_eq!(vd.get(1), Some("Reverse"));
397 assert_eq!(vd.get(2), Some("Neutral"));
398 assert_eq!(vd.get(3), Some("Drive"));
399 }
400
401 #[test]
402 fn test_dbc_builder_value_descriptions_message_not_found() {
403 let version = VersionBuilder::new().version("1.0");
404 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
405 let signal = SignalBuilder::new()
406 .name("RPM")
407 .start_bit(0)
408 .length(16)
409 .byte_order(ByteOrder::BigEndian)
410 .unsigned(true)
411 .factor(1.0)
412 .offset(0.0)
413 .min(0.0)
414 .max(100.0)
415 .receivers(ReceiversBuilder::new().none());
416 let message = MessageBuilder::new()
417 .id(256)
418 .name("EngineData")
419 .dlc(8)
420 .sender("ECM")
421 .add_signal(signal);
422
423 let value_desc = ValueDescriptionsBuilder::new().add_entry(0, "Off").add_entry(1, "On");
425
426 let result = DbcBuilder::new()
427 .version(version)
428 .nodes(nodes)
429 .add_message(message)
430 .add_value_description(999, "RPM", value_desc) .build();
432
433 assert!(result.is_err());
434 }
435
436 #[test]
437 fn test_dbc_builder_value_descriptions_signal_not_found() {
438 let version = VersionBuilder::new().version("1.0");
439 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
440 let signal = SignalBuilder::new()
441 .name("RPM")
442 .start_bit(0)
443 .length(16)
444 .byte_order(ByteOrder::BigEndian)
445 .unsigned(true)
446 .factor(1.0)
447 .offset(0.0)
448 .min(0.0)
449 .max(100.0)
450 .receivers(ReceiversBuilder::new().none());
451 let message = MessageBuilder::new()
452 .id(256)
453 .name("EngineData")
454 .dlc(8)
455 .sender("ECM")
456 .add_signal(signal);
457
458 let value_desc = ValueDescriptionsBuilder::new().add_entry(0, "Off").add_entry(1, "On");
460
461 let result = DbcBuilder::new()
462 .version(version)
463 .nodes(nodes)
464 .add_message(message)
465 .add_value_description(256, "NonExistentSignal", value_desc)
466 .build();
467
468 assert!(result.is_err());
469 }
470
471 #[test]
472 fn test_dbc_builder_validate_with_value_descriptions() {
473 let version = VersionBuilder::new().version("1.0");
474 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
475 let signal = SignalBuilder::new()
476 .name("Gear")
477 .start_bit(0)
478 .length(8)
479 .byte_order(ByteOrder::LittleEndian)
480 .unsigned(true)
481 .factor(1.0)
482 .offset(0.0)
483 .min(0.0)
484 .max(5.0)
485 .receivers(ReceiversBuilder::new().none());
486 let message = MessageBuilder::new()
487 .id(256)
488 .name("Transmission")
489 .dlc(8)
490 .sender("ECM")
491 .add_signal(signal);
492
493 let value_desc = ValueDescriptionsBuilder::new().add_entry(0, "Park").add_entry(1, "Drive");
494
495 let result = DbcBuilder::new()
496 .version(version)
497 .nodes(nodes)
498 .add_message(message)
499 .add_value_description(256, "Gear", value_desc)
500 .validate();
501
502 assert!(result.is_ok());
503 }
504
505 #[test]
510 fn test_dbc_builder_with_extended_multiplexing() {
511 let version = VersionBuilder::new().version("1.0");
512 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
513
514 let mux_signal = SignalBuilder::new()
516 .name("Mux1")
517 .start_bit(0)
518 .length(8)
519 .byte_order(ByteOrder::LittleEndian)
520 .unsigned(true)
521 .factor(1.0)
522 .offset(0.0)
523 .min(0.0)
524 .max(255.0)
525 .receivers(ReceiversBuilder::new().none());
526
527 let signal_a = SignalBuilder::new()
529 .name("SignalA")
530 .start_bit(16)
531 .length(16)
532 .byte_order(ByteOrder::LittleEndian)
533 .unsigned(true)
534 .factor(0.1)
535 .offset(0.0)
536 .min(0.0)
537 .max(100.0)
538 .receivers(ReceiversBuilder::new().none());
539
540 let message = MessageBuilder::new()
541 .id(500)
542 .name("MuxMessage")
543 .dlc(8)
544 .sender("ECM")
545 .add_signal(mux_signal)
546 .add_signal(signal_a);
547
548 let ext_mux = ExtendedMultiplexingBuilder::new()
550 .message_id(500)
551 .signal_name("SignalA")
552 .multiplexer_switch("Mux1")
553 .add_value_range(0, 5)
554 .add_value_range(10, 15);
555
556 let dbc = DbcBuilder::new()
557 .version(version)
558 .nodes(nodes)
559 .add_message(message)
560 .add_extended_multiplexing(ext_mux)
561 .build()
562 .unwrap();
563
564 assert_eq!(dbc.messages().len(), 1);
565 assert_eq!(dbc.extended_multiplexing().len(), 1);
566
567 let ext_mux = &dbc.extended_multiplexing()[0];
568 assert_eq!(ext_mux.message_id(), 500);
569 assert_eq!(ext_mux.signal_name(), "SignalA");
570 assert_eq!(ext_mux.multiplexer_switch(), "Mux1");
571 assert_eq!(ext_mux.value_ranges().len(), 2);
572 assert_eq!(ext_mux.value_ranges()[0], (0, 5));
573 assert_eq!(ext_mux.value_ranges()[1], (10, 15));
574 }
575
576 #[test]
577 fn test_dbc_builder_extended_multiplexing_message_not_found() {
578 let version = VersionBuilder::new().version("1.0");
579 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
580
581 let signal = SignalBuilder::new()
582 .name("RPM")
583 .start_bit(0)
584 .length(16)
585 .byte_order(ByteOrder::BigEndian)
586 .unsigned(true)
587 .factor(1.0)
588 .offset(0.0)
589 .min(0.0)
590 .max(100.0)
591 .receivers(ReceiversBuilder::new().none());
592
593 let message = MessageBuilder::new()
594 .id(256)
595 .name("EngineData")
596 .dlc(8)
597 .sender("ECM")
598 .add_signal(signal);
599
600 let ext_mux = ExtendedMultiplexingBuilder::new()
602 .message_id(999) .signal_name("RPM")
604 .multiplexer_switch("Mux1")
605 .add_value_range(0, 5);
606
607 let result = DbcBuilder::new()
608 .version(version)
609 .nodes(nodes)
610 .add_message(message)
611 .add_extended_multiplexing(ext_mux)
612 .build();
613
614 assert!(result.is_err());
615 }
616
617 #[test]
618 fn test_dbc_builder_extended_multiplexing_signal_not_found() {
619 let version = VersionBuilder::new().version("1.0");
620 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
621
622 let mux_signal = SignalBuilder::new()
623 .name("Mux1")
624 .start_bit(0)
625 .length(8)
626 .byte_order(ByteOrder::BigEndian)
627 .unsigned(true)
628 .factor(1.0)
629 .offset(0.0)
630 .min(0.0)
631 .max(100.0)
632 .receivers(ReceiversBuilder::new().none());
633
634 let message = MessageBuilder::new()
635 .id(256)
636 .name("EngineData")
637 .dlc(8)
638 .sender("ECM")
639 .add_signal(mux_signal);
640
641 let ext_mux = ExtendedMultiplexingBuilder::new()
643 .message_id(256)
644 .signal_name("NonExistent") .multiplexer_switch("Mux1")
646 .add_value_range(0, 5);
647
648 let result = DbcBuilder::new()
649 .version(version)
650 .nodes(nodes)
651 .add_message(message)
652 .add_extended_multiplexing(ext_mux)
653 .build();
654
655 assert!(result.is_err());
656 }
657
658 #[test]
659 fn test_dbc_builder_extended_multiplexing_switch_not_found() {
660 let version = VersionBuilder::new().version("1.0");
661 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
662
663 let signal = SignalBuilder::new()
664 .name("SignalA")
665 .start_bit(0)
666 .length(16)
667 .byte_order(ByteOrder::BigEndian)
668 .unsigned(true)
669 .factor(1.0)
670 .offset(0.0)
671 .min(0.0)
672 .max(100.0)
673 .receivers(ReceiversBuilder::new().none());
674
675 let message = MessageBuilder::new()
676 .id(256)
677 .name("EngineData")
678 .dlc(8)
679 .sender("ECM")
680 .add_signal(signal);
681
682 let ext_mux = ExtendedMultiplexingBuilder::new()
684 .message_id(256)
685 .signal_name("SignalA")
686 .multiplexer_switch("NonExistentMux") .add_value_range(0, 5);
688
689 let result = DbcBuilder::new()
690 .version(version)
691 .nodes(nodes)
692 .add_message(message)
693 .add_extended_multiplexing(ext_mux)
694 .build();
695
696 assert!(result.is_err());
697 }
698
699 #[test]
700 fn test_dbc_builder_extended_multiplexing_invalid_range() {
701 let version = VersionBuilder::new().version("1.0");
702 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
703
704 let mux_signal = SignalBuilder::new()
705 .name("Mux1")
706 .start_bit(0)
707 .length(8)
708 .byte_order(ByteOrder::LittleEndian)
709 .unsigned(true)
710 .factor(1.0)
711 .offset(0.0)
712 .min(0.0)
713 .max(255.0)
714 .receivers(ReceiversBuilder::new().none());
715
716 let signal_a = SignalBuilder::new()
717 .name("SignalA")
718 .start_bit(16)
719 .length(16)
720 .byte_order(ByteOrder::LittleEndian)
721 .unsigned(true)
722 .factor(0.1)
723 .offset(0.0)
724 .min(0.0)
725 .max(100.0)
726 .receivers(ReceiversBuilder::new().none());
727
728 let message = MessageBuilder::new()
729 .id(500)
730 .name("MuxMessage")
731 .dlc(8)
732 .sender("ECM")
733 .add_signal(mux_signal)
734 .add_signal(signal_a);
735
736 let ext_mux = ExtendedMultiplexingBuilder::new()
738 .message_id(500)
739 .signal_name("SignalA")
740 .multiplexer_switch("Mux1")
741 .add_value_range(10, 5); let result = DbcBuilder::new()
744 .version(version)
745 .nodes(nodes)
746 .add_message(message)
747 .add_extended_multiplexing(ext_mux)
748 .build();
749
750 assert!(result.is_err());
751 }
752
753 #[test]
754 fn test_dbc_builder_validate_with_extended_multiplexing() {
755 let version = VersionBuilder::new().version("1.0");
756 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
757
758 let mux_signal = SignalBuilder::new()
759 .name("Mux1")
760 .start_bit(0)
761 .length(8)
762 .byte_order(ByteOrder::LittleEndian)
763 .unsigned(true)
764 .factor(1.0)
765 .offset(0.0)
766 .min(0.0)
767 .max(255.0)
768 .receivers(ReceiversBuilder::new().none());
769
770 let signal_a = SignalBuilder::new()
771 .name("SignalA")
772 .start_bit(16)
773 .length(16)
774 .byte_order(ByteOrder::LittleEndian)
775 .unsigned(true)
776 .factor(0.1)
777 .offset(0.0)
778 .min(0.0)
779 .max(100.0)
780 .receivers(ReceiversBuilder::new().none());
781
782 let message = MessageBuilder::new()
783 .id(500)
784 .name("MuxMessage")
785 .dlc(8)
786 .sender("ECM")
787 .add_signal(mux_signal)
788 .add_signal(signal_a);
789
790 let ext_mux = ExtendedMultiplexingBuilder::new()
791 .message_id(500)
792 .signal_name("SignalA")
793 .multiplexer_switch("Mux1")
794 .add_value_range(0, 5);
795
796 let result = DbcBuilder::new()
797 .version(version)
798 .nodes(nodes)
799 .add_message(message)
800 .add_extended_multiplexing(ext_mux)
801 .validate();
802
803 assert!(result.is_ok());
804 }
805
806 #[test]
807 fn test_dbc_builder_multiple_extended_multiplexing() {
808 let version = VersionBuilder::new().version("1.0");
809 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
810
811 let mux_signal = SignalBuilder::new()
812 .name("Mux1")
813 .start_bit(0)
814 .length(8)
815 .byte_order(ByteOrder::LittleEndian)
816 .unsigned(true)
817 .factor(1.0)
818 .offset(0.0)
819 .min(0.0)
820 .max(255.0)
821 .receivers(ReceiversBuilder::new().none());
822
823 let signal_a = SignalBuilder::new()
824 .name("SignalA")
825 .start_bit(16)
826 .length(8)
827 .byte_order(ByteOrder::LittleEndian)
828 .unsigned(true)
829 .factor(1.0)
830 .offset(0.0)
831 .min(0.0)
832 .max(255.0)
833 .receivers(ReceiversBuilder::new().none());
834
835 let signal_b = SignalBuilder::new()
836 .name("SignalB")
837 .start_bit(24)
838 .length(8)
839 .byte_order(ByteOrder::LittleEndian)
840 .unsigned(true)
841 .factor(1.0)
842 .offset(0.0)
843 .min(0.0)
844 .max(255.0)
845 .receivers(ReceiversBuilder::new().none());
846
847 let message = MessageBuilder::new()
848 .id(500)
849 .name("MuxMessage")
850 .dlc(8)
851 .sender("ECM")
852 .add_signal(mux_signal)
853 .add_signal(signal_a)
854 .add_signal(signal_b);
855
856 let ext_mux_a = ExtendedMultiplexingBuilder::new()
857 .message_id(500)
858 .signal_name("SignalA")
859 .multiplexer_switch("Mux1")
860 .add_value_range(0, 5);
861
862 let ext_mux_b = ExtendedMultiplexingBuilder::new()
863 .message_id(500)
864 .signal_name("SignalB")
865 .multiplexer_switch("Mux1")
866 .add_value_range(10, 15);
867
868 let dbc = DbcBuilder::new()
869 .version(version)
870 .nodes(nodes)
871 .add_message(message)
872 .add_extended_multiplexings(vec![ext_mux_a, ext_mux_b])
873 .build()
874 .unwrap();
875
876 assert_eq!(dbc.extended_multiplexing().len(), 2);
877 assert_eq!(dbc.extended_multiplexing()[0].signal_name(), "SignalA");
878 assert_eq!(dbc.extended_multiplexing()[1].signal_name(), "SignalB");
879 }
880
881 #[test]
882 fn test_dbc_builder_clear_extended_multiplexing() {
883 let version = VersionBuilder::new().version("1.0");
884 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
885
886 let mux_signal = SignalBuilder::new()
887 .name("Mux1")
888 .start_bit(0)
889 .length(8)
890 .byte_order(ByteOrder::LittleEndian)
891 .unsigned(true)
892 .factor(1.0)
893 .offset(0.0)
894 .min(0.0)
895 .max(255.0)
896 .receivers(ReceiversBuilder::new().none());
897
898 let signal_a = SignalBuilder::new()
899 .name("SignalA")
900 .start_bit(16)
901 .length(16)
902 .byte_order(ByteOrder::LittleEndian)
903 .unsigned(true)
904 .factor(0.1)
905 .offset(0.0)
906 .min(0.0)
907 .max(100.0)
908 .receivers(ReceiversBuilder::new().none());
909
910 let message = MessageBuilder::new()
911 .id(500)
912 .name("MuxMessage")
913 .dlc(8)
914 .sender("ECM")
915 .add_signal(mux_signal)
916 .add_signal(signal_a);
917
918 let ext_mux = ExtendedMultiplexingBuilder::new()
919 .message_id(500)
920 .signal_name("SignalA")
921 .multiplexer_switch("Mux1")
922 .add_value_range(0, 5);
923
924 let dbc = DbcBuilder::new()
925 .version(version)
926 .nodes(nodes)
927 .add_message(message)
928 .add_extended_multiplexing(ext_mux)
929 .clear_extended_multiplexing()
930 .build()
931 .unwrap();
932
933 assert_eq!(dbc.extended_multiplexing().len(), 0);
934 }
935
936 #[test]
941 fn test_dbc_builder_with_value_descriptions_and_extended_multiplexing() {
942 let version = VersionBuilder::new().version("1.0");
943 let nodes = NodesBuilder::new().add_nodes(["ECM"]);
944
945 let mux_signal = SignalBuilder::new()
946 .name("Mux1")
947 .start_bit(0)
948 .length(8)
949 .byte_order(ByteOrder::LittleEndian)
950 .unsigned(true)
951 .factor(1.0)
952 .offset(0.0)
953 .min(0.0)
954 .max(255.0)
955 .receivers(ReceiversBuilder::new().none());
956
957 let signal_a = SignalBuilder::new()
958 .name("SignalA")
959 .start_bit(16)
960 .length(8)
961 .byte_order(ByteOrder::LittleEndian)
962 .unsigned(true)
963 .factor(1.0)
964 .offset(0.0)
965 .min(0.0)
966 .max(3.0)
967 .receivers(ReceiversBuilder::new().none());
968
969 let message = MessageBuilder::new()
970 .id(500)
971 .name("MuxMessage")
972 .dlc(8)
973 .sender("ECM")
974 .add_signal(mux_signal)
975 .add_signal(signal_a);
976
977 let value_desc = ValueDescriptionsBuilder::new()
978 .add_entry(0, "Off")
979 .add_entry(1, "Low")
980 .add_entry(2, "Medium")
981 .add_entry(3, "High");
982
983 let ext_mux = ExtendedMultiplexingBuilder::new()
984 .message_id(500)
985 .signal_name("SignalA")
986 .multiplexer_switch("Mux1")
987 .add_value_range(0, 5);
988
989 let dbc = DbcBuilder::new()
990 .version(version)
991 .nodes(nodes)
992 .add_message(message)
993 .add_value_description(500, "SignalA", value_desc)
994 .add_extended_multiplexing(ext_mux)
995 .build()
996 .unwrap();
997
998 let vd = dbc.value_descriptions_for_signal(500, "SignalA").unwrap();
1000 assert_eq!(vd.get(0), Some("Off"));
1001 assert_eq!(vd.get(3), Some("High"));
1002
1003 assert_eq!(dbc.extended_multiplexing().len(), 1);
1005 assert_eq!(dbc.extended_multiplexing()[0].signal_name(), "SignalA");
1006 }
1007}