1use crate::communication::{
2 AbstractPhysicalChannel, CommunicationDirection, ISignal, ISignalGroup, ISignalTriggering, PduToFrameMapping,
3 PhysicalChannel, SoConIPduIdentifier, SomeipTpConnection, TransferProperty,
4};
5use crate::{
6 AbstractionElement, ArPackage, AutosarAbstractionError, ByteOrder, EcuInstance, IdentifiableAbstractionElement,
7 abstraction_element, get_reference_parents, is_used_system_element, make_unique_name,
8};
9use autosar_data::{AutosarDataError, Element, ElementName, EnumItem};
10use std::str::FromStr;
11
12mod container_ipdu;
13mod isignal_ipdu;
14mod secured_ipdu;
15
16pub use container_ipdu::*;
17pub use isignal_ipdu::*;
18pub use secured_ipdu::*;
19
20pub trait AbstractPdu: AbstractionElement + Into<Pdu> {
24 fn set_length(&self, length: u32) -> Result<(), AutosarAbstractionError> {
26 self.element()
27 .get_or_create_sub_element(ElementName::Length)?
28 .set_character_data(length as u64)?;
29 Ok(())
30 }
31
32 fn length(&self) -> Option<u32> {
34 self.element()
35 .get_sub_element(ElementName::Length)?
36 .character_data()?
37 .parse_integer()
38 }
39
40 fn pdu_triggerings(&self) -> Vec<PduTriggering> {
42 let model_result = self.element().model();
43 let path_result = self.element().path();
44 if let (Ok(model), Ok(path)) = (model_result, path_result) {
45 model
46 .get_references_to(&path)
47 .iter()
48 .filter_map(|e| {
49 e.upgrade()
50 .and_then(|ref_elem| ref_elem.named_parent().ok().flatten())
51 .and_then(|elem| PduTriggering::try_from(elem).ok())
52 })
53 .collect()
54 } else {
55 vec![]
56 }
57 }
58}
59
60pub trait AbstractIpdu: AbstractPdu + Into<IPdu> {
64 fn set_contained_ipdu_props(&self, props: Option<&ContainedIPduProps>) -> Result<(), AutosarAbstractionError> {
68 ContainedIPduProps::set_props(self.element(), props)
69 }
70
71 #[must_use]
73 fn contained_ipdu_props(&self) -> Option<ContainedIPduProps> {
74 ContainedIPduProps::get_props(self.element())
75 }
76}
77
78#[derive(Debug, Clone, PartialEq, Eq, Hash)]
82pub struct NmPdu(Element);
83abstraction_element!(NmPdu, NmPdu);
84impl IdentifiableAbstractionElement for NmPdu {}
85
86impl NmPdu {
87 pub(crate) fn new(name: &str, package: &ArPackage, length: u32) -> Result<Self, AutosarAbstractionError> {
88 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
89 let elem_pdu = pkg_elements.create_named_sub_element(ElementName::NmPdu, name)?;
90 elem_pdu
91 .create_sub_element(ElementName::Length)?
92 .set_character_data(length.to_string())?;
93
94 Ok(Self(elem_pdu))
95 }
96
97 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
99 for pdu_triggering in self.pdu_triggerings() {
101 let _ = pdu_triggering.element().remove_sub_element_kind(ElementName::IPduRef);
102 let _ = pdu_triggering.remove(deep);
103 }
104
105 for signal_mapping in self.mapped_signals() {
106 let _ = signal_mapping.remove(deep);
107 }
108
109 let ref_parents = get_reference_parents(self.element())?;
110
111 AbstractionElement::remove(self, deep)?;
112
113 for (named_parent, _parent) in ref_parents {
114 if named_parent.element_name() == ElementName::PduToFrameMapping
115 && let Ok(pdu_to_frame_mapping) = PduToFrameMapping::try_from(named_parent)
116 {
117 pdu_to_frame_mapping.remove(deep)?;
118 }
119 }
120
121 Ok(())
122 }
123
124 pub fn set_unused_bit_pattern(&self, pattern: u8) -> Result<(), AutosarAbstractionError> {
126 self.element()
127 .get_or_create_sub_element(ElementName::UnusedBitPattern)?
128 .set_character_data(pattern.to_string())?;
129 Ok(())
130 }
131
132 #[must_use]
134 pub fn unused_bit_pattern(&self) -> Option<u8> {
135 self.element()
136 .get_sub_element(ElementName::UnusedBitPattern)?
137 .character_data()?
138 .parse_integer()
139 }
140
141 pub fn map_signal(
145 &self,
146 signal: &ISignal,
147 start_position: u32,
148 byte_order: ByteOrder,
149 update_bit: Option<u32>,
150 transfer_property: TransferProperty,
151 ) -> Result<ISignalToIPduMapping, AutosarAbstractionError> {
152 let signal_name = signal
153 .name()
154 .ok_or(AutosarAbstractionError::InvalidParameter("invalid signal".to_string()))?;
155
156 verify_signal_mapping(self, signal, start_position, byte_order, update_bit, &signal_name)?;
157
158 for pt in self.pdu_triggerings() {
160 let st = pt.create_signal_triggering(signal)?;
161 for pdu_port in pt.pdu_ports() {
162 if let (Ok(ecu), Some(direction)) = (pdu_port.ecu(), pdu_port.communication_direction()) {
163 st.connect_to_ecu(&ecu, direction)?;
164 }
165 }
166 }
167
168 let model = self.element().model()?;
170 let base_path = self.element().path()?;
171 let name = make_unique_name(&model, &base_path, &signal_name);
172
173 let mappings = self
176 .element()
177 .get_or_create_sub_element(ElementName::ISignalToIPduMappings)?;
178
179 ISignalToIPduMapping::new_with_signal(
180 &name,
181 &mappings,
182 signal,
183 start_position,
184 byte_order,
185 update_bit,
186 transfer_property,
187 )
188 }
189
190 pub fn map_signal_group(
192 &self,
193 signal_group: &ISignalGroup,
194 ) -> Result<ISignalToIPduMapping, AutosarAbstractionError> {
195 let signal_group_name = signal_group.name().ok_or(AutosarAbstractionError::InvalidParameter(
196 "invalid signal group".to_string(),
197 ))?;
198
199 for pt in self.pdu_triggerings() {
201 let st = pt.create_signal_group_triggering(signal_group)?;
202 for pdu_port in pt.pdu_ports() {
203 if let (Ok(ecu), Some(direction)) = (pdu_port.ecu(), pdu_port.communication_direction()) {
204 st.connect_to_ecu(&ecu, direction)?;
205 }
206 }
207 }
208
209 let model = self.element().model()?;
211 let base_path = self.element().path()?;
212 let name = make_unique_name(&model, &base_path, &signal_group_name);
213
214 let mappings = self
217 .element()
218 .get_or_create_sub_element(ElementName::ISignalToIPduMappings)?;
219
220 ISignalToIPduMapping::new_with_group(&name, &mappings, signal_group)
221 }
222}
223
224impl AbstractPdu for NmPdu {}
225
226impl SignalPdu for NmPdu {
227 fn mapped_signals(&self) -> impl Iterator<Item = ISignalToIPduMapping> + Send + use<> {
229 self.element()
230 .get_sub_element(ElementName::ISignalToIPduMappings)
231 .into_iter()
232 .flat_map(|mappings| mappings.sub_elements())
233 .filter_map(|elem| ISignalToIPduMapping::try_from(elem).ok())
234 }
235
236 fn map_signal(
237 &self,
238 signal: &ISignal,
239 start_position: u32,
240 byte_order: ByteOrder,
241 update_bit: Option<u32>,
242 transfer_property: TransferProperty,
243 ) -> Result<ISignalToIPduMapping, AutosarAbstractionError> {
244 NmPdu::map_signal(self, signal, start_position, byte_order, update_bit, transfer_property)
245 }
246
247 fn map_signal_group(&self, signal_group: &ISignalGroup) -> Result<ISignalToIPduMapping, AutosarAbstractionError> {
248 NmPdu::map_signal_group(self, signal_group)
249 }
250}
251
252impl From<NmPdu> for Pdu {
253 fn from(value: NmPdu) -> Self {
254 Pdu::NmPdu(value)
255 }
256}
257
258#[derive(Debug, Clone, PartialEq, Eq, Hash)]
262pub struct NPdu(Element);
263abstraction_element!(NPdu, NPdu);
264impl IdentifiableAbstractionElement for NPdu {}
265
266impl NPdu {
267 pub(crate) fn new(name: &str, package: &ArPackage, length: u32) -> Result<Self, AutosarAbstractionError> {
268 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
269 let elem_pdu = pkg_elements.create_named_sub_element(ElementName::NPdu, name)?;
270 elem_pdu
271 .create_sub_element(ElementName::Length)?
272 .set_character_data(length.to_string())?;
273
274 Ok(Self(elem_pdu))
275 }
276
277 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
279 for pdu_triggering in self.pdu_triggerings() {
281 let _ = pdu_triggering.element().remove_sub_element_kind(ElementName::IPduRef);
282 let _ = pdu_triggering.remove(deep);
283 }
284
285 let ref_parents = get_reference_parents(self.element())?;
286
287 AbstractionElement::remove(self, deep)?;
288
289 for (named_parent, _parent) in ref_parents {
290 if named_parent.element_name() == ElementName::PduToFrameMapping
291 && let Ok(pdu_to_frame_mapping) = PduToFrameMapping::try_from(named_parent)
292 {
293 pdu_to_frame_mapping.remove(deep)?;
294 }
295 }
296
297 Ok(())
298 }
299}
300
301impl AbstractPdu for NPdu {}
302
303impl AbstractIpdu for NPdu {}
304
305impl From<NPdu> for Pdu {
306 fn from(value: NPdu) -> Self {
307 Pdu::NPdu(value)
308 }
309}
310
311impl From<NPdu> for IPdu {
312 fn from(value: NPdu) -> Self {
313 IPdu::NPdu(value)
314 }
315}
316
317#[derive(Debug, Clone, PartialEq, Eq, Hash)]
321pub struct DcmIPdu(Element);
322abstraction_element!(DcmIPdu, DcmIPdu);
323impl IdentifiableAbstractionElement for DcmIPdu {}
324
325impl DcmIPdu {
326 pub(crate) fn new(
327 name: &str,
328 package: &ArPackage,
329 length: u32,
330 diag_pdu_type: DiagPduType,
331 ) -> Result<Self, AutosarAbstractionError> {
332 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
333 let elem_pdu = pkg_elements.create_named_sub_element(ElementName::DcmIPdu, name)?;
334 elem_pdu
335 .create_sub_element(ElementName::Length)?
336 .set_character_data(length.to_string())?;
337 let dcm_ipdu = Self(elem_pdu);
338 dcm_ipdu.set_diag_pdu_type(diag_pdu_type)?;
339
340 Ok(dcm_ipdu)
341 }
342
343 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
345 for pdu_triggering in self.pdu_triggerings() {
347 let _ = pdu_triggering.element().remove_sub_element_kind(ElementName::IPduRef);
348 let _ = pdu_triggering.remove(deep);
349 }
350
351 let ref_parents = get_reference_parents(self.element())?;
352
353 AbstractionElement::remove(self, deep)?;
354
355 for (named_parent, _parent) in ref_parents {
356 if named_parent.element_name() == ElementName::PduToFrameMapping
357 && let Ok(pdu_to_frame_mapping) = PduToFrameMapping::try_from(named_parent)
358 {
359 pdu_to_frame_mapping.remove(deep)?;
360 }
361 }
362
363 Ok(())
364 }
365
366 pub fn set_diag_pdu_type(&self, pdu_type: DiagPduType) -> Result<(), AutosarAbstractionError> {
368 self.element()
369 .get_or_create_sub_element(ElementName::DiagPduType)?
370 .set_character_data::<EnumItem>(pdu_type.into())?;
371 Ok(())
372 }
373
374 #[must_use]
376 pub fn diag_pdu_type(&self) -> Option<DiagPduType> {
377 let enum_item = self
378 .element()
379 .get_sub_element(ElementName::DiagPduType)?
380 .character_data()?
381 .enum_value()?;
382 DiagPduType::try_from(enum_item).ok()
383 }
384}
385
386impl AbstractPdu for DcmIPdu {}
387
388impl AbstractIpdu for DcmIPdu {}
389
390impl From<DcmIPdu> for Pdu {
391 fn from(value: DcmIPdu) -> Self {
392 Pdu::DcmIPdu(value)
393 }
394}
395
396impl From<DcmIPdu> for IPdu {
397 fn from(value: DcmIPdu) -> Self {
398 IPdu::DcmIPdu(value)
399 }
400}
401
402#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
406pub enum DiagPduType {
407 DiagRequest,
409 DiagResponse,
411}
412
413impl TryFrom<EnumItem> for DiagPduType {
414 type Error = AutosarAbstractionError;
415
416 fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
417 match value {
418 EnumItem::DiagRequest => Ok(DiagPduType::DiagRequest),
419 EnumItem::DiagResponse => Ok(DiagPduType::DiagResponse),
420 _ => Err(AutosarAbstractionError::ValueConversionError {
421 value: value.to_string(),
422 dest: "DiagPduType".to_string(),
423 }),
424 }
425 }
426}
427
428impl From<DiagPduType> for EnumItem {
429 fn from(value: DiagPduType) -> Self {
430 match value {
431 DiagPduType::DiagRequest => EnumItem::DiagRequest,
432 DiagPduType::DiagResponse => EnumItem::DiagResponse,
433 }
434 }
435}
436
437#[derive(Debug, Clone, PartialEq, Eq, Hash)]
441pub struct GeneralPurposePdu(Element);
442abstraction_element!(GeneralPurposePdu, GeneralPurposePdu);
443impl IdentifiableAbstractionElement for GeneralPurposePdu {}
444
445impl GeneralPurposePdu {
446 pub(crate) fn new(
447 name: &str,
448 package: &ArPackage,
449 length: u32,
450 category: GeneralPurposePduCategory,
451 ) -> Result<Self, AutosarAbstractionError> {
452 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
453 let pdu_elem = pkg_elements.create_named_sub_element(ElementName::GeneralPurposePdu, name)?;
454 let pdu = Self(pdu_elem);
455
456 pdu.set_length(length)?;
457 pdu.set_category(category)?;
458
459 Ok(pdu)
460 }
461
462 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
464 for pdu_triggering in self.pdu_triggerings() {
466 let _ = pdu_triggering.element().remove_sub_element_kind(ElementName::IPduRef);
467 let _ = pdu_triggering.remove(deep);
468 }
469
470 let ref_parents = get_reference_parents(self.element())?;
471
472 AbstractionElement::remove(self, deep)?;
473
474 for (named_parent, _parent) in ref_parents {
475 if named_parent.element_name() == ElementName::PduToFrameMapping
476 && let Ok(pdu_to_frame_mapping) = PduToFrameMapping::try_from(named_parent)
477 {
478 pdu_to_frame_mapping.remove(deep)?;
479 }
480 }
481
482 Ok(())
483 }
484
485 pub fn set_category(&self, category: GeneralPurposePduCategory) -> Result<(), AutosarAbstractionError> {
487 self.element()
488 .get_or_create_sub_element(ElementName::Category)?
489 .set_character_data(category.to_string())?;
490 Ok(())
491 }
492
493 #[must_use]
495 pub fn category(&self) -> Option<GeneralPurposePduCategory> {
496 let category_string = self
497 .element()
498 .get_sub_element(ElementName::Category)?
499 .character_data()?
500 .string_value()?;
501 GeneralPurposePduCategory::from_str(&category_string).ok()
502 }
503}
504
505impl AbstractPdu for GeneralPurposePdu {}
506
507impl From<GeneralPurposePdu> for Pdu {
508 fn from(value: GeneralPurposePdu) -> Self {
509 Pdu::GeneralPurposePdu(value)
510 }
511}
512
513#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
522pub enum GeneralPurposePduCategory {
523 Sd,
525 GlobalTime,
527 DoIp,
529}
530
531impl std::fmt::Display for GeneralPurposePduCategory {
532 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
533 match self {
534 GeneralPurposePduCategory::Sd => write!(f, "SD"),
535 GeneralPurposePduCategory::GlobalTime => write!(f, "GLOBAL_TIME"),
536 GeneralPurposePduCategory::DoIp => write!(f, "DOIP"),
537 }
538 }
539}
540
541impl std::str::FromStr for GeneralPurposePduCategory {
542 type Err = AutosarAbstractionError;
543
544 fn from_str(s: &str) -> Result<Self, Self::Err> {
545 match s {
546 "SD" => Ok(GeneralPurposePduCategory::Sd),
547 "GLOBAL_TIME" => Ok(GeneralPurposePduCategory::GlobalTime),
548 "DOIP" => Ok(GeneralPurposePduCategory::DoIp),
549 _ => Err(AutosarAbstractionError::InvalidParameter(s.to_string())),
550 }
551 }
552}
553
554#[derive(Debug, Clone, PartialEq, Eq, Hash)]
558pub struct GeneralPurposeIPdu(Element);
559abstraction_element!(GeneralPurposeIPdu, GeneralPurposeIPdu);
560impl IdentifiableAbstractionElement for GeneralPurposeIPdu {}
561
562impl GeneralPurposeIPdu {
563 pub(crate) fn new(
564 name: &str,
565 package: &ArPackage,
566 length: u32,
567 category: GeneralPurposeIPduCategory,
568 ) -> Result<Self, AutosarAbstractionError> {
569 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
570 let pdu_elem = pkg_elements.create_named_sub_element(ElementName::GeneralPurposeIPdu, name)?;
571 let pdu = Self(pdu_elem);
572
573 pdu.set_length(length)?;
574 pdu.set_category(category)?;
575
576 Ok(pdu)
577 }
578
579 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
581 for pdu_triggering in self.pdu_triggerings() {
583 let _ = pdu_triggering.element().remove_sub_element_kind(ElementName::IPduRef);
584 let _ = pdu_triggering.remove(deep);
585 }
586
587 let ref_parents = get_reference_parents(self.element())?;
588
589 AbstractionElement::remove(self, deep)?;
590
591 for (named_parent, _parent) in ref_parents {
592 if named_parent.element_name() == ElementName::PduToFrameMapping
593 && let Ok(pdu_to_frame_mapping) = PduToFrameMapping::try_from(named_parent)
594 {
595 pdu_to_frame_mapping.remove(deep)?;
596 }
597 }
598
599 Ok(())
600 }
601
602 pub fn set_category(&self, category: GeneralPurposeIPduCategory) -> Result<(), AutosarAbstractionError> {
604 self.element()
605 .get_or_create_sub_element(ElementName::Category)?
606 .set_character_data(category.to_string())?;
607 Ok(())
608 }
609
610 #[must_use]
612 pub fn category(&self) -> Option<GeneralPurposeIPduCategory> {
613 let category_string = self
614 .element()
615 .get_sub_element(ElementName::Category)?
616 .character_data()?
617 .string_value()?;
618 GeneralPurposeIPduCategory::from_str(&category_string).ok()
619 }
620}
621
622impl AbstractPdu for GeneralPurposeIPdu {}
623
624impl AbstractIpdu for GeneralPurposeIPdu {}
625
626impl From<GeneralPurposeIPdu> for Pdu {
627 fn from(value: GeneralPurposeIPdu) -> Self {
628 Pdu::GeneralPurposeIPdu(value)
629 }
630}
631
632impl From<GeneralPurposeIPdu> for IPdu {
633 fn from(value: GeneralPurposeIPdu) -> Self {
634 IPdu::GeneralPurposeIPdu(value)
635 }
636}
637
638#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
647pub enum GeneralPurposeIPduCategory {
648 Xcp,
650 SomeipSegmentedIpdu,
652 Dlt,
654}
655
656impl std::fmt::Display for GeneralPurposeIPduCategory {
657 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
658 match self {
659 GeneralPurposeIPduCategory::Xcp => write!(f, "XCP"),
660 GeneralPurposeIPduCategory::SomeipSegmentedIpdu => write!(f, "SOMEIP_SEGMENTED_IPDU"),
661 GeneralPurposeIPduCategory::Dlt => write!(f, "DLT"),
662 }
663 }
664}
665
666impl std::str::FromStr for GeneralPurposeIPduCategory {
667 type Err = AutosarAbstractionError;
668
669 fn from_str(s: &str) -> Result<Self, Self::Err> {
670 match s {
671 "XCP" => Ok(GeneralPurposeIPduCategory::Xcp),
672 "SOMEIP_SEGMENTED_IPDU" => Ok(GeneralPurposeIPduCategory::SomeipSegmentedIpdu),
673 "DLT" => Ok(GeneralPurposeIPduCategory::Dlt),
674 _ => Err(AutosarAbstractionError::InvalidParameter(s.to_string())),
675 }
676 }
677}
678
679#[derive(Debug, Clone, PartialEq, Eq, Hash)]
683pub struct MultiplexedIPdu(Element);
684abstraction_element!(MultiplexedIPdu, MultiplexedIPdu);
685impl IdentifiableAbstractionElement for MultiplexedIPdu {}
686
687impl MultiplexedIPdu {
688 pub(crate) fn new(name: &str, package: &ArPackage, length: u32) -> Result<Self, AutosarAbstractionError> {
689 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
690 let elem_pdu = pkg_elements.create_named_sub_element(ElementName::MultiplexedIPdu, name)?;
691 elem_pdu
692 .create_sub_element(ElementName::Length)?
693 .set_character_data(length.to_string())?;
694
695 Ok(Self(elem_pdu))
696 }
697
698 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
700 for pdu_triggering in self.pdu_triggerings() {
702 let _ = pdu_triggering.element().remove_sub_element_kind(ElementName::IPduRef);
703 let _ = pdu_triggering.remove(deep);
704 }
705
706 let opt_static_pdu = self.static_part();
707
708 for dynamic_part in self.dynamic_part_alternatives() {
709 dynamic_part.remove(deep)?;
710 }
711
712 let ref_parents = get_reference_parents(self.element())?;
713
714 AbstractionElement::remove(self, deep)?;
715
716 for (named_parent, _parent) in ref_parents {
717 if named_parent.element_name() == ElementName::PduToFrameMapping
718 && let Ok(pdu_to_frame_mapping) = PduToFrameMapping::try_from(named_parent)
719 {
720 pdu_to_frame_mapping.remove(deep)?;
721 }
722 }
723
724 if let Some(ipdu) = opt_static_pdu {
725 let mut triggerings = ipdu.pdu_triggerings();
726 if triggerings.len() == 1
729 && let Some(pdu_triggering) = triggerings.pop()
730 {
731 pdu_triggering.remove(deep)?;
732 }
733 }
734
735 Ok(())
736 }
737
738 pub fn set_static_part(&self, static_ipdu: &ISignalIPdu) -> Result<(), AutosarAbstractionError> {
740 let prev_static_part = self.static_part();
741
742 self.element()
743 .get_or_create_sub_element(ElementName::StaticParts)?
744 .get_or_create_sub_element(ElementName::StaticPart)?
745 .get_or_create_sub_element(ElementName::IPduRef)?
746 .set_reference_target(static_ipdu.element())?;
747
748 self.update_pdu_triggerings(prev_static_part.as_ref(), static_ipdu)?;
749
750 Ok(())
751 }
752
753 #[must_use]
755 pub fn static_part(&self) -> Option<ISignalIPdu> {
756 let ipdu_elem = self
757 .element()
758 .get_sub_element(ElementName::StaticParts)?
759 .get_sub_element(ElementName::StaticPart)?
760 .get_sub_element(ElementName::IPduRef)?
761 .get_reference_target()
762 .ok()?;
763 ISignalIPdu::try_from(ipdu_elem).ok()
764 }
765
766 pub fn add_dynamic_part(
772 &self,
773 dynamic_ipdu: &ISignalIPdu,
774 selector_code: u16,
775 initial_dynamic_part: bool,
776 ) -> Result<DynamicPartAlternative, AutosarAbstractionError> {
777 let dp_alternatives = self
778 .element()
779 .get_or_create_sub_element(ElementName::DynamicParts)?
780 .get_or_create_sub_element(ElementName::DynamicPart)?
781 .get_or_create_sub_element(ElementName::DynamicPartAlternatives)?;
782
783 DynamicPartAlternative::new(&dp_alternatives, dynamic_ipdu, selector_code, initial_dynamic_part)
784 }
785
786 pub fn dynamic_part_alternatives(&self) -> impl Iterator<Item = DynamicPartAlternative> + Send + use<> {
788 let dp_alternatives_elem = self
789 .element()
790 .get_sub_element(ElementName::DynamicParts)
791 .and_then(|e| e.get_sub_element(ElementName::DynamicPart))
792 .and_then(|e| e.get_sub_element(ElementName::DynamicPartAlternatives));
793
794 dp_alternatives_elem
795 .into_iter()
796 .flat_map(|e| e.sub_elements())
797 .filter_map(|elem| DynamicPartAlternative::try_from(elem).ok())
798 }
799
800 pub fn set_selector_field(
804 &self,
805 length: u8,
806 start_position: u32,
807 byte_order: ByteOrder,
808 ) -> Result<(), AutosarAbstractionError> {
809 if length == 0 || length > 16 {
810 return Err(AutosarAbstractionError::InvalidParameter(
811 "selector field length must be between 1 and 16".to_string(),
812 ));
813 }
814 self.element()
815 .get_or_create_sub_element(ElementName::SelectorFieldLength)?
816 .set_character_data(length as u64)?;
817 self.element()
818 .get_or_create_sub_element(ElementName::SelectorFieldStartPosition)?
819 .set_character_data(start_position as u64)?;
820 self.element()
821 .get_or_create_sub_element(ElementName::SelectorFieldByteOrder)?
822 .set_character_data::<EnumItem>(byte_order.into())?;
823 Ok(())
824 }
825
826 pub fn selector_field(&self) -> Option<(u8, u32, ByteOrder)> {
828 let length = self
829 .element()
830 .get_sub_element(ElementName::SelectorFieldLength)?
831 .character_data()?
832 .parse_integer()?;
833 let start_position = self
834 .element()
835 .get_sub_element(ElementName::SelectorFieldStartPosition)?
836 .character_data()?
837 .parse_integer()?;
838 let byte_order_enum = self
839 .element()
840 .get_sub_element(ElementName::SelectorFieldByteOrder)?
841 .character_data()?
842 .enum_value()?;
843 let byte_order = ByteOrder::try_from(byte_order_enum).ok()?;
844 Some((length, start_position, byte_order))
845 }
846
847 pub(crate) fn update_pdu_triggerings(
850 &self,
851 old_ipdu: Option<&ISignalIPdu>,
852 new_ipdu: &ISignalIPdu,
853 ) -> Result<(), AutosarAbstractionError> {
854 if let Some(old_ipdu) = old_ipdu {
857 for pt in old_ipdu.pdu_triggerings() {
858 pt.remove(false)?;
859 }
860 }
861
862 for multiplex_pt in self.pdu_triggerings() {
864 if let Ok(channel) = multiplex_pt.physical_channel() {
865 let new_pt = PduTriggering::new(&Pdu::ISignalIPdu(new_ipdu.clone()), &channel)?;
866 for pp in multiplex_pt.pdu_ports() {
867 if let (Ok(ecu), Some(direction)) = (pp.ecu(), pp.communication_direction()) {
868 let _ = new_pt.create_pdu_port(&ecu, direction);
869 }
870 }
871 }
872 }
873
874 Ok(())
875 }
876}
877
878impl AbstractPdu for MultiplexedIPdu {}
879
880impl AbstractIpdu for MultiplexedIPdu {}
881
882impl From<MultiplexedIPdu> for Pdu {
883 fn from(value: MultiplexedIPdu) -> Self {
884 Pdu::MultiplexedIPdu(value)
885 }
886}
887
888impl From<MultiplexedIPdu> for IPdu {
889 fn from(value: MultiplexedIPdu) -> Self {
890 IPdu::MultiplexedIPdu(value)
891 }
892}
893
894#[derive(Debug, Clone, PartialEq, Eq, Hash)]
898pub struct DynamicPartAlternative(Element);
899abstraction_element!(DynamicPartAlternative, DynamicPartAlternative);
900
901impl DynamicPartAlternative {
902 fn new(
903 parent: &Element,
904 dynamic_ipdu: &ISignalIPdu,
905 selector_code: u16,
906 initial_dynamic_part: bool,
907 ) -> Result<Self, AutosarAbstractionError> {
908 let dp_alt_elem = parent.create_sub_element(ElementName::DynamicPartAlternative)?;
909 let dp_alt = Self(dp_alt_elem);
910 dp_alt.set_ipdu(dynamic_ipdu)?;
911 dp_alt.set_selector_field_code(selector_code)?;
912 dp_alt.set_initial_dynamic_part(initial_dynamic_part)?;
913
914 Ok(dp_alt)
915 }
916
917 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
919 let opt_ipdu = self.ipdu();
921
922 AbstractionElement::remove(self, deep)?;
923
924 if let Some(ipdu) = opt_ipdu {
925 let mut triggerings = ipdu.pdu_triggerings();
926 if triggerings.len() == 1
929 && let Some(pdu_triggering) = triggerings.pop()
930 {
931 pdu_triggering.remove(deep)?;
932 }
933 }
934
935 Ok(())
936 }
937
938 pub fn set_ipdu(&self, ipdu: &ISignalIPdu) -> Result<(), AutosarAbstractionError> {
940 let old_ipdu = self.ipdu();
941 self.element()
942 .get_or_create_sub_element(ElementName::IPduRef)?
943 .set_reference_target(ipdu.element())?;
944
945 self.multiplexed_ipdu()?
946 .update_pdu_triggerings(old_ipdu.as_ref(), ipdu)?;
947
948 Ok(())
949 }
950
951 #[must_use]
953 pub fn ipdu(&self) -> Option<ISignalIPdu> {
954 let ipdu_elem = self
955 .element()
956 .get_sub_element(ElementName::IPduRef)?
957 .get_reference_target()
958 .ok()?;
959 ISignalIPdu::try_from(ipdu_elem).ok()
960 }
961
962 pub fn set_selector_field_code(&self, code: u16) -> Result<(), AutosarAbstractionError> {
964 self.element()
965 .get_or_create_sub_element(ElementName::SelectorFieldCode)?
966 .set_character_data(code as u64)?;
967 Ok(())
968 }
969
970 #[must_use]
972 pub fn selector_field_code(&self) -> Option<u16> {
973 self.element()
974 .get_sub_element(ElementName::SelectorFieldCode)?
975 .character_data()?
976 .parse_integer()
977 }
978
979 pub fn set_initial_dynamic_part(&self, initial: bool) -> Result<(), AutosarAbstractionError> {
981 self.element()
982 .get_or_create_sub_element(ElementName::InitialDynamicPart)?
983 .set_character_data(initial)?;
984 Ok(())
985 }
986
987 #[must_use]
989 pub fn is_initial_dynamic_part(&self) -> Option<bool> {
990 self.element()
991 .get_sub_element(ElementName::InitialDynamicPart)?
992 .character_data()?
993 .parse_bool()
994 }
995
996 pub fn multiplexed_ipdu(&self) -> Result<MultiplexedIPdu, AutosarAbstractionError> {
998 let parent_elem = self.element().named_parent()?;
999 let parent_elem = parent_elem.unwrap(); MultiplexedIPdu::try_from(parent_elem)
1001 }
1002}
1003
1004#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1010pub struct UserDefinedPdu(Element);
1011abstraction_element!(UserDefinedPdu, UserDefinedPdu);
1012impl IdentifiableAbstractionElement for UserDefinedPdu {}
1013
1014impl UserDefinedPdu {
1015 pub(crate) fn new(name: &str, package: &ArPackage, length: u32) -> Result<Self, AutosarAbstractionError> {
1016 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
1017 let pdu_elem = pkg_elements.create_named_sub_element(ElementName::UserDefinedPdu, name)?;
1018 let pdu = Self(pdu_elem);
1019
1020 pdu.set_length(length)?;
1021
1022 Ok(pdu)
1023 }
1024
1025 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
1027 for pdu_triggering in self.pdu_triggerings() {
1029 let _ = pdu_triggering.element().remove_sub_element_kind(ElementName::IPduRef);
1030 let _ = pdu_triggering.remove(deep);
1031 }
1032
1033 let ref_parents = get_reference_parents(self.element())?;
1034
1035 AbstractionElement::remove(self, deep)?;
1036
1037 for (named_parent, _parent) in ref_parents {
1038 if named_parent.element_name() == ElementName::PduToFrameMapping
1039 && let Ok(pdu_to_frame_mapping) = PduToFrameMapping::try_from(named_parent)
1040 {
1041 pdu_to_frame_mapping.remove(deep)?;
1042 }
1043 }
1044
1045 Ok(())
1046 }
1047}
1048
1049impl AbstractPdu for UserDefinedPdu {}
1050
1051impl From<UserDefinedPdu> for Pdu {
1052 fn from(value: UserDefinedPdu) -> Self {
1053 Pdu::UserDefinedPdu(value)
1054 }
1055}
1056
1057#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1061pub enum Pdu {
1062 ISignalIPdu(ISignalIPdu),
1064 NmPdu(NmPdu),
1066 NPdu(NPdu),
1068 DcmIPdu(DcmIPdu),
1070 GeneralPurposePdu(GeneralPurposePdu),
1072 GeneralPurposeIPdu(GeneralPurposeIPdu),
1074 ContainerIPdu(ContainerIPdu),
1076 SecuredIPdu(SecuredIPdu),
1078 MultiplexedIPdu(MultiplexedIPdu),
1080 UserDefinedPdu(UserDefinedPdu),
1082}
1083
1084impl AbstractionElement for Pdu {
1085 fn element(&self) -> &Element {
1086 match self {
1087 Pdu::ISignalIPdu(pdu) => pdu.element(),
1088 Pdu::NmPdu(pdu) => pdu.element(),
1089 Pdu::NPdu(pdu) => pdu.element(),
1090 Pdu::DcmIPdu(pdu) => pdu.element(),
1091 Pdu::GeneralPurposePdu(pdu) => pdu.element(),
1092 Pdu::GeneralPurposeIPdu(pdu) => pdu.element(),
1093 Pdu::ContainerIPdu(pdu) => pdu.element(),
1094 Pdu::SecuredIPdu(pdu) => pdu.element(),
1095 Pdu::MultiplexedIPdu(pdu) => pdu.element(),
1096 Pdu::UserDefinedPdu(pdu) => pdu.element(),
1097 }
1098 }
1099}
1100
1101impl TryFrom<Element> for Pdu {
1102 type Error = AutosarAbstractionError;
1103
1104 fn try_from(element: Element) -> Result<Self, Self::Error> {
1105 match element.element_name() {
1106 ElementName::ISignalIPdu => Ok(ISignalIPdu::try_from(element)?.into()),
1107 ElementName::NmPdu => Ok(NmPdu::try_from(element)?.into()),
1108 ElementName::NPdu => Ok(NPdu::try_from(element)?.into()),
1109 ElementName::DcmIPdu => Ok(DcmIPdu::try_from(element)?.into()),
1110 ElementName::GeneralPurposePdu => Ok(GeneralPurposePdu::try_from(element)?.into()),
1111 ElementName::GeneralPurposeIPdu => Ok(GeneralPurposeIPdu::try_from(element)?.into()),
1112 ElementName::ContainerIPdu => Ok(ContainerIPdu::try_from(element)?.into()),
1113 ElementName::SecuredIPdu => Ok(SecuredIPdu::try_from(element)?.into()),
1114 ElementName::MultiplexedIPdu => Ok(MultiplexedIPdu::try_from(element)?.into()),
1115 ElementName::UserDefinedPdu => Ok(UserDefinedPdu::try_from(element)?.into()),
1116 _ => Err(AutosarAbstractionError::ConversionError {
1117 element,
1118 dest: "Pdu".to_string(),
1119 }),
1120 }
1121 }
1122}
1123
1124impl IdentifiableAbstractionElement for Pdu {}
1125impl AbstractPdu for Pdu {}
1126
1127impl Pdu {
1128 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
1130 match self {
1131 Pdu::ISignalIPdu(pdu) => pdu.remove(deep),
1132 Pdu::NmPdu(pdu) => pdu.remove(deep),
1133 Pdu::NPdu(pdu) => pdu.remove(deep),
1134 Pdu::DcmIPdu(pdu) => pdu.remove(deep),
1135 Pdu::GeneralPurposePdu(pdu) => pdu.remove(deep),
1136 Pdu::GeneralPurposeIPdu(pdu) => pdu.remove(deep),
1137 Pdu::ContainerIPdu(pdu) => pdu.remove(deep),
1138 Pdu::SecuredIPdu(pdu) => pdu.remove(deep),
1139 Pdu::MultiplexedIPdu(pdu) => pdu.remove(deep),
1140 Pdu::UserDefinedPdu(pdu) => pdu.remove(deep),
1141 }
1142 }
1143}
1144
1145#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1149pub enum IPdu {
1150 ISignalIPdu(ISignalIPdu),
1152 NPdu(NPdu),
1154 DcmIPdu(DcmIPdu),
1156 GeneralPurposeIPdu(GeneralPurposeIPdu),
1158 ContainerIPdu(ContainerIPdu),
1160 SecuredIPdu(SecuredIPdu),
1162 MultiplexedIPdu(MultiplexedIPdu),
1164}
1165
1166impl AbstractionElement for IPdu {
1167 fn element(&self) -> &Element {
1168 match self {
1169 IPdu::ISignalIPdu(pdu) => pdu.element(),
1170 IPdu::NPdu(pdu) => pdu.element(),
1171 IPdu::DcmIPdu(pdu) => pdu.element(),
1172 IPdu::GeneralPurposeIPdu(pdu) => pdu.element(),
1173 IPdu::ContainerIPdu(pdu) => pdu.element(),
1174 IPdu::SecuredIPdu(pdu) => pdu.element(),
1175 IPdu::MultiplexedIPdu(pdu) => pdu.element(),
1176 }
1177 }
1178}
1179
1180impl TryFrom<Element> for IPdu {
1181 type Error = AutosarAbstractionError;
1182
1183 fn try_from(element: Element) -> Result<Self, Self::Error> {
1184 match element.element_name() {
1185 ElementName::ISignalIPdu => Ok(IPdu::ISignalIPdu(ISignalIPdu::try_from(element)?)),
1186 ElementName::NPdu => Ok(IPdu::NPdu(NPdu::try_from(element)?)),
1187 ElementName::DcmIPdu => Ok(IPdu::DcmIPdu(DcmIPdu::try_from(element)?)),
1188 ElementName::GeneralPurposeIPdu => Ok(IPdu::GeneralPurposeIPdu(GeneralPurposeIPdu::try_from(element)?)),
1189 ElementName::ContainerIPdu => Ok(IPdu::ContainerIPdu(ContainerIPdu::try_from(element)?)),
1190 ElementName::SecuredIPdu => Ok(IPdu::SecuredIPdu(SecuredIPdu::try_from(element)?)),
1191 ElementName::MultiplexedIPdu => Ok(IPdu::MultiplexedIPdu(MultiplexedIPdu::try_from(element)?)),
1192 _ => Err(AutosarAbstractionError::ConversionError {
1193 element,
1194 dest: "IPdu".to_string(),
1195 }),
1196 }
1197 }
1198}
1199
1200impl From<IPdu> for Pdu {
1201 fn from(value: IPdu) -> Self {
1202 match value {
1203 IPdu::ISignalIPdu(pdu) => Pdu::ISignalIPdu(pdu),
1204 IPdu::NPdu(pdu) => Pdu::NPdu(pdu),
1205 IPdu::DcmIPdu(pdu) => Pdu::DcmIPdu(pdu),
1206 IPdu::GeneralPurposeIPdu(pdu) => Pdu::GeneralPurposeIPdu(pdu),
1207 IPdu::ContainerIPdu(pdu) => Pdu::ContainerIPdu(pdu),
1208 IPdu::SecuredIPdu(pdu) => Pdu::SecuredIPdu(pdu),
1209 IPdu::MultiplexedIPdu(pdu) => Pdu::MultiplexedIPdu(pdu),
1210 }
1211 }
1212}
1213
1214impl IdentifiableAbstractionElement for IPdu {}
1215impl AbstractPdu for IPdu {}
1216impl AbstractIpdu for IPdu {}
1217
1218impl IPdu {
1219 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
1221 match self {
1222 IPdu::ISignalIPdu(pdu) => pdu.remove(deep),
1223 IPdu::NPdu(pdu) => pdu.remove(deep),
1224 IPdu::DcmIPdu(pdu) => pdu.remove(deep),
1225 IPdu::GeneralPurposeIPdu(pdu) => pdu.remove(deep),
1226 IPdu::ContainerIPdu(pdu) => pdu.remove(deep),
1227 IPdu::SecuredIPdu(pdu) => pdu.remove(deep),
1228 IPdu::MultiplexedIPdu(pdu) => pdu.remove(deep),
1229 }
1230 }
1231}
1232
1233#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1237pub struct PduTriggering(Element);
1238abstraction_element!(PduTriggering, PduTriggering);
1239impl IdentifiableAbstractionElement for PduTriggering {}
1240
1241impl PduTriggering {
1242 pub(crate) fn new(pdu: &Pdu, channel: &PhysicalChannel) -> Result<Self, AutosarAbstractionError> {
1243 let model = channel.element().model()?;
1244 let base_path = channel.element().path()?;
1245 let pdu_name = pdu
1246 .name()
1247 .ok_or(AutosarAbstractionError::InvalidParameter("invalid pdu".to_string()))?;
1248 let pt_name = format!("PT_{pdu_name}");
1249 let pt_name = make_unique_name(&model, &base_path, &pt_name);
1250
1251 let triggerings = channel
1252 .element()
1253 .get_or_create_sub_element(ElementName::PduTriggerings)?;
1254 let pt_elem = triggerings.create_named_sub_element(ElementName::PduTriggering, &pt_name)?;
1255 pt_elem
1256 .create_sub_element(ElementName::IPduRef)?
1257 .set_reference_target(pdu.element())?;
1258
1259 let pt = Self(pt_elem);
1260
1261 if let Pdu::ISignalIPdu(isignal_ipdu) = pdu {
1262 for signal_mapping in isignal_ipdu.mapped_signals() {
1263 if let Some(signal) = signal_mapping.signal() {
1264 pt.create_signal_triggering(&signal)?;
1265 } else if let Some(signal_group) = signal_mapping.signal_group() {
1266 pt.create_signal_group_triggering(&signal_group)?;
1267 }
1268 }
1269 }
1270
1271 Ok(pt)
1272 }
1273
1274 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
1276 let opt_pdu = self.pdu();
1277
1278 for signal_triggering in self.signal_triggerings() {
1279 signal_triggering.remove(deep)?;
1280 }
1281
1282 for pdu_port in self.pdu_ports() {
1283 pdu_port.remove(deep)?;
1284 }
1285
1286 let ref_parents = get_reference_parents(self.element())?;
1290
1291 AbstractionElement::remove(self, deep)?;
1292
1293 for (named_parent, parent) in ref_parents {
1294 if named_parent.element_name() == ElementName::SoConIPduIdentifier
1295 && let Ok(socon_ipdu_identifier) = SoConIPduIdentifier::try_from(named_parent)
1296 {
1297 socon_ipdu_identifier.remove(deep)?;
1298 } else if parent.element_name() == ElementName::SomeipTpConnection {
1299 if let Ok(someip_tp_connection) = SomeipTpConnection::try_from(parent) {
1300 someip_tp_connection.remove(deep)?;
1301 }
1302 } else if parent.element_name() == ElementName::PduTriggeringRefConditional
1303 && let Ok(Some(parent_parent)) = parent.parent()
1304 {
1305 parent_parent.remove_sub_element(parent)?;
1306 }
1307 }
1308
1309 if deep && let Some(pdu) = opt_pdu {
1310 if !is_used_system_element(pdu.element()) {
1312 pdu.remove(deep)?;
1313 }
1314 }
1315
1316 Ok(())
1317 }
1318
1319 #[must_use]
1321 pub fn pdu(&self) -> Option<Pdu> {
1322 let pdu_elem = self
1323 .element()
1324 .get_sub_element(ElementName::IPduRef)?
1325 .get_reference_target()
1326 .ok()?;
1327 Pdu::try_from(pdu_elem).ok()
1328 }
1329
1330 pub fn physical_channel(&self) -> Result<PhysicalChannel, AutosarAbstractionError> {
1332 let channel_elem = self.element().named_parent()?.ok_or(AutosarDataError::ItemDeleted)?;
1333 PhysicalChannel::try_from(channel_elem)
1334 }
1335
1336 pub fn create_pdu_port(
1338 &self,
1339 ecu: &EcuInstance,
1340 direction: CommunicationDirection,
1341 ) -> Result<IPduPort, AutosarAbstractionError> {
1342 for pdu_port in self.pdu_ports() {
1343 if let (Ok(existing_ecu), Some(existing_direction)) = (pdu_port.ecu(), pdu_port.communication_direction())
1344 && existing_ecu == *ecu
1345 && existing_direction == direction
1346 {
1347 return Ok(pdu_port);
1348 }
1349 }
1350
1351 let channel = self.physical_channel()?;
1352 let connector = channel
1353 .ecu_connector(ecu)
1354 .ok_or(AutosarAbstractionError::InvalidParameter(
1355 "The ECU is not connected to the channel".to_string(),
1356 ))?;
1357
1358 let name = self.name().ok_or(AutosarDataError::ItemDeleted)?;
1359 let suffix = match direction {
1360 CommunicationDirection::In => "Rx",
1361 CommunicationDirection::Out => "Tx",
1362 };
1363 let port_name = format!("{name}_{suffix}",);
1364 let pp_elem = connector
1365 .element()
1366 .get_or_create_sub_element(ElementName::EcuCommPortInstances)?
1367 .create_named_sub_element(ElementName::IPduPort, &port_name)?;
1368 pp_elem
1369 .create_sub_element(ElementName::CommunicationDirection)?
1370 .set_character_data::<EnumItem>(direction.into())?;
1371
1372 self.element()
1373 .get_or_create_sub_element(ElementName::IPduPortRefs)?
1374 .create_sub_element(ElementName::IPduPortRef)?
1375 .set_reference_target(&pp_elem)?;
1376
1377 for st in self.signal_triggerings() {
1378 st.connect_to_ecu(ecu, direction)?;
1379 }
1380
1381 Ok(IPduPort(pp_elem))
1382 }
1383
1384 pub fn pdu_ports(&self) -> impl Iterator<Item = IPduPort> + Send + use<> {
1386 self.element()
1387 .get_sub_element(ElementName::IPduPortRefs)
1388 .into_iter()
1389 .flat_map(|ipprefs| ipprefs.sub_elements())
1390 .filter_map(|ippref| {
1391 ippref
1392 .get_reference_target()
1393 .ok()
1394 .and_then(|elem| IPduPort::try_from(elem).ok())
1395 })
1396 }
1397
1398 pub fn signal_triggerings(&self) -> impl Iterator<Item = ISignalTriggering> + Send + use<> {
1400 self.element()
1401 .get_sub_element(ElementName::ISignalTriggerings)
1402 .into_iter()
1403 .flat_map(|ists| ists.sub_elements())
1404 .filter_map(|ist| {
1405 ist.get_sub_element(ElementName::ISignalTriggeringRef)
1406 .and_then(|str| str.get_reference_target().ok())
1407 .and_then(|elem| ISignalTriggering::try_from(elem).ok())
1408 })
1409 }
1410
1411 pub(crate) fn create_signal_triggering(
1413 &self,
1414 signal: &ISignal,
1415 ) -> Result<ISignalTriggering, AutosarAbstractionError> {
1416 let channel = self.physical_channel()?;
1417 let st = ISignalTriggering::new(signal, &channel)?;
1418 let triggerings = self
1419 .element()
1420 .get_or_create_sub_element(ElementName::ISignalTriggerings)?;
1421 triggerings
1422 .create_sub_element(ElementName::ISignalTriggeringRefConditional)?
1423 .create_sub_element(ElementName::ISignalTriggeringRef)?
1424 .set_reference_target(st.element())?;
1425
1426 for pdu_port in self.pdu_ports() {
1427 if let (Ok(ecu), Some(direction)) = (pdu_port.ecu(), pdu_port.communication_direction()) {
1428 st.connect_to_ecu(&ecu, direction)?;
1429 }
1430 }
1431
1432 Ok(st)
1433 }
1434
1435 pub(crate) fn create_signal_group_triggering(
1437 &self,
1438 signal_group: &ISignalGroup,
1439 ) -> Result<ISignalTriggering, AutosarAbstractionError> {
1440 let channel = self.physical_channel()?;
1441 let st = ISignalTriggering::new_group(signal_group, &channel)?;
1442 let triggerings = self
1443 .element()
1444 .get_or_create_sub_element(ElementName::ISignalTriggerings)?;
1445 triggerings
1446 .create_sub_element(ElementName::ISignalTriggeringRefConditional)?
1447 .create_sub_element(ElementName::ISignalTriggeringRef)?
1448 .set_reference_target(st.element())?;
1449
1450 for pdu_port in self.pdu_ports() {
1451 if let (Ok(ecu), Some(direction)) = (pdu_port.ecu(), pdu_port.communication_direction()) {
1452 st.connect_to_ecu(&ecu, direction)?;
1453 }
1454 }
1455
1456 Ok(st)
1457 }
1458}
1459
1460#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1464pub struct IPduPort(Element);
1465abstraction_element!(IPduPort, IPduPort);
1466impl IdentifiableAbstractionElement for IPduPort {}
1467
1468impl IPduPort {
1469 pub fn ecu(&self) -> Result<EcuInstance, AutosarAbstractionError> {
1471 let comm_connector_elem = self.element().named_parent()?.unwrap();
1472 let ecu_elem = comm_connector_elem.named_parent()?.unwrap();
1473 EcuInstance::try_from(ecu_elem)
1474 }
1475
1476 pub fn set_communication_direction(
1478 &self,
1479 direction: CommunicationDirection,
1480 ) -> Result<(), AutosarAbstractionError> {
1481 self.element()
1482 .get_or_create_sub_element(ElementName::CommunicationDirection)?
1483 .set_character_data::<EnumItem>(direction.into())?;
1484 Ok(())
1485 }
1486
1487 #[must_use]
1489 pub fn communication_direction(&self) -> Option<CommunicationDirection> {
1490 self.element()
1491 .get_sub_element(ElementName::CommunicationDirection)?
1492 .character_data()?
1493 .enum_value()?
1494 .try_into()
1495 .ok()
1496 }
1497}
1498
1499#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1504pub enum PduCollectionTrigger {
1505 Always,
1507 Never,
1509}
1510
1511impl From<PduCollectionTrigger> for EnumItem {
1512 fn from(value: PduCollectionTrigger) -> Self {
1513 match value {
1514 PduCollectionTrigger::Always => EnumItem::Always,
1515 PduCollectionTrigger::Never => EnumItem::Never,
1516 }
1517 }
1518}
1519
1520impl TryFrom<EnumItem> for PduCollectionTrigger {
1521 type Error = AutosarAbstractionError;
1522
1523 fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
1524 match value {
1525 EnumItem::Always => Ok(PduCollectionTrigger::Always),
1526 EnumItem::Never => Ok(PduCollectionTrigger::Never),
1527 _ => Err(AutosarAbstractionError::ValueConversionError {
1528 value: value.to_string(),
1529 dest: "PduCollectionTrigger".to_string(),
1530 }),
1531 }
1532 }
1533}
1534
1535#[cfg(test)]
1538mod test {
1539 use super::*;
1540 use crate::{
1541 AutosarModelAbstraction, ByteOrder, SystemCategory,
1542 communication::{AbstractFrame, AbstractFrameTriggering, CanAddressingMode, CanFrameType, TransferProperty},
1543 };
1544 use autosar_data::AutosarVersion;
1545
1546 #[test]
1547 fn test_pdus() {
1548 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
1549 let package = model.get_or_create_package("/pkg").unwrap();
1550 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1551
1552 let isignal_ipdu = system.create_isignal_ipdu("isignal_ipdu", &package, 1).unwrap();
1553 let nm_pdu = system.create_nm_pdu("nm_pdu", &package, 1).unwrap();
1554 let n_pdu = system.create_n_pdu("n_pdu", &package, 1).unwrap();
1555 let dcm_ipdu = system
1556 .create_dcm_ipdu("dcm_ipdu", &package, 1, DiagPduType::DiagRequest)
1557 .unwrap();
1558 let gp_pdu = system
1559 .create_general_purpose_pdu("gp_pdu", &package, 1, GeneralPurposePduCategory::Sd)
1560 .unwrap();
1561 let gp_ipdu = system
1562 .create_general_purpose_ipdu("gp_ipdu", &package, 1, GeneralPurposeIPduCategory::Xcp)
1563 .unwrap();
1564 let container_ipdu = system
1565 .create_container_ipdu(
1566 "container_ipdu",
1567 &package,
1568 1,
1569 ContainerIPduHeaderType::ShortHeader,
1570 RxAcceptContainedIPdu::AcceptAll,
1571 )
1572 .unwrap();
1573 let secured_ipdu = system
1574 .create_secured_ipdu("secured_ipdu", &package, 1, &SecureCommunicationProps::default())
1575 .unwrap();
1576 let multiplexed_ipdu = system.create_multiplexed_ipdu("multiplexed_ipdu", &package, 1).unwrap();
1577
1578 assert_eq!(isignal_ipdu.length().unwrap(), 1);
1579 assert_eq!(nm_pdu.length().unwrap(), 1);
1580 assert_eq!(n_pdu.length().unwrap(), 1);
1581 assert_eq!(dcm_ipdu.length().unwrap(), 1);
1582 assert_eq!(gp_pdu.length().unwrap(), 1);
1583 assert_eq!(gp_ipdu.length().unwrap(), 1);
1584 assert_eq!(container_ipdu.length().unwrap(), 1);
1585 assert_eq!(secured_ipdu.length().unwrap(), 1);
1586 assert_eq!(multiplexed_ipdu.length().unwrap(), 1);
1587
1588 isignal_ipdu.set_length(2).unwrap();
1589 assert_eq!(isignal_ipdu.length().unwrap(), 2);
1590
1591 let frame = system.create_flexray_frame("frame1", &package, 64).unwrap();
1592 frame
1593 .map_pdu(&isignal_ipdu, 0, ByteOrder::MostSignificantByteLast, None)
1594 .unwrap();
1595 frame
1596 .map_pdu(&nm_pdu, 8, ByteOrder::MostSignificantByteLast, None)
1597 .unwrap();
1598 frame
1599 .map_pdu(&n_pdu, 16, ByteOrder::MostSignificantByteLast, None)
1600 .unwrap();
1601 frame
1602 .map_pdu(&dcm_ipdu, 24, ByteOrder::MostSignificantByteLast, None)
1603 .unwrap();
1604 frame
1605 .map_pdu(&gp_pdu, 32, ByteOrder::MostSignificantByteLast, None)
1606 .unwrap();
1607 frame
1608 .map_pdu(&gp_ipdu, 40, ByteOrder::MostSignificantByteLast, None)
1609 .unwrap();
1610 frame
1611 .map_pdu(&container_ipdu, 48, ByteOrder::MostSignificantByteLast, None)
1612 .unwrap();
1613 frame
1614 .map_pdu(&secured_ipdu, 56, ByteOrder::MostSignificantByteLast, None)
1615 .unwrap();
1616 frame
1617 .map_pdu(&multiplexed_ipdu, 64, ByteOrder::MostSignificantByteLast, None)
1618 .unwrap();
1619
1620 let mut pdus_iter = frame.mapped_pdus();
1621 assert_eq!(pdus_iter.next().unwrap().name().unwrap(), "isignal_ipdu");
1622 assert_eq!(pdus_iter.next().unwrap().name().unwrap(), "nm_pdu");
1623 assert_eq!(pdus_iter.next().unwrap().name().unwrap(), "n_pdu");
1624 assert_eq!(pdus_iter.next().unwrap().name().unwrap(), "dcm_ipdu");
1625 assert_eq!(pdus_iter.next().unwrap().name().unwrap(), "gp_pdu");
1626 assert_eq!(pdus_iter.next().unwrap().name().unwrap(), "gp_ipdu");
1627 assert_eq!(pdus_iter.next().unwrap().name().unwrap(), "container_ipdu");
1628 assert_eq!(pdus_iter.next().unwrap().name().unwrap(), "secured_ipdu");
1629 assert_eq!(pdus_iter.next().unwrap().name().unwrap(), "multiplexed_ipdu");
1630 assert!(pdus_iter.next().is_none());
1631 }
1632
1633 #[test]
1634 fn test_pdu_triggering() {
1635 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
1636 let package = model.get_or_create_package("/pkg").unwrap();
1637 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1638
1639 let isignal_ipdu = system.create_isignal_ipdu("isignal_ipdu", &package, 1).unwrap();
1641 let syssignal = package.create_system_signal("syssignal").unwrap();
1642 let isignal = system.create_isignal("isignal", &package, 1, &syssignal, None).unwrap();
1643 isignal_ipdu
1644 .map_signal(
1645 &isignal,
1646 0,
1647 ByteOrder::MostSignificantByteLast,
1648 None,
1649 TransferProperty::Triggered,
1650 )
1651 .unwrap();
1652 let syssignal_group = package.create_system_signal_group("syssignal_group").unwrap();
1654 let isignal_group = system
1655 .create_isignal_group("isignal_group", &package, &syssignal_group)
1656 .unwrap();
1657 let syssignal2 = package.create_system_signal("syssignal2").unwrap();
1658 let isignal2 = system
1659 .create_isignal("isignal2", &package, 1, &syssignal2, None)
1660 .unwrap();
1661 isignal_ipdu.map_signal_group(&isignal_group).unwrap();
1662 isignal_ipdu
1663 .map_signal(
1664 &isignal2,
1665 1,
1666 ByteOrder::MostSignificantByteLast,
1667 None,
1668 TransferProperty::Triggered,
1669 )
1670 .unwrap();
1671
1672 let can_cluster = system.create_can_cluster("Cluster", &package, None).unwrap();
1674 let channel = can_cluster.create_physical_channel("Channel").unwrap();
1675 let frame = system.create_can_frame("frame", &package, 8).unwrap();
1676 let frame_triggering = channel
1677 .trigger_frame(&frame, 0x123, CanAddressingMode::Standard, CanFrameType::Can20)
1678 .unwrap();
1679 let _mapping = frame
1680 .map_pdu(&isignal_ipdu, 0, ByteOrder::MostSignificantByteLast, None)
1681 .unwrap();
1682
1683 let ecu = system.create_ecu_instance("ecu", &package).unwrap();
1685 let controller = ecu.create_can_communication_controller("controller").unwrap();
1686 controller.connect_physical_channel("connection", &channel).unwrap();
1687 frame_triggering
1688 .connect_to_ecu(&ecu, CommunicationDirection::In)
1689 .unwrap();
1690
1691 let pdu_triggering = frame_triggering.pdu_triggerings().next().unwrap();
1692 assert_eq!(pdu_triggering.pdu_ports().count(), 1);
1693 assert_eq!(pdu_triggering.signal_triggerings().count(), 3); let pdu_port = pdu_triggering.pdu_ports().next().unwrap();
1696 assert_eq!(pdu_port.ecu().unwrap().name().unwrap(), "ecu");
1697 assert_eq!(pdu_port.communication_direction().unwrap(), CommunicationDirection::In);
1698 pdu_port
1699 .set_communication_direction(CommunicationDirection::Out)
1700 .unwrap();
1701 assert_eq!(pdu_port.communication_direction().unwrap(), CommunicationDirection::Out);
1702 pdu_port.set_name("new_name").unwrap();
1703 assert_eq!(pdu_port.name().unwrap(), "new_name");
1704 }
1705
1706 #[test]
1707 fn nm_pdu() {
1708 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00052);
1709 let package = model.get_or_create_package("/pkg").unwrap();
1710 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1711
1712 let nm_pdu = system.create_nm_pdu("nm_pdu", &package, 1).unwrap();
1713 assert_eq!(nm_pdu.length().unwrap(), 1);
1714
1715 nm_pdu.set_length(8).unwrap();
1716 assert_eq!(nm_pdu.length().unwrap(), 8);
1717
1718 nm_pdu.set_unused_bit_pattern(0xff).unwrap();
1719 assert_eq!(nm_pdu.unused_bit_pattern().unwrap(), 0xff);
1720
1721 let syssignal = package.create_system_signal("sys_userdata").unwrap();
1723 let isignal = system
1724 .create_isignal("userdata", &package, 16, &syssignal, None)
1725 .unwrap();
1726 let mapping = nm_pdu
1727 .map_signal(
1728 &isignal,
1729 0,
1730 ByteOrder::MostSignificantByteFirst,
1731 Some(16),
1732 TransferProperty::Triggered,
1733 )
1734 .unwrap();
1735 assert_eq!(mapping.signal().unwrap(), isignal);
1736 }
1737
1738 #[test]
1739 fn general_purpose_pdu() {
1740 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
1741 let package = model.get_or_create_package("/pkg").unwrap();
1742 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1743
1744 let gp_pdu1 = system
1745 .create_general_purpose_pdu("gp_pdu1", &package, 1, GeneralPurposePduCategory::Sd)
1746 .unwrap();
1747 assert_eq!(gp_pdu1.category().unwrap(), GeneralPurposePduCategory::Sd);
1748
1749 let gp_pdu2 = system
1750 .create_general_purpose_pdu("gp_pdu2", &package, 1, GeneralPurposePduCategory::GlobalTime)
1751 .unwrap();
1752 assert_eq!(gp_pdu2.category().unwrap(), GeneralPurposePduCategory::GlobalTime);
1753
1754 let gp_pdu3 = system
1755 .create_general_purpose_pdu("gp_pdu3", &package, 1, GeneralPurposePduCategory::DoIp)
1756 .unwrap();
1757 assert_eq!(gp_pdu3.category().unwrap(), GeneralPurposePduCategory::DoIp);
1758
1759 assert_eq!(
1761 GeneralPurposePduCategory::from_str("SD").unwrap(),
1762 GeneralPurposePduCategory::Sd
1763 );
1764 assert_eq!(
1765 GeneralPurposePduCategory::from_str("GLOBAL_TIME").unwrap(),
1766 GeneralPurposePduCategory::GlobalTime
1767 );
1768 assert_eq!(
1769 GeneralPurposePduCategory::from_str("DOIP").unwrap(),
1770 GeneralPurposePduCategory::DoIp
1771 );
1772 assert!(GeneralPurposePduCategory::from_str("invalid").is_err());
1773 }
1774
1775 #[test]
1776 fn general_purpose_ipdu() {
1777 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
1778 let package = model.get_or_create_package("/pkg").unwrap();
1779 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1780
1781 let gp_ipdu1 = system
1782 .create_general_purpose_ipdu("gp_ipdu1", &package, 1, GeneralPurposeIPduCategory::Xcp)
1783 .unwrap();
1784 assert_eq!(gp_ipdu1.category().unwrap(), GeneralPurposeIPduCategory::Xcp);
1785
1786 let gp_ipdu2 = system
1787 .create_general_purpose_ipdu("gp_ipdu2", &package, 1, GeneralPurposeIPduCategory::SomeipSegmentedIpdu)
1788 .unwrap();
1789 assert_eq!(
1790 gp_ipdu2.category().unwrap(),
1791 GeneralPurposeIPduCategory::SomeipSegmentedIpdu
1792 );
1793
1794 let gp_ipdu3 = system
1795 .create_general_purpose_ipdu("gp_ipdu3", &package, 1, GeneralPurposeIPduCategory::Dlt)
1796 .unwrap();
1797 assert_eq!(gp_ipdu3.category().unwrap(), GeneralPurposeIPduCategory::Dlt);
1798
1799 assert_eq!(
1801 GeneralPurposeIPduCategory::from_str("XCP").unwrap(),
1802 GeneralPurposeIPduCategory::Xcp
1803 );
1804 assert_eq!(
1805 GeneralPurposeIPduCategory::from_str("SOMEIP_SEGMENTED_IPDU").unwrap(),
1806 GeneralPurposeIPduCategory::SomeipSegmentedIpdu
1807 );
1808 assert_eq!(
1809 GeneralPurposeIPduCategory::from_str("DLT").unwrap(),
1810 GeneralPurposeIPduCategory::Dlt
1811 );
1812 assert!(GeneralPurposeIPduCategory::from_str("invalid").is_err());
1813 }
1814
1815 #[test]
1816 fn multiplexed_ipdu() {
1817 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
1818 let package = model.get_or_create_package("/pkg").unwrap();
1819 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1820
1821 let multiplexed_ipdu = system.create_multiplexed_ipdu("multiplexed_ipdu", &package, 1).unwrap();
1822 assert_eq!(multiplexed_ipdu.length().unwrap(), 1);
1823
1824 multiplexed_ipdu.set_length(16).unwrap();
1825 assert_eq!(multiplexed_ipdu.length().unwrap(), 16);
1826
1827 let static_ipdu = system.create_isignal_ipdu("static_ipdu", &package, 8).unwrap();
1828 multiplexed_ipdu.set_static_part(&static_ipdu).unwrap();
1829 assert_eq!(multiplexed_ipdu.static_part().unwrap(), static_ipdu);
1830
1831 let dynamic_ipdu = system.create_isignal_ipdu("dynamic_ipdu", &package, 8).unwrap();
1832 let dp_alt = multiplexed_ipdu.add_dynamic_part(&dynamic_ipdu, 0, true).unwrap();
1833 assert_eq!(dp_alt.ipdu().unwrap(), dynamic_ipdu);
1834 assert_eq!(dp_alt.selector_field_code().unwrap(), 0);
1835 assert_eq!(dp_alt.is_initial_dynamic_part().unwrap(), true);
1836 assert_eq!(dp_alt.multiplexed_ipdu().unwrap(), multiplexed_ipdu);
1837 assert_eq!(multiplexed_ipdu.dynamic_part_alternatives().count(), 1);
1838
1839 multiplexed_ipdu
1840 .set_selector_field(8, 16, ByteOrder::MostSignificantByteFirst)
1841 .unwrap();
1842 let (start_bit, length, byte_order) = multiplexed_ipdu.selector_field().unwrap();
1843 assert_eq!(start_bit, 8);
1844 assert_eq!(length, 16);
1845 assert_eq!(byte_order, ByteOrder::MostSignificantByteFirst);
1846
1847 let cluster = system.create_can_cluster("cluster", &package, None).unwrap();
1848 let channel = cluster.create_physical_channel("channel").unwrap();
1849 let frame = system.create_can_frame("frame", &package, 64).unwrap();
1850 channel
1851 .trigger_frame(&frame, 0x33, CanAddressingMode::Standard, CanFrameType::CanFd)
1852 .unwrap();
1853 let _mapping = frame
1854 .map_pdu(&multiplexed_ipdu, 0, ByteOrder::MostSignificantByteLast, None)
1855 .unwrap();
1856
1857 assert_eq!(channel.frame_triggerings().count(), 1);
1858 assert_eq!(channel.pdu_triggerings().count(), 3); }
1860
1861 #[test]
1862 fn ipdu() {
1863 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
1864 let package = model.get_or_create_package("/pkg").unwrap();
1865 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1866
1867 let isignal_ipdu = system.create_isignal_ipdu("isignal_ipdu", &package, 1).unwrap();
1868 let n_pdu = system.create_n_pdu("n_pdu", &package, 1).unwrap();
1869 let dcm_ipdu = system
1870 .create_dcm_ipdu("dcm_ipdu", &package, 1, DiagPduType::DiagResponse)
1871 .unwrap();
1872 let gp_ipdu = system
1873 .create_general_purpose_ipdu("gp_ipdu", &package, 1, GeneralPurposeIPduCategory::Xcp)
1874 .unwrap();
1875 let container_ipdu = system
1876 .create_container_ipdu(
1877 "container_ipdu",
1878 &package,
1879 1,
1880 ContainerIPduHeaderType::LongHeader,
1881 RxAcceptContainedIPdu::AcceptConfigured,
1882 )
1883 .unwrap();
1884 let secured_ipdu = system
1885 .create_secured_ipdu("secured_ipdu", &package, 1, &SecureCommunicationProps::default())
1886 .unwrap();
1887 let multiplexed_ipdu = system.create_multiplexed_ipdu("multiplexed_ipdu", &package, 1).unwrap();
1888
1889 let ipdu: IPdu = isignal_ipdu.clone().into();
1890 assert_eq!(ipdu.element(), isignal_ipdu.element());
1891 assert!(matches!(ipdu, IPdu::ISignalIPdu(_)));
1892
1893 let ipdu: IPdu = n_pdu.clone().into();
1896 assert_eq!(ipdu.element(), n_pdu.element());
1897 assert!(matches!(ipdu, IPdu::NPdu(_)));
1898
1899 let ipdu: IPdu = dcm_ipdu.clone().into();
1900 assert_eq!(ipdu.element(), dcm_ipdu.element());
1901 assert!(matches!(ipdu, IPdu::DcmIPdu(_)));
1902
1903 let ipdu: IPdu = n_pdu.clone().into();
1904 assert_eq!(ipdu.element(), n_pdu.element());
1905 assert!(matches!(ipdu, IPdu::NPdu(_)));
1906
1907 let ipdu: IPdu = gp_ipdu.clone().into();
1910 assert_eq!(ipdu.element(), gp_ipdu.element());
1911 assert!(matches!(ipdu, IPdu::GeneralPurposeIPdu(_)));
1912
1913 let ipdu: IPdu = container_ipdu.clone().into();
1914 assert_eq!(ipdu.element(), container_ipdu.element());
1915 assert!(matches!(ipdu, IPdu::ContainerIPdu(_)));
1916
1917 let ipdu: IPdu = secured_ipdu.clone().into();
1918 assert_eq!(ipdu.element(), secured_ipdu.element());
1919 assert!(matches!(ipdu, IPdu::SecuredIPdu(_)));
1920
1921 let ipdu: IPdu = multiplexed_ipdu.clone().into();
1922 assert_eq!(ipdu.element(), multiplexed_ipdu.element());
1923 assert!(matches!(ipdu, IPdu::MultiplexedIPdu(_)));
1924
1925 let pdu: Pdu = ipdu.clone().into();
1927 assert_eq!(pdu.element(), ipdu.element());
1928 }
1929
1930 #[test]
1931 fn remove() {
1932 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
1933 let package = model.get_or_create_package("/pkg").unwrap();
1934 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1935
1936 let isignal_ipdu = system.create_isignal_ipdu("isignal_ipdu", &package, 1).unwrap();
1937 let n_pdu = system.create_n_pdu("n_pdu", &package, 1).unwrap();
1938 let dcm_ipdu = system
1939 .create_dcm_ipdu("dcm_ipdu", &package, 1, DiagPduType::DiagResponse)
1940 .unwrap();
1941 let gp_ipdu = system
1942 .create_general_purpose_ipdu("gp_ipdu", &package, 1, GeneralPurposeIPduCategory::Xcp)
1943 .unwrap();
1944 let container_ipdu = system
1945 .create_container_ipdu(
1946 "container_ipdu",
1947 &package,
1948 1,
1949 ContainerIPduHeaderType::LongHeader,
1950 RxAcceptContainedIPdu::AcceptConfigured,
1951 )
1952 .unwrap();
1953 let secured_ipdu = system
1954 .create_secured_ipdu("secured_ipdu", &package, 1, &SecureCommunicationProps::default())
1955 .unwrap();
1956 let multiplexed_ipdu = system.create_multiplexed_ipdu("multiplexed_ipdu", &package, 1).unwrap();
1957
1958 assert!(!is_used_system_element(isignal_ipdu.element()));
1959 assert!(!is_used_system_element(n_pdu.element()));
1960 assert!(!is_used_system_element(dcm_ipdu.element()));
1961 assert!(!is_used_system_element(gp_ipdu.element()));
1962 assert!(!is_used_system_element(container_ipdu.element()));
1963 assert!(!is_used_system_element(secured_ipdu.element()));
1964 assert!(!is_used_system_element(multiplexed_ipdu.element()));
1965
1966 let can_cluster = system.create_can_cluster("cluster", &package, None).unwrap();
1967 let channel = can_cluster.create_physical_channel("channel").unwrap();
1968 let frame1 = system.create_can_frame("frame", &package, 64).unwrap();
1969 channel
1970 .trigger_frame(&frame1, 0x123, CanAddressingMode::Standard, CanFrameType::Can20)
1971 .unwrap();
1972 let _mapping = frame1
1973 .map_pdu(&isignal_ipdu, 0, ByteOrder::MostSignificantByteLast, None)
1974 .unwrap();
1975 let frame2 = system.create_can_frame("frame2", &package, 64).unwrap();
1976 channel
1977 .trigger_frame(&frame2, 0x124, CanAddressingMode::Standard, CanFrameType::Can20)
1978 .unwrap();
1979 let _mapping = frame2
1980 .map_pdu(&n_pdu, 0, ByteOrder::MostSignificantByteLast, None)
1981 .unwrap();
1982 let frame3 = system.create_can_frame("frame3", &package, 64).unwrap();
1983 channel
1984 .trigger_frame(&frame3, 0x125, CanAddressingMode::Standard, CanFrameType::Can20)
1985 .unwrap();
1986 let _mapping = frame3
1987 .map_pdu(&dcm_ipdu, 0, ByteOrder::MostSignificantByteLast, None)
1988 .unwrap();
1989 let frame4 = system.create_can_frame("frame4", &package, 64).unwrap();
1990 channel
1991 .trigger_frame(&frame4, 0x126, CanAddressingMode::Standard, CanFrameType::Can20)
1992 .unwrap();
1993 let _mapping = frame4
1994 .map_pdu(&gp_ipdu, 0, ByteOrder::MostSignificantByteLast, None)
1995 .unwrap();
1996 let frame5 = system.create_can_frame("frame5", &package, 64).unwrap();
1997 channel
1998 .trigger_frame(&frame5, 0x127, CanAddressingMode::Standard, CanFrameType::Can20)
1999 .unwrap();
2000 let _mapping = frame5
2001 .map_pdu(&container_ipdu, 0, ByteOrder::MostSignificantByteLast, None)
2002 .unwrap();
2003 let frame6 = system.create_can_frame("frame6", &package, 64).unwrap();
2004 channel
2005 .trigger_frame(&frame6, 0x128, CanAddressingMode::Standard, CanFrameType::Can20)
2006 .unwrap();
2007 let _mapping = frame6
2008 .map_pdu(&secured_ipdu, 0, ByteOrder::MostSignificantByteLast, None)
2009 .unwrap();
2010 let frame7 = system.create_can_frame("frame7", &package, 64).unwrap();
2011 channel
2012 .trigger_frame(&frame7, 0x129, CanAddressingMode::Standard, CanFrameType::Can20)
2013 .unwrap();
2014 let _mapping = frame7
2015 .map_pdu(&multiplexed_ipdu, 0, ByteOrder::MostSignificantByteLast, None)
2016 .unwrap();
2017
2018 assert_eq!(channel.pdu_triggerings().count(), 7);
2019
2020 let static_part_pdu = system.create_isignal_ipdu("static_part_pdu", &package, 8).unwrap();
2022 multiplexed_ipdu.set_static_part(&static_part_pdu).unwrap();
2023 let dynamic_part_pdu = system.create_isignal_ipdu("dynamic_part_pdu", &package, 8).unwrap();
2024 multiplexed_ipdu.add_dynamic_part(&dynamic_part_pdu, 0, true).unwrap();
2025
2026 assert_eq!(channel.pdu_triggerings().count(), 9); let contained_ipdu = system.create_isignal_ipdu("contained_ipdu", &package, 8).unwrap();
2030 container_ipdu.map_ipdu(&contained_ipdu, &channel).unwrap();
2031
2032 let payload_ipdu = system.create_isignal_ipdu("payload_ipdu", &package, 8).unwrap();
2034 secured_ipdu.set_payload_ipdu(&payload_ipdu, &channel).unwrap();
2035
2036 assert_eq!(channel.pdu_triggerings().count(), 11); isignal_ipdu.remove(true).unwrap();
2040 n_pdu.remove(true).unwrap();
2041 dcm_ipdu.remove(true).unwrap();
2042 gp_ipdu.remove(true).unwrap();
2043 container_ipdu.remove(true).unwrap();
2044 secured_ipdu.remove(true).unwrap();
2045 multiplexed_ipdu.remove(true).unwrap();
2046
2047 assert_eq!(channel.pdu_triggerings().count(), 0);
2049 }
2050}