diff --git a/odxtools/multiplexer.py b/odxtools/multiplexer.py index 1d362789..f3f14069 100644 --- a/odxtools/multiplexer.py +++ b/odxtools/multiplexer.py @@ -236,3 +236,38 @@ def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue: decode_state.origin_byte_position = orig_origin return result + + @override + def get_static_bit_length(self) -> int | None: + """ + Returns the static bit length of the multiplexer structure, if determinable. + + If all cases (including the default, if present) have the same static bit length, + the codec length is considered static and is returned. + Otherwise, returns None to indicate that the size is dynamic. + """ + reference_case = self.default_case if self.default_case else self.cases[0] + + case_bit_length: int | None + if reference_case.structure is None: + case_bit_length = 0 + else: + case_bit_length = reference_case.structure.get_static_bit_length() + if case_bit_length is None: + return None + case_size: int | None + for mux_case in self.cases: + if mux_case.structure is None: + case_size = 0 + else: + case_size = mux_case.structure.get_static_bit_length() + if case_size != case_bit_length: + return None # Found a case with a different or unknown size + + switch_key_size = self.switch_key.dop.get_static_bit_length() + if switch_key_size is None: + return None + + return max( + switch_key_size + self.switch_key.byte_position * 8 + + (self.switch_key.bit_position or 0), case_bit_length + self.byte_position * 8) diff --git a/tests/test_diag_data_dictionary_spec.py b/tests/test_diag_data_dictionary_spec.py index 51f64982..0084ef41 100644 --- a/tests/test_diag_data_dictionary_spec.py +++ b/tests/test_diag_data_dictionary_spec.py @@ -276,6 +276,34 @@ def test_initialization(self) -> None: decoded = mux.decode_from_pdu(decode_state) self.assertEqual(decoded, ("default_case", {})) + # mux cases don't have the same structure size + assert mux.default_case is not None + mux.default_case.structure_ref = OdxLinkRef.from_id(mux_case2_struct.odx_id) + ecu._resolve_odxlinks(odxlinks) + self.assertEqual(mux.get_static_bit_length(), None) + # mux cases have the same structure size + mux.cases[0].structure_ref = OdxLinkRef.from_id(mux_case2_struct.odx_id) + ecu._resolve_odxlinks(odxlinks) + self.assertEqual(mux.get_static_bit_length(), 16) + + # zero-case scenario, only default case is considered + cases = mux.cases + mux.cases = NamedItemList() + ecu._resolve_odxlinks(odxlinks) + self.assertEqual(mux.get_static_bit_length(), 16) + + # no default case, but cases have the same structure size + mux.default_case = None + mux.cases = cases + ecu._resolve_odxlinks(odxlinks) + self.assertEqual(mux.get_static_bit_length(), 16) + + # no default case, and each case has no associated structure, only the switch key size is considered + mux.cases[0].structure_ref = None + mux.cases[1].structure_ref = None + ecu._resolve_odxlinks(odxlinks) + self.assertEqual(mux.get_static_bit_length(), 8) + if __name__ == "__main__": unittest.main()