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