1use crate::{
2 AbstractionElement, ArPackage, AutosarAbstractionError, ByteOrder, IdentifiableAbstractionElement,
3 abstraction_element,
4};
5use autosar_data::{AutosarVersion, Element, ElementName, EnumItem};
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11pub struct DataTransformationSet(Element);
12abstraction_element!(DataTransformationSet, DataTransformationSet);
13impl IdentifiableAbstractionElement for DataTransformationSet {}
14
15impl DataTransformationSet {
16 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
18 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
19 let transformation_set = elements.create_named_sub_element(ElementName::DataTransformationSet, name)?;
20
21 Ok(Self(transformation_set))
22 }
23
24 pub fn create_data_transformation(
26 &self,
27 name: &str,
28 transformations: &[&TransformationTechnology],
29 execute_despite_data_unavailability: bool,
30 ) -> Result<DataTransformation, AutosarAbstractionError> {
31 let data_transformations = self
32 .element()
33 .get_or_create_sub_element(ElementName::DataTransformations)?;
34 let transformation = DataTransformation::new(
35 &data_transformations,
36 name,
37 transformations,
38 execute_despite_data_unavailability,
39 )?;
40 Ok(transformation)
41 }
42
43 pub fn data_transformations(&self) -> impl Iterator<Item = DataTransformation> + Send + 'static {
45 self.element()
46 .get_sub_element(ElementName::DataTransformations)
47 .into_iter()
48 .flat_map(|container| container.sub_elements())
49 .filter_map(|elem| elem.try_into().ok())
50 }
51
52 pub fn create_transformation_technology(
54 &self,
55 name: &str,
56 config: &TransformationTechnologyConfig,
57 ) -> Result<TransformationTechnology, AutosarAbstractionError> {
58 let transtechs = self
59 .element()
60 .get_or_create_sub_element(ElementName::TransformationTechnologys)?;
61 TransformationTechnology::new(&transtechs, name, config)
62 }
63
64 pub fn transformation_technologies(&self) -> impl Iterator<Item = TransformationTechnology> + Send + 'static {
66 self.element()
67 .get_sub_element(ElementName::TransformationTechnologys)
68 .into_iter()
69 .flat_map(|container| container.sub_elements())
70 .filter_map(|elem| elem.try_into().ok())
71 }
72}
73
74#[derive(Debug, Clone, PartialEq, Eq, Hash)]
78pub struct DataTransformation(Element);
79abstraction_element!(DataTransformation, DataTransformation);
80impl IdentifiableAbstractionElement for DataTransformation {}
81
82impl DataTransformation {
83 fn new(
85 parent: &Element,
86 name: &str,
87 transformations: &[&TransformationTechnology],
88 execute_despite_data_unavailability: bool,
89 ) -> Result<Self, AutosarAbstractionError> {
90 if transformations.is_empty() {
92 return Err(AutosarAbstractionError::InvalidParameter(
93 "A DataTransformation must contain at least one TransformationTechnology".to_string(),
94 ));
95 }
96
97 for transformation in &transformations[1..] {
99 if transformation.transformer_class() == Some(EnumItem::Serializer) {
100 return Err(AutosarAbstractionError::InvalidParameter(
101 "A DataTransformation may only contain a TransformationTechnology with TransformerClass 'Serializer' at the start of the chain".to_string(),
102 ));
103 }
104 }
105
106 let dts = parent
108 .named_parent()?
109 .and_then(|dts| DataTransformationSet::try_from(dts).ok());
110 if !transformations
111 .iter()
112 .all(|ttech| ttech.data_transformation_set() == dts)
113 {
114 return Err(AutosarAbstractionError::InvalidParameter(
115 "All TransformationTechnologies in a DataTransformation must be part of the same DataTransformationSet"
116 .to_string(),
117 ));
118 }
119
120 if transformations
122 .iter()
123 .any(|ttech| ttech.protocol().as_deref() == Some("E2E"))
124 && !execute_despite_data_unavailability
125 {
126 return Err(AutosarAbstractionError::InvalidParameter(
127 "If a DataTransformation contains an E2E transformation, executeDespiteDataUnavailability must be true"
128 .to_string(),
129 ));
130 }
131
132 let transformation = parent.create_named_sub_element(ElementName::DataTransformation, name)?;
133 transformation
134 .create_sub_element(ElementName::ExecuteDespiteDataUnavailability)?
135 .set_character_data(execute_despite_data_unavailability)?;
136 let chain_refs = transformation.create_sub_element(ElementName::TransformerChainRefs)?;
137 for transformation in transformations {
138 chain_refs
139 .create_sub_element(ElementName::TransformerChainRef)?
140 .set_reference_target(transformation.element())?;
141 }
142
143 Ok(Self(transformation))
144 }
145
146 #[must_use]
148 pub fn data_transformation_set(&self) -> Option<DataTransformationSet> {
149 self.element()
150 .named_parent()
151 .ok()?
152 .and_then(|dts| DataTransformationSet::try_from(dts).ok())
153 }
154
155 pub fn transformation_technologies(&self) -> impl Iterator<Item = TransformationTechnology> + Send + 'static {
174 self.0
175 .get_sub_element(ElementName::TransformerChainRefs)
176 .into_iter()
177 .flat_map(|container| container.sub_elements())
178 .filter_map(|elem| {
179 elem.get_reference_target()
180 .ok()
181 .and_then(|ttech| TransformationTechnology::try_from(ttech).ok())
182 })
183 }
184}
185
186#[derive(Debug, Clone, PartialEq, Eq, Hash)]
190pub struct TransformationTechnology(Element);
191abstraction_element!(TransformationTechnology, TransformationTechnology);
192impl IdentifiableAbstractionElement for TransformationTechnology {}
193
194impl TransformationTechnology {
195 fn new(
197 parent: &Element,
198 name: &str,
199 config: &TransformationTechnologyConfig,
200 ) -> Result<Self, AutosarAbstractionError> {
201 let ttech_elem = parent.create_named_sub_element(ElementName::TransformationTechnology, name)?;
202 let ttech = Self(ttech_elem);
203 ttech.set_config(config)?;
204
205 Ok(ttech)
206 }
207
208 pub fn set_config(&self, config: &TransformationTechnologyConfig) -> Result<(), AutosarAbstractionError> {
210 let ttech = self.element();
211 let version = ttech.min_version()?;
212 let buffer_props = ttech.get_or_create_sub_element(ElementName::BufferProperties)?;
213
214 match config {
215 TransformationTechnologyConfig::Generic(generic_config) => {
216 ttech
217 .get_or_create_sub_element(ElementName::Protocol)?
218 .set_character_data(generic_config.protocol_name.as_str())?;
219 ttech
220 .get_or_create_sub_element(ElementName::Version)?
221 .set_character_data(generic_config.protocol_version.as_str())?;
222 ttech
223 .get_or_create_sub_element(ElementName::TransformerClass)?
224 .set_character_data(EnumItem::Custom)?;
225 buffer_props
226 .get_or_create_sub_element(ElementName::HeaderLength)?
227 .set_character_data(u64::from(generic_config.header_length))?;
228 buffer_props
229 .get_or_create_sub_element(ElementName::InPlace)?
230 .set_character_data(generic_config.in_place)?;
231
232 let _ = ttech.remove_sub_element_kind(ElementName::TransformationDescriptions);
234 let _ = buffer_props.remove_sub_element_kind(ElementName::BufferComputation);
236 let _ = ttech.remove_sub_element_kind(ElementName::NeedsOriginalData);
238 }
239 TransformationTechnologyConfig::Com(com_config) => {
240 ttech
241 .get_or_create_sub_element(ElementName::Protocol)?
242 .set_character_data("COMBased")?;
243 ttech
244 .get_or_create_sub_element(ElementName::Version)?
245 .set_character_data("1")?;
246 ttech
247 .get_or_create_sub_element(ElementName::TransformerClass)?
248 .set_character_data(EnumItem::Serializer)?;
249
250 buffer_props
252 .get_or_create_sub_element(ElementName::HeaderLength)?
253 .set_character_data(0)?;
254 buffer_props
256 .get_or_create_sub_element(ElementName::InPlace)?
257 .set_character_data("false")?;
258
259 if version <= AutosarVersion::Autosar_00049 {
260 let _ = buffer_props.remove_sub_element_kind(ElementName::BufferComputation);
261 let bufcomp_compu = buffer_props
263 .create_sub_element(ElementName::BufferComputation)?
264 .create_sub_element(ElementName::CompuRationalCoeffs)?;
265 let numerator = bufcomp_compu.create_sub_element(ElementName::CompuNumerator)?;
266 numerator
267 .create_sub_element(ElementName::V)?
268 .set_character_data(u64::from(com_config.isignal_ipdu_length))?;
269 numerator.create_sub_element(ElementName::V)?.set_character_data(1)?;
270 bufcomp_compu
271 .create_sub_element(ElementName::CompuDenominator)?
272 .create_sub_element(ElementName::V)?
273 .set_character_data(1)?;
274 }
275
276 let _ = ttech.remove_sub_element_kind(ElementName::TransformationDescriptions);
278 let _ = ttech.remove_sub_element_kind(ElementName::NeedsOriginalData);
280 }
281 TransformationTechnologyConfig::E2E(e2e_config) => {
282 ttech
283 .get_or_create_sub_element(ElementName::Protocol)?
284 .set_character_data("E2E")?;
285 ttech
286 .get_or_create_sub_element(ElementName::Version)?
287 .set_character_data("1.0.0")?;
288 ttech
289 .get_or_create_sub_element(ElementName::TransformerClass)?
290 .set_character_data(EnumItem::Safety)?;
291 if version >= AutosarVersion::Autosar_4_3_0 {
292 ttech
293 .get_or_create_sub_element(ElementName::HasInternalState)?
294 .set_character_data("true")?;
295 }
296 ttech
297 .get_or_create_sub_element(ElementName::NeedsOriginalData)?
298 .set_character_data("false")?;
299
300 let (profile_name, header_length) = match e2e_config.profile {
302 E2EProfile::P01 => ("PROFILE_01", 16),
303 E2EProfile::P02 => ("PROFILE_02", 16),
304 E2EProfile::P04 => ("PROFILE_04", 96),
305 E2EProfile::P04m => ("PROFILE_04m", 128),
306 E2EProfile::P05 => ("PROFILE_05", 24),
307 E2EProfile::P06 => ("PROFILE_06", 40),
308 E2EProfile::P07 => ("PROFILE_07", 160),
309 E2EProfile::P07m => ("PROFILE_07m", 192),
310 E2EProfile::P08 => ("PROFILE_08", 128),
311 E2EProfile::P08m => ("PROFILE_08m", 160),
312 E2EProfile::P11 => ("PROFILE_11", 16),
313 E2EProfile::P22 => ("PROFILE_22", 16),
314 E2EProfile::P44 => ("PROFILE_44", 96),
315 E2EProfile::P44m => ("PROFILE_44m", 128),
316 };
317
318 let real_header_length = if e2e_config.zero_header_length {
321 0u32
322 } else {
323 header_length
324 };
325
326 buffer_props
327 .get_or_create_sub_element(ElementName::HeaderLength)?
328 .set_character_data(u64::from(real_header_length))?;
329 buffer_props
330 .get_or_create_sub_element(ElementName::InPlace)?
331 .set_character_data(e2e_config.transform_in_place)?;
332
333 let trans_desc = ttech.get_or_create_sub_element(ElementName::TransformationDescriptions)?;
334 let _ = trans_desc.remove_sub_element_kind(ElementName::SomeipTransformationDescription);
335 let e2e_desc = trans_desc.get_or_create_sub_element(ElementName::EndToEndTransformationDescription)?;
336
337 e2e_desc
339 .get_or_create_sub_element(ElementName::ProfileName)?
340 .set_character_data(profile_name)?;
341 e2e_desc
342 .get_or_create_sub_element(ElementName::UpperHeaderBitsToShift)?
343 .set_character_data(u64::from(e2e_config.offset))?;
344 e2e_desc
345 .get_or_create_sub_element(ElementName::MaxDeltaCounter)?
346 .set_character_data(u64::from(e2e_config.max_delta_counter))?;
347 e2e_desc
348 .get_or_create_sub_element(ElementName::MaxErrorStateInit)?
349 .set_character_data(u64::from(e2e_config.max_error_state_init))?;
350 e2e_desc
351 .get_or_create_sub_element(ElementName::MaxErrorStateInvalid)?
352 .set_character_data(u64::from(e2e_config.max_error_state_invalid))?;
353 e2e_desc
354 .get_or_create_sub_element(ElementName::MaxErrorStateValid)?
355 .set_character_data(u64::from(e2e_config.max_error_state_valid))?;
356 e2e_desc
357 .get_or_create_sub_element(ElementName::MaxNoNewOrRepeatedData)?
358 .set_character_data(u64::from(e2e_config.max_no_new_or_repeated_data))?;
359 e2e_desc
360 .get_or_create_sub_element(ElementName::MinOkStateInit)?
361 .set_character_data(u64::from(e2e_config.min_ok_state_init))?;
362 e2e_desc
363 .get_or_create_sub_element(ElementName::MinOkStateInvalid)?
364 .set_character_data(u64::from(e2e_config.min_ok_state_invalid))?;
365 e2e_desc
366 .get_or_create_sub_element(ElementName::MinOkStateValid)?
367 .set_character_data(u64::from(e2e_config.min_ok_state_valid))?;
368
369 if version <= AutosarVersion::Autosar_00047 {
371 e2e_desc
373 .get_or_create_sub_element(ElementName::WindowSize)?
374 .set_character_data(u64::from(e2e_config.window_size))?;
375 } else {
376 e2e_desc
378 .get_or_create_sub_element(ElementName::WindowSizeInit)?
379 .set_character_data(u64::from(e2e_config.window_size_init.unwrap_or(e2e_config.window_size)))?;
380 e2e_desc
381 .get_or_create_sub_element(ElementName::WindowSizeInvalid)?
382 .set_character_data(u64::from(
383 e2e_config.window_size_invalid.unwrap_or(e2e_config.window_size),
384 ))?;
385 e2e_desc
386 .get_or_create_sub_element(ElementName::WindowSizeValid)?
387 .set_character_data(u64::from(
388 e2e_config.window_size_valid.unwrap_or(e2e_config.window_size),
389 ))?;
390 }
391
392 if matches!(e2e_config.profile, E2EProfile::P01 | E2EProfile::P11) {
394 let Some(data_id_mode) = e2e_config.data_id_mode else {
396 return Err(AutosarAbstractionError::InvalidParameter(
397 "Data ID mode is required for E2E profiles 01 and 11".to_string(),
398 ));
399 };
400 e2e_desc
401 .get_or_create_sub_element(ElementName::DataIdMode)?
402 .set_character_data::<EnumItem>(data_id_mode.into())?;
403
404 let Some(counter_offset) = e2e_config.counter_offset else {
406 return Err(AutosarAbstractionError::InvalidParameter(
407 "Counter offset is required for E2E profiles 01 and 11".to_string(),
408 ));
409 };
410 e2e_desc
411 .get_or_create_sub_element(ElementName::CounterOffset)?
412 .set_character_data(u64::from(counter_offset))?;
413
414 let Some(crc_offset) = e2e_config.crc_offset else {
416 return Err(AutosarAbstractionError::InvalidParameter(
417 "CRC offset is required for E2E profiles 01 and 11".to_string(),
418 ));
419 };
420 e2e_desc
421 .get_or_create_sub_element(ElementName::CrcOffset)?
422 .set_character_data(u64::from(crc_offset))?;
423
424 if data_id_mode == DataIdMode::Lower12Bit {
426 let Some(data_id_nibble_offset) = e2e_config.data_id_nibble_offset else {
427 return Err(AutosarAbstractionError::InvalidParameter(
428 "Data ID nibble offset is required for E2E profiles 01 and 11 with DataIdMode::Lower12Bit".to_string(),
429 ));
430 };
431 e2e_desc
432 .get_or_create_sub_element(ElementName::DataIdNibbleOffset)?
433 .set_character_data(u64::from(data_id_nibble_offset))?;
434 }
435
436 let _ = e2e_desc.remove_sub_element_kind(ElementName::Offset);
438 } else {
439 e2e_desc
441 .get_or_create_sub_element(ElementName::Offset)?
442 .set_character_data(u64::from(e2e_config.offset))?;
443
444 let _ = e2e_desc.remove_sub_element_kind(ElementName::DataIdMode);
446 let _ = e2e_desc.remove_sub_element_kind(ElementName::CounterOffset);
447 let _ = e2e_desc.remove_sub_element_kind(ElementName::CrcOffset);
448 let _ = e2e_desc.remove_sub_element_kind(ElementName::DataIdNibbleOffset);
449 }
450
451 if let Some(profile_behavior) = e2e_config.profile_behavior {
454 e2e_desc
455 .get_or_create_sub_element(ElementName::ProfileBehavior)?
456 .set_character_data::<EnumItem>(profile_behavior.into())?;
457 }
458
459 if let Some(sync_counter_init) = e2e_config.sync_counter_init {
461 e2e_desc
462 .get_or_create_sub_element(ElementName::SyncCounterInit)?
463 .set_character_data(u64::from(sync_counter_init))?;
464 }
465
466 let _ = buffer_props.remove_sub_element_kind(ElementName::BufferComputation);
468 }
469 TransformationTechnologyConfig::SomeIp(someip_config) => {
470 ttech
471 .get_or_create_sub_element(ElementName::Protocol)?
472 .set_character_data("SOMEIP")?;
473 ttech
474 .get_or_create_sub_element(ElementName::TransformerClass)?
475 .set_character_data(EnumItem::Serializer)?;
476
477 buffer_props
479 .get_or_create_sub_element(ElementName::HeaderLength)?
480 .set_character_data(64)?;
481 buffer_props
483 .get_or_create_sub_element(ElementName::InPlace)?
484 .set_character_data("false")?;
485
486 let trans_desc = ttech.get_or_create_sub_element(ElementName::TransformationDescriptions)?;
487 let _ = trans_desc.remove_sub_element_kind(ElementName::EndToEndTransformationDescription);
488 let someip_desc = trans_desc.get_or_create_sub_element(ElementName::SomeipTransformationDescription)?;
489 someip_desc
490 .get_or_create_sub_element(ElementName::Alignment)?
491 .set_character_data(u64::from(someip_config.alignment))?;
492 someip_desc
493 .get_or_create_sub_element(ElementName::ByteOrder)?
494 .set_character_data::<EnumItem>(someip_config.byte_order.into())?;
495 someip_desc
496 .get_or_create_sub_element(ElementName::InterfaceVersion)?
497 .set_character_data(u64::from(someip_config.interface_version))?;
498
499 ttech
501 .get_or_create_sub_element(ElementName::Version)?
502 .set_character_data("1.0.0")?;
503
504 let _ = buffer_props.remove_sub_element_kind(ElementName::BufferComputation);
506 let _ = ttech.remove_sub_element_kind(ElementName::NeedsOriginalData);
508 }
509 }
510
511 Ok(())
512 }
513
514 #[must_use]
516 pub fn protocol(&self) -> Option<String> {
517 self.element()
518 .get_sub_element(ElementName::Protocol)?
519 .character_data()?
520 .string_value()
521 }
522
523 #[must_use]
525 pub fn transformer_class(&self) -> Option<EnumItem> {
526 self.element()
527 .get_sub_element(ElementName::TransformerClass)?
528 .character_data()?
529 .enum_value()
530 }
531
532 #[must_use]
534 pub fn data_transformation_set(&self) -> Option<DataTransformationSet> {
535 self.element()
536 .named_parent()
537 .ok()?
538 .and_then(|dts| DataTransformationSet::try_from(dts).ok())
539 }
540
541 #[must_use]
543 pub fn config(&self) -> Option<TransformationTechnologyConfig> {
544 let protocol = self
545 .element()
546 .get_sub_element(ElementName::Protocol)?
547 .character_data()?
548 .string_value()?;
549
550 let opt_e2e_desc = self
551 .element()
552 .get_sub_element(ElementName::TransformationDescriptions)
553 .and_then(|tdesc| tdesc.get_sub_element(ElementName::EndToEndTransformationDescription));
554 let opt_someip_desc = self
555 .element()
556 .get_sub_element(ElementName::TransformationDescriptions)
557 .and_then(|tdesc| tdesc.get_sub_element(ElementName::SomeipTransformationDescription));
558
559 if let Some(e2e_desc) = opt_e2e_desc {
560 let profile_name = e2e_desc
562 .get_sub_element(ElementName::ProfileName)?
563 .character_data()?
564 .string_value()?;
565 let profile = match profile_name.as_str() {
566 "PROFILE_01" => E2EProfile::P01,
567 "PROFILE_02" => E2EProfile::P02,
568 "PROFILE_04" => E2EProfile::P04,
569 "PROFILE_04m" => E2EProfile::P04m,
570 "PROFILE_05" => E2EProfile::P05,
571 "PROFILE_06" => E2EProfile::P06,
572 "PROFILE_07" => E2EProfile::P07,
573 "PROFILE_07m" => E2EProfile::P07m,
574 "PROFILE_08" => E2EProfile::P08,
575 "PROFILE_08m" => E2EProfile::P08m,
576 "PROFILE_11" => E2EProfile::P11,
577 "PROFILE_22" => E2EProfile::P22,
578 "PROFILE_44" => E2EProfile::P44,
579 "PROFILE_44m" => E2EProfile::P44m,
580 _ => return None,
581 };
582
583 let buffer_props = self.element().get_sub_element(ElementName::BufferProperties)?;
584 let in_place = buffer_props
585 .get_sub_element(ElementName::InPlace)?
586 .character_data()?
587 .parse_bool()?;
588 let buffer_header_length = buffer_props
589 .get_sub_element(ElementName::HeaderLength)?
590 .character_data()?
591 .parse_integer::<u32>()?;
592
593 let opt_window_size_init = e2e_desc
594 .get_sub_element(ElementName::WindowSizeInit)
595 .and_then(|elem| elem.character_data())
596 .and_then(|cdata| cdata.parse_integer::<u32>());
597 let opt_window_size_invalid = e2e_desc
598 .get_sub_element(ElementName::WindowSizeInvalid)
599 .and_then(|elem| elem.character_data())
600 .and_then(|cdata| cdata.parse_integer::<u32>());
601 let opt_window_size_valid = e2e_desc
602 .get_sub_element(ElementName::WindowSizeValid)
603 .and_then(|elem| elem.character_data())
604 .and_then(|cdata| cdata.parse_integer::<u32>());
605 let opt_window_size = e2e_desc
608 .get_sub_element(ElementName::WindowSize)
609 .and_then(|elem| elem.character_data())
610 .and_then(|cdata| cdata.parse_integer())
611 .or(opt_window_size_init)
612 .or(opt_window_size_invalid)
613 .or(opt_window_size_valid);
614
615 let config = E2ETransformationTechnologyConfig {
616 profile,
617 zero_header_length: buffer_header_length == 0,
618 transform_in_place: in_place,
619 offset: 0,
620 max_delta_counter: e2e_desc
621 .get_sub_element(ElementName::MaxDeltaCounter)?
622 .character_data()?
623 .parse_integer()?,
624 max_error_state_init: e2e_desc
625 .get_sub_element(ElementName::MaxErrorStateInit)?
626 .character_data()?
627 .parse_integer()?,
628 max_error_state_invalid: e2e_desc
629 .get_sub_element(ElementName::MaxErrorStateInvalid)?
630 .character_data()?
631 .parse_integer()?,
632 max_error_state_valid: e2e_desc
633 .get_sub_element(ElementName::MaxErrorStateValid)?
634 .character_data()?
635 .parse_integer()?,
636 max_no_new_or_repeated_data: e2e_desc
637 .get_sub_element(ElementName::MaxNoNewOrRepeatedData)?
638 .character_data()?
639 .parse_integer()?,
640 min_ok_state_init: e2e_desc
641 .get_sub_element(ElementName::MinOkStateInit)?
642 .character_data()?
643 .parse_integer()?,
644 min_ok_state_invalid: e2e_desc
645 .get_sub_element(ElementName::MinOkStateInvalid)?
646 .character_data()?
647 .parse_integer()?,
648 min_ok_state_valid: e2e_desc
649 .get_sub_element(ElementName::MinOkStateValid)?
650 .character_data()?
651 .parse_integer()?,
652 window_size: opt_window_size?,
653 window_size_init: e2e_desc
654 .get_sub_element(ElementName::WindowSizeInit)
655 .and_then(|elem| elem.character_data())
656 .and_then(|cd| cd.parse_integer()),
657 window_size_invalid: e2e_desc
658 .get_sub_element(ElementName::WindowSizeInvalid)
659 .and_then(|elem| elem.character_data())
660 .and_then(|cd| cd.parse_integer()),
661 window_size_valid: e2e_desc
662 .get_sub_element(ElementName::WindowSizeValid)
663 .and_then(|elem| elem.character_data())
664 .and_then(|cd| cd.parse_integer()),
665 profile_behavior: e2e_desc
666 .get_sub_element(ElementName::ProfileBehavior)
667 .and_then(|elem| elem.character_data())
668 .and_then(|cd| cd.enum_value())
669 .and_then(|enumitem| enumitem.try_into().ok()),
670 sync_counter_init: e2e_desc
671 .get_sub_element(ElementName::SyncCounterInit)
672 .and_then(|elem| elem.character_data())
673 .and_then(|cd| cd.parse_integer()),
674 data_id_mode: e2e_desc
675 .get_sub_element(ElementName::DataIdMode)
676 .and_then(|elem| elem.character_data())
677 .and_then(|cd| cd.enum_value())
678 .and_then(|enumitem| enumitem.try_into().ok()),
679 data_id_nibble_offset: e2e_desc
680 .get_sub_element(ElementName::DataIdNibbleOffset)
681 .and_then(|elem| elem.character_data())
682 .and_then(|cd| cd.parse_integer()),
683 crc_offset: e2e_desc
684 .get_sub_element(ElementName::CrcOffset)
685 .and_then(|elem| elem.character_data())
686 .and_then(|cd| cd.parse_integer()),
687 counter_offset: e2e_desc
688 .get_sub_element(ElementName::CounterOffset)
689 .and_then(|elem| elem.character_data())
690 .and_then(|cd| cd.parse_integer()),
691 };
692
693 Some(TransformationTechnologyConfig::E2E(config))
694 } else if let Some(someip_desc) = opt_someip_desc {
695 let someip_config = SomeIpTransformationTechnologyConfig {
697 alignment: someip_desc
698 .get_sub_element(ElementName::Alignment)?
699 .character_data()?
700 .parse_integer()?,
701 byte_order: someip_desc
702 .get_sub_element(ElementName::ByteOrder)?
703 .character_data()?
704 .enum_value()
705 .and_then(|enumitem| enumitem.try_into().ok())?,
706 interface_version: someip_desc
707 .get_sub_element(ElementName::InterfaceVersion)?
708 .character_data()?
709 .parse_integer()?,
710 };
711 Some(TransformationTechnologyConfig::SomeIp(someip_config))
712 } else if protocol == "COMBased" || protocol == "ComBased" {
713 let com_config = ComTransformationTechnologyConfig {
715 isignal_ipdu_length: self
716 .element()
717 .get_sub_element(ElementName::BufferProperties)?
718 .get_sub_element(ElementName::BufferComputation)?
719 .get_sub_element(ElementName::CompuRationalCoeffs)?
720 .get_sub_element(ElementName::CompuNumerator)?
721 .get_sub_element(ElementName::V)?
722 .character_data()?
723 .parse_integer()?,
724 };
725 Some(TransformationTechnologyConfig::Com(com_config))
726 } else {
727 let buffer_props = self.element().get_sub_element(ElementName::BufferProperties)?;
729 let in_place = buffer_props
730 .get_sub_element(ElementName::InPlace)?
731 .character_data()?
732 .parse_bool()?;
733
734 let generic_config = GenericTransformationTechnologyConfig {
735 protocol_name: self
736 .element()
737 .get_sub_element(ElementName::Protocol)?
738 .character_data()?
739 .string_value()?,
740 protocol_version: self
741 .element()
742 .get_sub_element(ElementName::Version)?
743 .character_data()?
744 .string_value()?,
745 header_length: buffer_props
746 .get_sub_element(ElementName::HeaderLength)?
747 .character_data()?
748 .parse_integer()?,
749 in_place,
750 };
751 Some(TransformationTechnologyConfig::Generic(generic_config))
752 }
753 }
754}
755
756#[derive(Debug, Clone, PartialEq, Eq)]
760pub enum TransformationTechnologyConfig {
761 Generic(GenericTransformationTechnologyConfig),
763 Com(ComTransformationTechnologyConfig),
765 E2E(E2ETransformationTechnologyConfig),
767 SomeIp(SomeIpTransformationTechnologyConfig),
769}
770
771#[derive(Debug, Clone, PartialEq, Eq)]
776pub struct GenericTransformationTechnologyConfig {
777 pub protocol_name: String,
779 pub protocol_version: String,
781 pub header_length: u32,
783 pub in_place: bool,
785}
786
787#[derive(Debug, Clone, PartialEq, Eq)]
791pub struct ComTransformationTechnologyConfig {
792 pub isignal_ipdu_length: u32,
795}
796
797#[derive(Debug, Clone, PartialEq, Eq)]
801pub struct E2ETransformationTechnologyConfig {
802 pub profile: E2EProfile,
804 pub zero_header_length: bool,
808 pub transform_in_place: bool,
810 pub offset: u32,
813 pub max_delta_counter: u32,
815 pub max_error_state_init: u32,
817 pub max_error_state_invalid: u32,
819 pub max_error_state_valid: u32,
821 pub max_no_new_or_repeated_data: u32,
823 pub min_ok_state_init: u32,
825 pub min_ok_state_invalid: u32,
827 pub min_ok_state_valid: u32,
829 pub window_size: u32,
833 pub window_size_init: Option<u32>,
835 pub window_size_invalid: Option<u32>,
837 pub window_size_valid: Option<u32>,
839 pub profile_behavior: Option<E2EProfileBehavior>,
841 pub sync_counter_init: Option<u32>,
843 pub data_id_mode: Option<DataIdMode>,
845 pub data_id_nibble_offset: Option<u32>,
847 pub crc_offset: Option<u32>,
849 pub counter_offset: Option<u32>,
851}
852
853#[derive(Debug, Clone, PartialEq, Eq)]
857pub struct SomeIpTransformationTechnologyConfig {
858 pub alignment: u32,
860 pub byte_order: ByteOrder,
862 pub interface_version: u32,
864}
865
866#[derive(Debug, Clone, Copy, PartialEq, Eq)]
870pub enum E2EProfile {
871 P01,
873 P02,
875 P04,
877 P04m,
879 P05,
881 P06,
883 P07,
885 P07m,
887 P08,
889 P08m,
891 P11,
893 P22,
895 P44,
897 P44m,
899}
900
901#[derive(Debug, Clone, Copy, PartialEq, Eq)]
905pub enum E2EProfileBehavior {
906 PreR4_2,
908 R4_2,
910}
911
912impl From<E2EProfileBehavior> for EnumItem {
913 fn from(e2e_profile_behavior: E2EProfileBehavior) -> EnumItem {
914 match e2e_profile_behavior {
915 E2EProfileBehavior::PreR4_2 => EnumItem::PreR4_2,
916 E2EProfileBehavior::R4_2 => EnumItem::R4_2,
917 }
918 }
919}
920
921impl TryFrom<EnumItem> for E2EProfileBehavior {
922 type Error = AutosarAbstractionError;
923
924 fn try_from(value: EnumItem) -> Result<E2EProfileBehavior, AutosarAbstractionError> {
925 match value {
926 EnumItem::PreR4_2 => Ok(E2EProfileBehavior::PreR4_2),
927 EnumItem::R4_2 => Ok(E2EProfileBehavior::R4_2),
928 _ => Err(AutosarAbstractionError::ValueConversionError {
929 value: value.to_string(),
930 dest: "E2EProfileBehavior".to_string(),
931 }),
932 }
933 }
934}
935
936#[derive(Debug, Clone, Copy, PartialEq, Eq)]
940pub enum DataIdMode {
941 All16Bit,
943 Alternating8Bit,
945 Lower12Bit,
947 Lower8Bit,
949}
950
951impl From<DataIdMode> for EnumItem {
952 fn from(data_id_mode: DataIdMode) -> EnumItem {
953 match data_id_mode {
954 DataIdMode::All16Bit => EnumItem::All16Bit,
955 DataIdMode::Alternating8Bit => EnumItem::Alternating8Bit,
956 DataIdMode::Lower12Bit => EnumItem::Lower12Bit,
957 DataIdMode::Lower8Bit => EnumItem::Lower8Bit,
958 }
959 }
960}
961
962impl TryFrom<EnumItem> for DataIdMode {
963 type Error = AutosarAbstractionError;
964
965 fn try_from(value: EnumItem) -> Result<DataIdMode, AutosarAbstractionError> {
966 match value {
967 EnumItem::All16Bit => Ok(DataIdMode::All16Bit),
968 EnumItem::Alternating8Bit => Ok(DataIdMode::Alternating8Bit),
969 EnumItem::Lower12Bit => Ok(DataIdMode::Lower12Bit),
970 EnumItem::Lower8Bit => Ok(DataIdMode::Lower8Bit),
971 _ => Err(AutosarAbstractionError::ValueConversionError {
972 value: value.to_string(),
973 dest: "DataIdMode".to_string(),
974 }),
975 }
976 }
977}
978
979#[derive(Debug, Clone, Copy, PartialEq, Eq)]
983pub enum SomeIpMessageType {
984 Notification,
986 Request,
988 RequestNoReturn,
990 Response,
992}
993
994impl From<SomeIpMessageType> for EnumItem {
995 fn from(someip_msg_type: SomeIpMessageType) -> EnumItem {
996 match someip_msg_type {
997 SomeIpMessageType::Notification => EnumItem::Notification,
998 SomeIpMessageType::Request => EnumItem::Request,
999 SomeIpMessageType::RequestNoReturn => EnumItem::RequestNoReturn,
1000 SomeIpMessageType::Response => EnumItem::Response,
1001 }
1002 }
1003}
1004
1005impl TryFrom<EnumItem> for SomeIpMessageType {
1006 type Error = AutosarAbstractionError;
1007
1008 fn try_from(value: EnumItem) -> Result<SomeIpMessageType, AutosarAbstractionError> {
1009 match value {
1010 EnumItem::Notification => Ok(SomeIpMessageType::Notification),
1011 EnumItem::Request => Ok(SomeIpMessageType::Request),
1012 EnumItem::RequestNoReturn => Ok(SomeIpMessageType::RequestNoReturn),
1013 EnumItem::Response => Ok(SomeIpMessageType::Response),
1014 _ => Err(AutosarAbstractionError::ValueConversionError {
1015 value: value.to_string(),
1016 dest: "SomeIpMessageType".to_string(),
1017 }),
1018 }
1019 }
1020}
1021
1022#[derive(Debug, Clone, PartialEq, Eq)]
1026pub struct EndToEndTransformationISignalProps(Element);
1027abstraction_element!(EndToEndTransformationISignalProps, EndToEndTransformationISignalProps);
1028
1029impl EndToEndTransformationISignalProps {
1030 pub(crate) fn new(
1031 parent_element: Element,
1032 transformer: &TransformationTechnology,
1033 ) -> Result<Self, AutosarAbstractionError> {
1034 if transformer.protocol().as_deref() != Some("E2E") {
1035 return Err(AutosarAbstractionError::InvalidParameter(
1036 "EndToEndTransformationISignalProps must reference a E2E transformer".to_string(),
1037 ));
1038 }
1039 let e2e_props_elem = parent_element.create_sub_element(ElementName::EndToEndTransformationISignalProps)?;
1040
1041 let e2e_props = Self(e2e_props_elem);
1042 e2e_props.set_transformer(transformer)?;
1043
1044 Ok(e2e_props)
1045 }
1046
1047 fn inner_element(&self) -> Option<Element> {
1048 self.0
1049 .get_sub_element(ElementName::EndToEndTransformationISignalPropsVariants)?
1050 .get_sub_element(ElementName::EndToEndTransformationISignalPropsConditional)
1051 }
1052
1053 fn create_inner_element(&self) -> Result<Element, AutosarAbstractionError> {
1054 let e2e_props_elem = self
1055 .element()
1056 .get_or_create_sub_element(ElementName::EndToEndTransformationISignalPropsVariants)?
1057 .get_or_create_sub_element(ElementName::EndToEndTransformationISignalPropsConditional)?;
1058 Ok(e2e_props_elem)
1059 }
1060
1061 pub fn set_transformer(&self, transformer: &TransformationTechnology) -> Result<(), AutosarAbstractionError> {
1063 if transformer.protocol().as_deref() != Some("E2E") {
1064 return Err(AutosarAbstractionError::InvalidParameter(
1065 "EndToEndTransformationISignalProps must reference a E2E transformer".to_string(),
1066 ));
1067 }
1068 self.create_inner_element()?
1069 .get_or_create_sub_element(ElementName::TransformerRef)?
1070 .set_reference_target(transformer.element())?;
1071 Ok(())
1072 }
1073
1074 #[must_use]
1076 pub fn transformer(&self) -> Option<TransformationTechnology> {
1077 let t_elem = self
1078 .inner_element()?
1079 .get_sub_element(ElementName::TransformerRef)?
1080 .get_reference_target()
1081 .ok()?;
1082 TransformationTechnology::try_from(t_elem).ok()
1083 }
1084
1085 pub fn set_data_ids(&self, data_ids: &[u32]) -> Result<(), AutosarAbstractionError> {
1087 if data_ids.is_empty() {
1088 let _ = self
1089 .inner_element()
1090 .and_then(|inner| inner.remove_sub_element_kind(ElementName::DataIds).ok());
1091 } else {
1092 let data_ids_elem = self.create_inner_element()?.create_sub_element(ElementName::DataIds)?;
1093 for data_id in data_ids {
1094 data_ids_elem
1095 .create_sub_element(ElementName::DataId)?
1096 .set_character_data(u64::from(*data_id))?;
1097 }
1098 }
1099 Ok(())
1100 }
1101
1102 #[must_use]
1104 pub fn data_ids(&self) -> Vec<u32> {
1105 self.inner_element()
1106 .and_then(|inner_elem| inner_elem.get_sub_element(ElementName::DataIds))
1107 .map(|elem| {
1108 elem.sub_elements()
1109 .filter_map(|elem| elem.character_data().and_then(|cdata| cdata.parse_integer()))
1110 .collect()
1111 })
1112 .unwrap_or_default()
1113 }
1114
1115 pub fn set_data_length(&self, data_length: Option<u32>) -> Result<(), AutosarAbstractionError> {
1117 if let Some(data_length) = data_length {
1118 self.create_inner_element()?
1119 .get_or_create_sub_element(ElementName::DataLength)?
1120 .set_character_data(data_length.to_string())?;
1121 } else {
1122 let _ = self
1123 .inner_element()
1124 .and_then(|inner| inner.remove_sub_element_kind(ElementName::DataLength).ok());
1125 }
1126 Ok(())
1127 }
1128
1129 #[must_use]
1131 pub fn data_length(&self) -> Option<u32> {
1132 self.inner_element()?
1133 .get_sub_element(ElementName::DataLength)?
1134 .character_data()?
1135 .parse_integer()
1136 }
1137
1138 pub fn set_max_data_length(&self, max_data_length: Option<u32>) -> Result<(), AutosarAbstractionError> {
1140 if let Some(max_data_length) = max_data_length {
1141 self.create_inner_element()?
1142 .get_or_create_sub_element(ElementName::MaxDataLength)?
1143 .set_character_data(max_data_length.to_string())?;
1144 } else {
1145 let _ = self
1146 .inner_element()
1147 .and_then(|inner| inner.remove_sub_element_kind(ElementName::MaxDataLength).ok());
1148 }
1149 Ok(())
1150 }
1151
1152 #[must_use]
1154 pub fn max_data_length(&self) -> Option<u32> {
1155 self.inner_element()?
1156 .get_sub_element(ElementName::MaxDataLength)
1157 .and_then(|elem| elem.character_data())
1158 .and_then(|cdata| cdata.parse_integer())
1159 }
1160
1161 pub fn set_min_data_length(&self, min_data_length: Option<u32>) -> Result<(), AutosarAbstractionError> {
1163 if let Some(min_data_length) = min_data_length {
1164 self.create_inner_element()?
1165 .get_or_create_sub_element(ElementName::MinDataLength)?
1166 .set_character_data(min_data_length.to_string())?;
1167 } else {
1168 let _ = self
1169 .inner_element()
1170 .and_then(|inner| inner.remove_sub_element_kind(ElementName::MinDataLength).ok());
1171 }
1172 Ok(())
1173 }
1174
1175 #[must_use]
1177 pub fn min_data_length(&self) -> Option<u32> {
1178 self.inner_element()?
1179 .get_sub_element(ElementName::MinDataLength)?
1180 .character_data()?
1181 .parse_integer()
1182 }
1183
1184 pub fn set_source_id(&self, source_id: Option<u32>) -> Result<(), AutosarAbstractionError> {
1186 if let Some(source_id) = source_id {
1187 self.create_inner_element()?
1188 .get_or_create_sub_element(ElementName::SourceId)?
1189 .set_character_data(source_id.to_string())?;
1190 } else {
1191 let _ = self
1192 .inner_element()
1193 .and_then(|inner| inner.remove_sub_element_kind(ElementName::SourceId).ok());
1194 }
1195 Ok(())
1196 }
1197
1198 #[must_use]
1200 pub fn source_id(&self) -> Option<u32> {
1201 self.inner_element()?
1202 .get_sub_element(ElementName::SourceId)?
1203 .character_data()?
1204 .parse_integer()
1205 }
1206}
1207
1208#[derive(Debug, Clone, PartialEq, Eq)]
1212pub struct SomeIpTransformationISignalProps(Element);
1213abstraction_element!(SomeIpTransformationISignalProps, SomeipTransformationISignalProps);
1214
1215impl SomeIpTransformationISignalProps {
1216 pub(crate) fn new(
1217 parent_element: Element,
1218 transformer: &TransformationTechnology,
1219 ) -> Result<Self, AutosarAbstractionError> {
1220 if transformer.protocol().as_deref() != Some("SOMEIP") {
1221 return Err(AutosarAbstractionError::InvalidParameter(
1222 "SOMEIPTransformationISignalProps must reference a SOMEIP transformer".to_string(),
1223 ));
1224 }
1225 let someip_props_elem = parent_element.create_sub_element(ElementName::SomeipTransformationISignalProps)?;
1226 let someip_props = Self(someip_props_elem);
1227 someip_props.set_transformer(transformer)?;
1228
1229 Ok(someip_props)
1230 }
1231
1232 fn inner_element(&self) -> Option<Element> {
1233 self.0
1234 .get_sub_element(ElementName::SomeipTransformationISignalPropsVariants)?
1235 .get_sub_element(ElementName::SomeipTransformationISignalPropsConditional)
1236 }
1237
1238 fn create_inner_element(&self) -> Result<Element, AutosarAbstractionError> {
1239 let e2e_props_elem = self
1240 .element()
1241 .get_or_create_sub_element(ElementName::SomeipTransformationISignalPropsVariants)?
1242 .get_or_create_sub_element(ElementName::SomeipTransformationISignalPropsConditional)?;
1243 Ok(e2e_props_elem)
1244 }
1245
1246 pub fn set_transformer(&self, transformer: &TransformationTechnology) -> Result<(), AutosarAbstractionError> {
1248 if transformer.protocol().as_deref() != Some("SOMEIP") {
1249 return Err(AutosarAbstractionError::InvalidParameter(
1250 "SOMEIPTransformationISignalProps must reference a SOMEIP transformer".to_string(),
1251 ));
1252 }
1253 self.create_inner_element()?
1254 .get_or_create_sub_element(ElementName::TransformerRef)?
1255 .set_reference_target(transformer.element())?;
1256 Ok(())
1257 }
1258
1259 #[must_use]
1261 pub fn transformer(&self) -> Option<TransformationTechnology> {
1262 let t_elem = self
1263 .inner_element()?
1264 .get_sub_element(ElementName::TransformerRef)?
1265 .get_reference_target()
1266 .ok()?;
1267 TransformationTechnology::try_from(t_elem).ok()
1268 }
1269
1270 pub fn set_legacy_strings(&self, legacy_strings: Option<bool>) -> Result<(), AutosarAbstractionError> {
1272 if let Some(legacy_strings) = legacy_strings {
1273 self.create_inner_element()?
1274 .get_or_create_sub_element(ElementName::ImplementsLegacyStringSerialization)?
1275 .set_character_data(legacy_strings.to_string())?;
1276 } else {
1277 let _ = self.inner_element().and_then(|inner| {
1278 inner
1279 .remove_sub_element_kind(ElementName::ImplementsLegacyStringSerialization)
1280 .ok()
1281 });
1282 }
1283 Ok(())
1284 }
1285
1286 #[must_use]
1288 pub fn legacy_strings(&self) -> Option<bool> {
1289 self.inner_element()?
1290 .get_sub_element(ElementName::ImplementsLegacyStringSerialization)?
1291 .character_data()?
1292 .parse_bool()
1293 }
1294
1295 pub fn set_interface_version(&self, interface_version: Option<u32>) -> Result<(), AutosarAbstractionError> {
1297 if let Some(interface_version) = interface_version {
1298 self.create_inner_element()?
1299 .get_or_create_sub_element(ElementName::InterfaceVersion)?
1300 .set_character_data(interface_version.to_string())?;
1301 } else {
1302 let _ = self
1303 .inner_element()
1304 .and_then(|inner| inner.remove_sub_element_kind(ElementName::InterfaceVersion).ok());
1305 }
1306 Ok(())
1307 }
1308
1309 #[must_use]
1311 pub fn interface_version(&self) -> Option<u32> {
1312 self.inner_element()?
1313 .get_sub_element(ElementName::InterfaceVersion)?
1314 .character_data()?
1315 .parse_integer()
1316 }
1317
1318 pub fn set_dynamic_length(&self, dynamic_length: Option<bool>) -> Result<(), AutosarAbstractionError> {
1320 if let Some(dynamic_length) = dynamic_length {
1321 self.create_inner_element()?
1322 .get_or_create_sub_element(ElementName::IsDynamicLengthFieldSize)?
1323 .set_character_data(dynamic_length.to_string())?;
1324 } else {
1325 let _ = self.inner_element().and_then(|inner| {
1326 inner
1327 .remove_sub_element_kind(ElementName::IsDynamicLengthFieldSize)
1328 .ok()
1329 });
1330 }
1331 Ok(())
1332 }
1333
1334 #[must_use]
1336 pub fn dynamic_length(&self) -> Option<bool> {
1337 self.inner_element()?
1338 .get_sub_element(ElementName::IsDynamicLengthFieldSize)?
1339 .character_data()?
1340 .parse_bool()
1341 }
1342
1343 pub fn set_message_type(&self, message_type: Option<SomeIpMessageType>) -> Result<(), AutosarAbstractionError> {
1345 if let Some(message_type) = message_type {
1346 self.create_inner_element()?
1347 .get_or_create_sub_element(ElementName::MessageType)?
1348 .set_character_data::<EnumItem>(message_type.into())?;
1349 } else {
1350 let _ = self
1351 .inner_element()
1352 .and_then(|inner| inner.remove_sub_element_kind(ElementName::MessageType).ok());
1353 }
1354 Ok(())
1355 }
1356
1357 #[must_use]
1359 pub fn message_type(&self) -> Option<SomeIpMessageType> {
1360 self.inner_element()?
1361 .get_sub_element(ElementName::MessageType)?
1362 .character_data()?
1363 .enum_value()?
1364 .try_into()
1365 .ok()
1366 }
1367
1368 pub fn set_size_of_array_length(&self, size_of_array_length: Option<u32>) -> Result<(), AutosarAbstractionError> {
1370 if let Some(size_of_array_length) = size_of_array_length {
1371 self.create_inner_element()?
1372 .get_or_create_sub_element(ElementName::SizeOfArrayLengthFields)?
1373 .set_character_data(size_of_array_length.to_string())?;
1374 } else {
1375 let _ = self
1376 .inner_element()
1377 .and_then(|inner| inner.remove_sub_element_kind(ElementName::SizeOfArrayLengthFields).ok());
1378 }
1379 Ok(())
1380 }
1381
1382 #[must_use]
1384 pub fn size_of_array_length(&self) -> Option<u32> {
1385 self.inner_element()?
1386 .get_sub_element(ElementName::SizeOfArrayLengthFields)?
1387 .character_data()?
1388 .parse_integer()
1389 }
1390
1391 pub fn set_size_of_string_length(&self, size_of_string_length: Option<u32>) -> Result<(), AutosarAbstractionError> {
1393 if let Some(size_of_string_length) = size_of_string_length {
1394 self.create_inner_element()?
1395 .get_or_create_sub_element(ElementName::SizeOfStringLengthFields)?
1396 .set_character_data(size_of_string_length.to_string())?;
1397 } else {
1398 let _ = self.inner_element().and_then(|inner| {
1399 inner
1400 .remove_sub_element_kind(ElementName::SizeOfStringLengthFields)
1401 .ok()
1402 });
1403 }
1404 Ok(())
1405 }
1406
1407 #[must_use]
1409 pub fn size_of_string_length(&self) -> Option<u32> {
1410 self.inner_element()?
1411 .get_sub_element(ElementName::SizeOfStringLengthFields)?
1412 .character_data()?
1413 .parse_integer()
1414 }
1415
1416 pub fn set_size_of_struct_length(&self, size_of_struct_length: Option<u32>) -> Result<(), AutosarAbstractionError> {
1418 if let Some(size_of_struct_length) = size_of_struct_length {
1419 self.create_inner_element()?
1420 .get_or_create_sub_element(ElementName::SizeOfStructLengthFields)?
1421 .set_character_data(size_of_struct_length.to_string())?;
1422 } else {
1423 let _ = self.inner_element().and_then(|inner| {
1424 inner
1425 .remove_sub_element_kind(ElementName::SizeOfStructLengthFields)
1426 .ok()
1427 });
1428 }
1429 Ok(())
1430 }
1431
1432 #[must_use]
1434 pub fn size_of_struct_length(&self) -> Option<u32> {
1435 self.inner_element()?
1436 .get_sub_element(ElementName::SizeOfStructLengthFields)?
1437 .character_data()?
1438 .parse_integer()
1439 }
1440
1441 pub fn set_size_of_union_length(&self, size_of_union_length: Option<u32>) -> Result<(), AutosarAbstractionError> {
1443 if let Some(size_of_union_length) = size_of_union_length {
1444 self.create_inner_element()?
1445 .get_or_create_sub_element(ElementName::SizeOfUnionLengthFields)?
1446 .set_character_data(size_of_union_length.to_string())?;
1447 } else {
1448 let _ = self
1449 .inner_element()
1450 .and_then(|inner| inner.remove_sub_element_kind(ElementName::SizeOfUnionLengthFields).ok());
1451 }
1452 Ok(())
1453 }
1454
1455 #[must_use]
1457 pub fn size_of_union_length(&self) -> Option<u32> {
1458 self.inner_element()?
1459 .get_sub_element(ElementName::SizeOfUnionLengthFields)?
1460 .character_data()?
1461 .parse_integer()
1462 }
1463}
1464
1465#[derive(Debug, Clone, PartialEq, Eq)]
1469pub enum TransformationISignalProps {
1470 E2E(EndToEndTransformationISignalProps),
1472 SomeIp(SomeIpTransformationISignalProps),
1474}
1475
1476impl AbstractionElement for TransformationISignalProps {
1477 fn element(&self) -> &Element {
1478 match self {
1479 TransformationISignalProps::E2E(e2e_props) => e2e_props.element(),
1480 TransformationISignalProps::SomeIp(someip_props) => someip_props.element(),
1481 }
1482 }
1483}
1484
1485impl TryFrom<Element> for TransformationISignalProps {
1486 type Error = AutosarAbstractionError;
1487
1488 fn try_from(element: Element) -> Result<Self, Self::Error> {
1489 match element.element_name() {
1490 ElementName::EndToEndTransformationISignalProps => {
1491 EndToEndTransformationISignalProps::try_from(element).map(TransformationISignalProps::E2E)
1492 }
1493 ElementName::SomeipTransformationISignalProps => {
1494 SomeIpTransformationISignalProps::try_from(element).map(TransformationISignalProps::SomeIp)
1495 }
1496 _ => Err(AutosarAbstractionError::ConversionError {
1497 element,
1498 dest: "TransformationISignalProps".to_string(),
1499 }),
1500 }
1501 }
1502}
1503
1504#[cfg(test)]
1507mod test {
1508 use super::*;
1509 use crate::{
1510 AutosarModelAbstraction,
1511 communication::{ISignal, SystemSignal},
1512 datatype::{BaseTypeEncoding, SwBaseType},
1513 };
1514
1515 #[test]
1516 fn transformation_technologies() {
1517 let versions = vec![
1520 AutosarVersion::Autosar_4_2_1,
1521 AutosarVersion::Autosar_4_3_0,
1522 AutosarVersion::Autosar_00044,
1523 AutosarVersion::Autosar_00046,
1524 AutosarVersion::Autosar_00047,
1525 AutosarVersion::Autosar_00048,
1526 AutosarVersion::Autosar_00049,
1527 AutosarVersion::Autosar_00050,
1528 AutosarVersion::Autosar_00051,
1529 AutosarVersion::Autosar_00052,
1530 ];
1531 for version in versions {
1532 create_transformation_technologies(version);
1533 }
1534 }
1535
1536 fn create_transformation_technologies(file_version: AutosarVersion) {
1537 let model = AutosarModelAbstraction::create("test", file_version);
1538 let package = model.get_or_create_package("/package").unwrap();
1539 let dts = DataTransformationSet::new("test", &package).unwrap();
1540
1541 let config = TransformationTechnologyConfig::Generic(GenericTransformationTechnologyConfig {
1543 protocol_name: "test".to_string(),
1544 protocol_version: "1.0.0".to_string(),
1545 header_length: 16,
1546 in_place: true,
1547 });
1548 let ttech = dts.create_transformation_technology("generic", &config).unwrap();
1549 let config2 = ttech.config().unwrap();
1550 assert_eq!(config, config2);
1551
1552 let config = TransformationTechnologyConfig::Com(ComTransformationTechnologyConfig { isignal_ipdu_length: 8 });
1554 dts.create_transformation_technology("com", &config).unwrap();
1555
1556 for profile in &[
1558 E2EProfile::P01,
1559 E2EProfile::P02,
1560 E2EProfile::P04,
1561 E2EProfile::P04m,
1562 E2EProfile::P05,
1563 E2EProfile::P06,
1564 E2EProfile::P07,
1565 E2EProfile::P07m,
1566 E2EProfile::P08,
1567 E2EProfile::P08m,
1568 E2EProfile::P11,
1569 E2EProfile::P22,
1570 E2EProfile::P44,
1571 E2EProfile::P44m,
1572 ] {
1573 let e2e_config = E2ETransformationTechnologyConfig {
1574 profile: *profile,
1575 zero_header_length: false,
1576 transform_in_place: true,
1577 offset: 0,
1578 max_delta_counter: 0,
1579 max_error_state_init: 0,
1580 max_error_state_invalid: 0,
1581 max_error_state_valid: 0,
1582 max_no_new_or_repeated_data: 0,
1583 min_ok_state_init: 0,
1584 min_ok_state_invalid: 0,
1585 min_ok_state_valid: 0,
1586 window_size: 10,
1587 window_size_init: Some(11),
1588 window_size_invalid: Some(12),
1589 window_size_valid: Some(13),
1590 profile_behavior: Some(E2EProfileBehavior::R4_2),
1591 sync_counter_init: Some(0),
1592 data_id_mode: Some(DataIdMode::Lower12Bit),
1593 data_id_nibble_offset: Some(1),
1594 crc_offset: Some(2),
1595 counter_offset: Some(3),
1596 };
1597 let config = TransformationTechnologyConfig::E2E(e2e_config.clone());
1598 let ttech = dts
1599 .create_transformation_technology(&format!("{profile:?}"), &config)
1600 .unwrap();
1601 let config2 = ttech.config().unwrap();
1602 let TransformationTechnologyConfig::E2E(e2e_config2) = config2 else {
1603 panic!("Expected E2E transformation technology");
1604 };
1605 assert_eq!(e2e_config.profile, e2e_config2.profile);
1606 assert_eq!(e2e_config.zero_header_length, e2e_config2.zero_header_length);
1607 assert_eq!(e2e_config.transform_in_place, e2e_config2.transform_in_place);
1608 assert_eq!(e2e_config.offset, e2e_config2.offset);
1609 assert_eq!(e2e_config.max_delta_counter, e2e_config2.max_delta_counter);
1610 assert_eq!(e2e_config.max_error_state_init, e2e_config2.max_error_state_init);
1611 assert_eq!(e2e_config.max_error_state_invalid, e2e_config2.max_error_state_invalid);
1612 assert_eq!(e2e_config.max_error_state_valid, e2e_config2.max_error_state_valid);
1613 assert_eq!(
1614 e2e_config.max_no_new_or_repeated_data,
1615 e2e_config2.max_no_new_or_repeated_data
1616 );
1617 assert_eq!(e2e_config.min_ok_state_init, e2e_config2.min_ok_state_init);
1618 assert_eq!(e2e_config.min_ok_state_invalid, e2e_config2.min_ok_state_invalid);
1619 assert_eq!(e2e_config.min_ok_state_valid, e2e_config2.min_ok_state_valid);
1620 if *profile == E2EProfile::P01 || *profile == E2EProfile::P11 {
1621 assert_eq!(e2e_config.data_id_mode, e2e_config2.data_id_mode);
1622 assert_eq!(e2e_config.data_id_nibble_offset, e2e_config2.data_id_nibble_offset);
1623 }
1624 }
1625
1626 let config = TransformationTechnologyConfig::SomeIp(SomeIpTransformationTechnologyConfig {
1628 alignment: 8,
1629 byte_order: ByteOrder::MostSignificantByteFirst,
1630 interface_version: 1,
1631 });
1632 let ttech = dts.create_transformation_technology("someip", &config).unwrap();
1633 let config2 = ttech.config().unwrap();
1634 assert_eq!(config, config2);
1635
1636 let mut ttechs_iter = dts.transformation_technologies();
1638 assert_eq!(ttechs_iter.next().unwrap().name().unwrap(), "generic");
1639 assert_eq!(ttechs_iter.next().unwrap().name().unwrap(), "com");
1640 }
1641
1642 #[test]
1643 fn data_transformation() {
1644 let model = AutosarModelAbstraction::create("test", AutosarVersion::Autosar_00049);
1645 let package = model.get_or_create_package("/package").unwrap();
1646 let dts = DataTransformationSet::new("test_dts", &package).unwrap();
1647
1648 let e2e_transformation_config = TransformationTechnologyConfig::E2E(E2ETransformationTechnologyConfig {
1649 profile: E2EProfile::P01,
1650 zero_header_length: false,
1651 transform_in_place: true,
1652 offset: 0,
1653 max_delta_counter: 0,
1654 max_error_state_init: 0,
1655 max_error_state_invalid: 0,
1656 max_error_state_valid: 0,
1657 max_no_new_or_repeated_data: 0,
1658 min_ok_state_init: 0,
1659 min_ok_state_invalid: 0,
1660 min_ok_state_valid: 0,
1661 window_size: 11,
1662 window_size_init: Some(11),
1663 window_size_invalid: Some(12),
1664 window_size_valid: Some(13),
1665 profile_behavior: Some(E2EProfileBehavior::R4_2),
1666 sync_counter_init: Some(0),
1667 data_id_mode: Some(DataIdMode::All16Bit),
1668 data_id_nibble_offset: None,
1669 crc_offset: Some(2),
1670 counter_offset: Some(3),
1671 });
1672 let e2e_transformation = dts
1673 .create_transformation_technology("e2e", &e2e_transformation_config)
1674 .unwrap();
1675 assert_eq!(e2e_transformation.config().unwrap(), e2e_transformation_config);
1676
1677 let com_transformation_config =
1678 TransformationTechnologyConfig::Com(ComTransformationTechnologyConfig { isignal_ipdu_length: 8 });
1679 let com_transformation = dts
1680 .create_transformation_technology("com", &com_transformation_config)
1681 .unwrap();
1682 assert_eq!(com_transformation.config().unwrap(), com_transformation_config);
1683
1684 let someip_transformation_config =
1685 TransformationTechnologyConfig::SomeIp(SomeIpTransformationTechnologyConfig {
1686 alignment: 8,
1687 byte_order: ByteOrder::MostSignificantByteFirst,
1688 interface_version: 1,
1689 });
1690 let someip_transformation = dts
1691 .create_transformation_technology("someip", &someip_transformation_config)
1692 .unwrap();
1693 assert_eq!(someip_transformation.config().unwrap(), someip_transformation_config);
1694
1695 let generic_transformation_config =
1696 TransformationTechnologyConfig::Generic(GenericTransformationTechnologyConfig {
1697 protocol_name: "test".to_string(),
1698 protocol_version: "1.0.0".to_string(),
1699 header_length: 16,
1700 in_place: true,
1701 });
1702 let generic_transformation = dts
1703 .create_transformation_technology("generic", &generic_transformation_config)
1704 .unwrap();
1705 assert_eq!(someip_transformation.config().unwrap(), someip_transformation_config);
1706
1707 let result = dts.create_data_transformation("test1", &[], true);
1709 assert!(result.is_err());
1710
1711 let result = dts.create_data_transformation("test2", &[&com_transformation, &someip_transformation], true);
1713 assert!(result.is_err());
1714
1715 let result = dts.create_data_transformation("test3", &[&com_transformation], true);
1717 assert!(result.is_ok());
1718
1719 let result = dts.create_data_transformation("test4", &[&e2e_transformation], true);
1721 assert!(result.is_ok());
1722
1723 let result = dts.create_data_transformation("test5", &[&someip_transformation], true);
1725 assert!(result.is_ok());
1726
1727 let result = dts.create_data_transformation("test6", &[&generic_transformation], true);
1729 assert!(result.is_ok());
1730
1731 let result = dts.create_data_transformation("test7", &[&com_transformation, &e2e_transformation], true);
1733 assert!(result.is_ok());
1734
1735 let result = dts.create_data_transformation("test8", &[&someip_transformation, &e2e_transformation], true);
1737 assert!(result.is_ok());
1738
1739 let result = dts.create_data_transformation("test9", &[&generic_transformation, &e2e_transformation], true);
1741 assert!(result.is_ok());
1742 let dt = result.unwrap();
1743 assert_eq!(dt.data_transformation_set().unwrap(), dts);
1744
1745 let dts2 = package.create_data_transformation_set("test_dts2").unwrap();
1746
1747 let result = dts2.create_data_transformation("test10", &[&e2e_transformation], true);
1749 assert!(result.is_err());
1750
1751 let mut dts_iter = dts.data_transformations();
1753 assert_eq!(dts_iter.next().unwrap().name().unwrap(), "test3");
1754 assert_eq!(dts_iter.next().unwrap().name().unwrap(), "test4");
1755 assert_eq!(dts_iter.next().unwrap().name().unwrap(), "test5");
1756 assert_eq!(dts_iter.next().unwrap().name().unwrap(), "test6");
1757 assert_eq!(dts_iter.next().unwrap().name().unwrap(), "test7");
1758 assert_eq!(dts_iter.next().unwrap().name().unwrap(), "test8");
1759 assert_eq!(dts_iter.next().unwrap().name().unwrap(), "test9");
1760 assert_eq!(dts_iter.next(), None);
1761 }
1762
1763 #[test]
1764 fn transformation_technology() {
1765 let model = AutosarModelAbstraction::create("test", AutosarVersion::Autosar_4_2_1);
1766 let package = model.get_or_create_package("/package").unwrap();
1767 let dts = DataTransformationSet::new("test_dts", &package).unwrap();
1768
1769 let e2e_config_p01 = TransformationTechnologyConfig::E2E(E2ETransformationTechnologyConfig {
1770 profile: E2EProfile::P01,
1771 zero_header_length: false,
1772 transform_in_place: true,
1773 offset: 0,
1774 max_delta_counter: 0,
1775 max_error_state_init: 0,
1776 max_error_state_invalid: 0,
1777 max_error_state_valid: 0,
1778 max_no_new_or_repeated_data: 0,
1779 min_ok_state_init: 0,
1780 min_ok_state_invalid: 0,
1781 min_ok_state_valid: 0,
1782 window_size: 10,
1783 window_size_init: Some(11),
1784 window_size_invalid: Some(12),
1785 window_size_valid: Some(13),
1786 profile_behavior: Some(E2EProfileBehavior::R4_2),
1787 sync_counter_init: Some(0),
1788 data_id_mode: Some(DataIdMode::Lower12Bit),
1789 data_id_nibble_offset: Some(1),
1790 crc_offset: Some(2),
1791 counter_offset: Some(3),
1792 });
1793 let e2e_config_p04 = TransformationTechnologyConfig::E2E(E2ETransformationTechnologyConfig {
1794 profile: E2EProfile::P04,
1795 zero_header_length: false,
1796 transform_in_place: true,
1797 offset: 0,
1798 max_delta_counter: 0,
1799 max_error_state_init: 0,
1800 max_error_state_invalid: 0,
1801 max_error_state_valid: 0,
1802 max_no_new_or_repeated_data: 0,
1803 min_ok_state_init: 0,
1804 min_ok_state_invalid: 0,
1805 min_ok_state_valid: 0,
1806 window_size: 10,
1807 window_size_init: Some(11),
1808 window_size_invalid: Some(12),
1809 window_size_valid: Some(13),
1810 profile_behavior: Some(E2EProfileBehavior::R4_2),
1811 sync_counter_init: Some(0),
1812 data_id_mode: None,
1813 data_id_nibble_offset: None,
1814 crc_offset: None,
1815 counter_offset: None,
1816 });
1817 let com_config =
1818 TransformationTechnologyConfig::Com(ComTransformationTechnologyConfig { isignal_ipdu_length: 8 });
1819 let someip_config = TransformationTechnologyConfig::SomeIp(SomeIpTransformationTechnologyConfig {
1820 alignment: 8,
1821 byte_order: ByteOrder::MostSignificantByteFirst,
1822 interface_version: 1,
1823 });
1824 let generic_config = TransformationTechnologyConfig::Generic(GenericTransformationTechnologyConfig {
1825 protocol_name: "test".to_string(),
1826 protocol_version: "1.0.0".to_string(),
1827 header_length: 16,
1828 in_place: true,
1829 });
1830
1831 let transformation = dts.create_transformation_technology("t", &e2e_config_p01).unwrap();
1833 let e2e_p01_transformation_orig = transformation.element().serialize();
1834 dts.element()
1835 .remove_sub_element_kind(ElementName::TransformationTechnologys)
1836 .unwrap();
1837
1838 let transformation = dts.create_transformation_technology("t", &e2e_config_p04).unwrap();
1839 let e2e_p04_transformation_orig = transformation.element().serialize();
1840 dts.element()
1841 .remove_sub_element_kind(ElementName::TransformationTechnologys)
1842 .unwrap();
1843
1844 let transformation = dts.create_transformation_technology("t", &com_config).unwrap();
1845 let com_transformation_orig = transformation.element().serialize();
1846 dts.element()
1847 .remove_sub_element_kind(ElementName::TransformationTechnologys)
1848 .unwrap();
1849
1850 let transformation = dts.create_transformation_technology("t", &someip_config).unwrap();
1851 let someip_transformation_orig = transformation.element().serialize();
1852 dts.element()
1853 .remove_sub_element_kind(ElementName::TransformationTechnologys)
1854 .unwrap();
1855
1856 let transformation = dts.create_transformation_technology("t", &generic_config).unwrap();
1857 let generic_transformation_orig = transformation.element().serialize();
1858 dts.element()
1859 .remove_sub_element_kind(ElementName::TransformationTechnologys)
1860 .unwrap();
1861
1862 let transformation = dts.create_transformation_technology("t", &generic_config).unwrap();
1864 transformation.set_config(&e2e_config_p01).unwrap();
1865 assert_eq!(transformation.element().serialize(), e2e_p01_transformation_orig);
1866 transformation.set_config(&e2e_config_p04).unwrap();
1867 assert_eq!(transformation.element().serialize(), e2e_p04_transformation_orig);
1868 transformation.set_config(&com_config).unwrap();
1869 assert_eq!(transformation.element().serialize(), com_transformation_orig);
1870 transformation.set_config(&someip_config).unwrap();
1871 assert_eq!(transformation.element().serialize(), someip_transformation_orig);
1872 transformation.set_config(&generic_config).unwrap();
1873 assert_eq!(transformation.element().serialize(), generic_transformation_orig);
1874 }
1875
1876 #[test]
1877 fn data_transformation_chain_iter() {
1878 let model = AutosarModelAbstraction::create("test", AutosarVersion::Autosar_4_2_1);
1879 let package = model.get_or_create_package("/package").unwrap();
1880 let dts = DataTransformationSet::new("test_dts", &package).unwrap();
1881
1882 let com_transformation = dts
1883 .create_transformation_technology(
1884 "com",
1885 &TransformationTechnologyConfig::Com(ComTransformationTechnologyConfig { isignal_ipdu_length: 8 }),
1886 )
1887 .unwrap();
1888
1889 let dt = dts
1890 .create_data_transformation("test", &[&com_transformation], false)
1891 .unwrap();
1892 assert_eq!(dt.transformation_technologies().count(), 1);
1893 let com_transformation2 = dt.transformation_technologies().next().unwrap();
1894 assert_eq!(com_transformation, com_transformation2);
1895 }
1896
1897 #[test]
1898 fn transformation_isignal_props() {
1899 let model = AutosarModelAbstraction::create("test", AutosarVersion::Autosar_00049);
1900 let package = model.get_or_create_package("/package").unwrap();
1901 let dts = DataTransformationSet::new("test_dts", &package).unwrap();
1902
1903 let e2e_transformation = dts
1904 .create_transformation_technology(
1905 "e2e",
1906 &TransformationTechnologyConfig::E2E(E2ETransformationTechnologyConfig {
1907 profile: E2EProfile::P01,
1908 zero_header_length: false,
1909 transform_in_place: true,
1910 offset: 0,
1911 max_delta_counter: 0,
1912 max_error_state_init: 0,
1913 max_error_state_invalid: 0,
1914 max_error_state_valid: 0,
1915 max_no_new_or_repeated_data: 0,
1916 min_ok_state_init: 0,
1917 min_ok_state_invalid: 0,
1918 min_ok_state_valid: 0,
1919 window_size: 10,
1920 window_size_init: Some(11),
1921 window_size_invalid: Some(12),
1922 window_size_valid: Some(13),
1923 profile_behavior: Some(E2EProfileBehavior::R4_2),
1924 sync_counter_init: Some(0),
1925 data_id_mode: Some(DataIdMode::Lower12Bit),
1926 data_id_nibble_offset: Some(1),
1927 crc_offset: Some(2),
1928 counter_offset: Some(3),
1929 }),
1930 )
1931 .unwrap();
1932 let someip_transformation = dts
1933 .create_transformation_technology(
1934 "someip",
1935 &TransformationTechnologyConfig::SomeIp(SomeIpTransformationTechnologyConfig {
1936 alignment: 8,
1937 byte_order: ByteOrder::MostSignificantByteFirst,
1938 interface_version: 1,
1939 }),
1940 )
1941 .unwrap();
1942
1943 let sw_base_type =
1944 SwBaseType::new("sw_base_type", &package, 8, BaseTypeEncoding::None, None, None, None).unwrap();
1945 let signal = ISignal::new(
1946 "signal",
1947 &package,
1948 8,
1949 &SystemSignal::new("sys_signal", &package).unwrap(),
1950 Some(&sw_base_type),
1951 )
1952 .unwrap();
1953
1954 let e2e_props = signal
1955 .create_e2e_transformation_isignal_props(&e2e_transformation)
1956 .unwrap();
1957 assert_eq!(e2e_props.transformer().unwrap(), e2e_transformation);
1958 e2e_props.set_data_ids(&[1, 2, 3]).unwrap();
1959 e2e_props.set_data_length(Some(8)).unwrap();
1960 e2e_props.set_max_data_length(Some(16)).unwrap();
1961 e2e_props.set_min_data_length(Some(4)).unwrap();
1962 e2e_props.set_source_id(Some(0)).unwrap();
1963 assert_eq!(e2e_props.data_ids(), vec![1, 2, 3]);
1964 assert_eq!(e2e_props.data_length().unwrap(), 8);
1965 assert_eq!(e2e_props.max_data_length().unwrap(), 16);
1966 assert_eq!(e2e_props.min_data_length().unwrap(), 4);
1967 assert_eq!(e2e_props.source_id().unwrap(), 0);
1968 e2e_props.set_data_ids(&[]).unwrap();
1969 e2e_props.set_data_length(None).unwrap();
1970 e2e_props.set_max_data_length(None).unwrap();
1971 e2e_props.set_min_data_length(None).unwrap();
1972 e2e_props.set_source_id(None).unwrap();
1973 assert_eq!(e2e_props.data_ids(), vec![]);
1974 assert_eq!(e2e_props.data_length(), None);
1975 assert_eq!(e2e_props.max_data_length(), None);
1976 assert_eq!(e2e_props.min_data_length(), None);
1977 assert_eq!(e2e_props.source_id(), None);
1978
1979 assert!(EndToEndTransformationISignalProps::try_from(e2e_props.element().clone()).is_ok());
1980
1981 let someip_props = signal
1982 .create_someip_transformation_isignal_props(&someip_transformation)
1983 .unwrap();
1984 assert_eq!(someip_props.transformer().unwrap(), someip_transformation);
1985 someip_props.set_legacy_strings(Some(true)).unwrap();
1986 someip_props.set_interface_version(Some(1)).unwrap();
1987 someip_props.set_dynamic_length(Some(true)).unwrap();
1988 someip_props.set_message_type(Some(SomeIpMessageType::Request)).unwrap();
1989 someip_props.set_size_of_array_length(Some(8)).unwrap();
1990 someip_props.set_size_of_string_length(Some(16)).unwrap();
1991 someip_props.set_size_of_struct_length(Some(32)).unwrap();
1992 someip_props.set_size_of_union_length(Some(64)).unwrap();
1993 assert!(someip_props.legacy_strings().unwrap());
1994 assert_eq!(someip_props.interface_version().unwrap(), 1);
1995 assert!(someip_props.dynamic_length().unwrap());
1996 assert_eq!(someip_props.message_type().unwrap(), SomeIpMessageType::Request);
1997 assert_eq!(someip_props.size_of_array_length().unwrap(), 8);
1998 assert_eq!(someip_props.size_of_string_length().unwrap(), 16);
1999 assert_eq!(someip_props.size_of_struct_length().unwrap(), 32);
2000 assert_eq!(someip_props.size_of_union_length().unwrap(), 64);
2001 someip_props.set_legacy_strings(None).unwrap();
2002 someip_props.set_interface_version(None).unwrap();
2003 someip_props.set_dynamic_length(None).unwrap();
2004 someip_props.set_message_type(None).unwrap();
2005 someip_props.set_size_of_array_length(None).unwrap();
2006 someip_props.set_size_of_string_length(None).unwrap();
2007 someip_props.set_size_of_struct_length(None).unwrap();
2008 someip_props.set_size_of_union_length(None).unwrap();
2009 assert_eq!(someip_props.legacy_strings(), None);
2010 assert_eq!(someip_props.interface_version(), None);
2011 assert_eq!(someip_props.dynamic_length(), None);
2012 assert_eq!(someip_props.message_type(), None);
2013 assert_eq!(someip_props.size_of_array_length(), None);
2014 assert_eq!(someip_props.size_of_string_length(), None);
2015 assert_eq!(someip_props.size_of_struct_length(), None);
2016 assert_eq!(someip_props.size_of_union_length(), None);
2017
2018 assert!(SomeIpTransformationISignalProps::try_from(someip_props.element().clone()).is_ok());
2019
2020 assert_eq!(signal.transformation_isignal_props().count(), 2);
2021 let mut props_iter = signal.transformation_isignal_props();
2022 assert_eq!(props_iter.next().unwrap().element(), e2e_props.element());
2023 assert_eq!(props_iter.next().unwrap().element(), someip_props.element());
2024 }
2025}