dbc_rs/extended_multiplexing/impls.rs
1use super::{ExtendedMultiplexing, ValueRanges};
2use crate::compat::Name;
3
4impl ExtendedMultiplexing {
5 /// Extended-multiplexing entry from validated parts.
6 pub(crate) fn new(
7 message_id: u32,
8 signal_name: Name,
9 multiplexer_switch: Name,
10 value_ranges: ValueRanges,
11 ) -> Self {
12 Self {
13 message_id,
14 signal_name,
15 multiplexer_switch,
16 value_ranges,
17 }
18 }
19
20 /// Returns the CAN message ID this extended multiplexing entry applies to.
21 ///
22 /// # Examples
23 ///
24 /// ```rust,no_run
25 /// use dbc_rs::Dbc;
26 ///
27 /// let dbc = Dbc::parse(r#"VERSION "1.0"
28 ///
29 /// BU_: ECM
30 ///
31 /// BO_ 500 MuxMessage : 8 ECM
32 /// SG_ Mux1 M : 0|8@1+ (1,0) [0|255] ""
33 /// SG_ Signal_A m0 : 16|16@1+ (0.1,0) [0|100] "unit" *
34 ///
35 /// SG_MUL_VAL_ 500 Signal_A Mux1 5-10 ;
36 /// "#)?;
37 ///
38 /// let entry = dbc.extended_multiplexing_for_message(500).next().unwrap();
39 /// assert_eq!(entry.message_id(), 500);
40 /// # Ok::<(), dbc_rs::Error>(())
41 /// ```
42 #[inline]
43 #[must_use = "return value should be used"]
44 pub fn message_id(&self) -> u32 {
45 self.message_id
46 }
47
48 /// Returns the name of the signal this extended multiplexing entry controls.
49 ///
50 /// The signal will only be decoded when the multiplexer switch value falls
51 /// within one of the defined value ranges.
52 ///
53 /// # Examples
54 ///
55 /// ```rust,no_run
56 /// use dbc_rs::Dbc;
57 ///
58 /// let dbc = Dbc::parse(r#"VERSION "1.0"
59 ///
60 /// BU_: ECM
61 ///
62 /// BO_ 500 MuxMessage : 8 ECM
63 /// SG_ Mux1 M : 0|8@1+ (1,0) [0|255] ""
64 /// SG_ Signal_A m0 : 16|16@1+ (0.1,0) [0|100] "unit" *
65 ///
66 /// SG_MUL_VAL_ 500 Signal_A Mux1 5-10 ;
67 /// "#)?;
68 ///
69 /// let entry = dbc.extended_multiplexing_for_message(500).next().unwrap();
70 /// assert_eq!(entry.signal_name(), "Signal_A");
71 /// # Ok::<(), dbc_rs::Error>(())
72 /// ```
73 #[inline]
74 #[must_use = "return value should be used"]
75 pub fn signal_name(&self) -> &str {
76 self.signal_name.as_str()
77 }
78
79 /// Returns the name of the multiplexer switch signal that controls activation.
80 ///
81 /// The multiplexer switch is a signal marked with `M` in the DBC file. When
82 /// decoding, the switch's current value is compared against the value ranges
83 /// to determine if the controlled signal should be decoded.
84 ///
85 /// # Examples
86 ///
87 /// ```rust,no_run
88 /// use dbc_rs::Dbc;
89 ///
90 /// let dbc = Dbc::parse(r#"VERSION "1.0"
91 ///
92 /// BU_: ECM
93 ///
94 /// BO_ 500 MuxMessage : 8 ECM
95 /// SG_ Mux1 M : 0|8@1+ (1,0) [0|255] ""
96 /// SG_ Signal_A m0 : 16|16@1+ (0.1,0) [0|100] "unit" *
97 ///
98 /// SG_MUL_VAL_ 500 Signal_A Mux1 5-10 ;
99 /// "#)?;
100 ///
101 /// let entry = dbc.extended_multiplexing_for_message(500).next().unwrap();
102 /// assert_eq!(entry.multiplexer_switch(), "Mux1");
103 /// # Ok::<(), dbc_rs::Error>(())
104 /// ```
105 #[inline]
106 #[must_use = "return value should be used"]
107 pub fn multiplexer_switch(&self) -> &str {
108 self.multiplexer_switch.as_str()
109 }
110
111 /// Returns the value ranges that activate the controlled signal.
112 ///
113 /// Each tuple `(min, max)` defines an inclusive range. The signal is decoded
114 /// when the multiplexer switch value falls within **any** of these ranges.
115 ///
116 /// For example, `[(0, 5), (10, 15)]` means the signal is active when the
117 /// switch value is 0-5 OR 10-15.
118 ///
119 /// # Examples
120 ///
121 /// ```rust,no_run
122 /// use dbc_rs::Dbc;
123 ///
124 /// let dbc = Dbc::parse(r#"VERSION "1.0"
125 ///
126 /// BU_: ECM
127 ///
128 /// BO_ 500 MuxMessage : 8 ECM
129 /// SG_ Mux1 M : 0|8@1+ (1,0) [0|255] ""
130 /// SG_ Signal_A m0 : 16|16@1+ (0.1,0) [0|100] "unit" *
131 ///
132 /// SG_MUL_VAL_ 500 Signal_A Mux1 0-5,10-15 ;
133 /// "#)?;
134 ///
135 /// let entry = dbc.extended_multiplexing_for_message(500).next().unwrap();
136 /// let ranges = entry.value_ranges();
137 ///
138 /// // Check if switch value 3 activates the signal
139 /// let switch_value = 3u64;
140 /// let is_active = ranges.iter().any(|(min, max)| switch_value >= *min && switch_value <= *max);
141 /// assert!(is_active);
142 /// # Ok::<(), dbc_rs::Error>(())
143 /// ```
144 #[inline]
145 #[must_use = "return value should be used"]
146 pub fn value_ranges(&self) -> &[(u64, u64)] {
147 self.value_ranges.as_slice()
148 }
149}