autosar_data_abstraction/communication/physical_channel/ethernet/
someip.rs

1use crate::communication::{
2    Cluster, EventGroupControlType, GeneralPurposeIPduCategory, ISignalIPdu, Pdu, PduTriggering, SoConIPduIdentifier,
3    SocketAddress, TpConfig,
4};
5use crate::{
6    AbstractionElement, ArPackage, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element,
7};
8use autosar_data::{Element, ElementName, EnumItem};
9
10//##################################################################
11
12/// A `ServiceInstanceCollectionSet` contains `ServiceInstance`s that are provided or consumed by an ECU
13#[derive(Debug, Clone, PartialEq, Eq, Hash)]
14pub struct ServiceInstanceCollectionSet(Element);
15abstraction_element!(ServiceInstanceCollectionSet, ServiceInstanceCollectionSet);
16impl IdentifiableAbstractionElement for ServiceInstanceCollectionSet {}
17
18impl ServiceInstanceCollectionSet {
19    /// create a new `ServiceInstanceCollectionSet`
20    ///
21    /// This is a Fibex element, so this function is not exported in the API.
22    /// Users should call `System::create_service_instance_collection_set` instead, which also creates the required `FibexElementRef`.
23    pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
24        let sic = package
25            .element()
26            .get_or_create_sub_element(ElementName::Elements)?
27            .create_named_sub_element(ElementName::ServiceInstanceCollectionSet, name)?;
28        Ok(Self(sic))
29    }
30
31    /// create a new `ProvidedServiceInstance` in this `ServiceInstanceCollectionSet`
32    pub fn create_provided_service_instance(
33        &self,
34        name: &str,
35        service_identifier: u16,
36        instance_identifier: u16,
37        major_version: u32,
38        minor_version: u32,
39    ) -> Result<ProvidedServiceInstance, AutosarAbstractionError> {
40        let instances = self
41            .element()
42            .get_or_create_sub_element(ElementName::ServiceInstances)?;
43
44        ProvidedServiceInstance::new(
45            name,
46            &instances,
47            service_identifier,
48            instance_identifier,
49            major_version,
50            minor_version,
51        )
52    }
53
54    /// create a new `ConsumedServiceInstance` in this `ServiceInstanceCollectionSet`
55    pub fn create_consumed_service_instance(
56        &self,
57        name: &str,
58        service_identifier: u16,
59        instance_identifier: u16,
60        major_version: u32,
61        minor_version: &str,
62    ) -> Result<ConsumedServiceInstance, AutosarAbstractionError> {
63        let instances = self
64            .element()
65            .get_or_create_sub_element(ElementName::ServiceInstances)?;
66
67        ConsumedServiceInstance::new(
68            name,
69            &instances,
70            service_identifier,
71            instance_identifier,
72            major_version,
73            minor_version,
74        )
75    }
76
77    /// create an iterator over all `ServiceInstances` in this set
78    pub fn service_instances(&self) -> impl Iterator<Item = ServiceInstance> + Send + use<> {
79        self.element()
80            .get_sub_element(ElementName::ServiceInstances)
81            .into_iter()
82            .flat_map(|elem| elem.sub_elements())
83            .filter_map(|elem| ServiceInstance::try_from(elem).ok())
84    }
85}
86
87//##################################################################
88
89/// A `ServiceInstance` is a service that is provided or consumed by an ECU
90#[derive(Debug, Clone, PartialEq, Eq, Hash)]
91pub enum ServiceInstance {
92    /// A service that is provided by an ECU
93    Provided(ProvidedServiceInstance),
94    /// A service that is consumed by an ECU
95    Consumed(ConsumedServiceInstance),
96}
97
98impl AbstractionElement for ServiceInstance {
99    fn element(&self) -> &Element {
100        match self {
101            ServiceInstance::Provided(psi) => psi.element(),
102            ServiceInstance::Consumed(csi) => csi.element(),
103        }
104    }
105}
106
107impl IdentifiableAbstractionElement for ServiceInstance {}
108
109impl TryFrom<Element> for ServiceInstance {
110    type Error = AutosarAbstractionError;
111
112    fn try_from(element: Element) -> Result<Self, Self::Error> {
113        match element.element_name() {
114            ElementName::ProvidedServiceInstance => Ok(ServiceInstance::Provided(ProvidedServiceInstance(element))),
115            ElementName::ConsumedServiceInstance => Ok(ServiceInstance::Consumed(ConsumedServiceInstance(element))),
116            _ => Err(AutosarAbstractionError::InvalidParameter(
117                "Element is not a ServiceInstance".to_string(),
118            )),
119        }
120    }
121}
122
123//##################################################################
124
125/// A `ProvidedServiceInstance` is a service that is provided by an ECU
126#[derive(Debug, Clone, PartialEq, Eq, Hash)]
127pub struct ProvidedServiceInstance(Element);
128
129impl AbstractionElement for ProvidedServiceInstance {
130    fn element(&self) -> &Element {
131        &self.0
132    }
133}
134
135impl IdentifiableAbstractionElement for ProvidedServiceInstance {}
136
137impl TryFrom<Element> for ProvidedServiceInstance {
138    type Error = AutosarAbstractionError;
139
140    fn try_from(element: Element) -> Result<Self, Self::Error> {
141        // hierarchy: ServiceInstances -> ProvidedServiceInstance
142        let parent_name = element.parent()?.map(|p| p.element_name());
143        if !matches!(parent_name, Some(ElementName::ServiceInstances)) {
144            return Err(AutosarAbstractionError::ConversionError {
145                element,
146                dest: "ProvidedServiceInstance".to_string(),
147            });
148        }
149
150        if element.element_name() == ElementName::ProvidedServiceInstance {
151            Ok(Self(element))
152        } else {
153            Err(AutosarAbstractionError::ConversionError {
154                element,
155                dest: "ProvidedServiceInstance".to_string(),
156            })
157        }
158    }
159}
160
161impl ProvidedServiceInstance {
162    pub(crate) fn new(
163        name: &str,
164        parent: &Element,
165        service_identifier: u16,
166        instance_identifier: u16,
167        major_version: u32,
168        minor_version: u32,
169    ) -> Result<Self, AutosarAbstractionError> {
170        let psi_elem = parent.create_named_sub_element(ElementName::ProvidedServiceInstance, name)?;
171        let psi = Self(psi_elem);
172
173        psi.set_service_identifier(service_identifier)?;
174        psi.set_instance_identifier(instance_identifier)?;
175        psi.set_major_version(major_version)?;
176        psi.set_minor_version(minor_version)?;
177
178        Ok(psi)
179    }
180
181    /// set the service identifier of this `ProvidedServiceInstance`
182    pub fn set_service_identifier(&self, service_identifier: u16) -> Result<(), AutosarAbstractionError> {
183        self.0
184            .get_or_create_sub_element(ElementName::ServiceIdentifier)?
185            .set_character_data(u64::from(service_identifier))?;
186        Ok(())
187    }
188
189    /// get the service identifier of this `ProvidedServiceInstance`
190    #[must_use]
191    pub fn service_identifier(&self) -> Option<u16> {
192        self.0
193            .get_sub_element(ElementName::ServiceIdentifier)
194            .and_then(|si| si.character_data())
195            .and_then(|cdata| cdata.parse_integer())
196    }
197
198    /// set the instance identifier of this `ProvidedServiceInstance`
199    pub fn set_instance_identifier(&self, instance_identifier: u16) -> Result<(), AutosarAbstractionError> {
200        self.0
201            .get_or_create_sub_element(ElementName::InstanceIdentifier)?
202            .set_character_data(u64::from(instance_identifier))?;
203        Ok(())
204    }
205
206    /// get the instance identifier of this `ProvidedServiceInstance`
207    #[must_use]
208    pub fn instance_identifier(&self) -> Option<u16> {
209        self.0
210            .get_sub_element(ElementName::InstanceIdentifier)
211            .and_then(|ii| ii.character_data())
212            .and_then(|cdata| cdata.parse_integer())
213    }
214
215    /// set the major version of this `ProvidedServiceInstance`
216    pub fn set_major_version(&self, major_version: u32) -> Result<(), AutosarAbstractionError> {
217        self.0
218            .get_or_create_sub_element(ElementName::MajorVersion)?
219            .set_character_data(u64::from(major_version))?;
220        Ok(())
221    }
222
223    /// get the major version of this `ProvidedServiceInstance`
224    #[must_use]
225    pub fn major_version(&self) -> Option<u32> {
226        self.0
227            .get_sub_element(ElementName::MajorVersion)
228            .and_then(|mv| mv.character_data())
229            .and_then(|cdata| cdata.parse_integer())
230    }
231
232    /// set the minor version of this `ProvidedServiceInstance`
233    pub fn set_minor_version(&self, minor_version: u32) -> Result<(), AutosarAbstractionError> {
234        self.0
235            .get_or_create_sub_element(ElementName::MinorVersion)?
236            .set_character_data(u64::from(minor_version))?;
237        Ok(())
238    }
239
240    /// get the minor version of this `ProvidedServiceInstance`
241    #[must_use]
242    pub fn minor_version(&self) -> Option<u32> {
243        self.0
244            .get_sub_element(ElementName::MinorVersion)
245            .and_then(|mv| mv.character_data())
246            .and_then(|cdata| cdata.parse_integer())
247    }
248
249    /// create a new `EventHandler` in this `ProvidedServiceInstance`
250    pub fn create_event_handler(
251        &self,
252        name: &str,
253        event_group_identifier: u32,
254    ) -> Result<EventHandler, AutosarAbstractionError> {
255        let ehs = self.element().get_or_create_sub_element(ElementName::EventHandlers)?;
256        EventHandler::new(name, &ehs, event_group_identifier)
257    }
258
259    /// get the `EventHandler`s in this `ProvidedServiceInstance`
260    pub fn event_handlers(&self) -> impl Iterator<Item = EventHandler> + Send + use<> {
261        self.element()
262            .get_sub_element(ElementName::EventHandlers)
263            .into_iter()
264            .flat_map(|ehs| ehs.sub_elements())
265            .filter_map(|eh| EventHandler::try_from(eh).ok())
266    }
267
268    /// set a local unicast address for this `ProvidedServiceInstance`
269    ///
270    /// The PSI may use two local unicast addresses, one each for UDP and TCP.
271    /// The unicast address is used to assign the service to a specific ECU, and may not be empty.
272    pub fn set_local_unicast_address(&self, address: &SocketAddress) -> Result<(), AutosarAbstractionError> {
273        set_local_unicast_address(self.element(), address)
274    }
275
276    /// get the local unicast addresses
277    pub fn local_unicast_addresses(&self) -> impl Iterator<Item = LocalUnicastAddress> + Send + use<> {
278        local_unicast_addresses_iter(self.element())
279    }
280
281    /// set the SD server instance configuration for this `ProvidedServiceInstance`
282    pub fn set_sd_server_instance_config(
283        &self,
284        config: &SomeipSdServerServiceInstanceConfig,
285    ) -> Result<(), AutosarAbstractionError> {
286        self.element()
287            .get_or_create_sub_element(ElementName::SdServerTimerConfigs)?
288            .create_sub_element(ElementName::SomeipSdServerServiceInstanceConfigRefConditional)?
289            .create_sub_element(ElementName::SomeipSdServerServiceInstanceConfigRef)?
290            .set_reference_target(config.element())?;
291        Ok(())
292    }
293
294    /// get the SD server instance configuration for this `ProvidedServiceInstance`
295    #[must_use]
296    pub fn sd_server_instance_config(&self) -> Option<SomeipSdServerServiceInstanceConfig> {
297        let ref_elem = self
298            .element()
299            .get_sub_element(ElementName::SdServerTimerConfigs)?
300            .get_sub_element(ElementName::SomeipSdServerServiceInstanceConfigRefConditional)?
301            .get_sub_element(ElementName::SomeipSdServerServiceInstanceConfigRef)?
302            .get_reference_target()
303            .ok()?;
304        SomeipSdServerServiceInstanceConfig::try_from(ref_elem).ok()
305    }
306}
307
308//##################################################################
309
310/// An `EventHandler` describes the handling of a single event in a `ProvidedServiceInstance`
311#[derive(Debug, Clone, PartialEq, Eq, Hash)]
312pub struct EventHandler(Element);
313
314impl AbstractionElement for EventHandler {
315    fn element(&self) -> &Element {
316        &self.0
317    }
318}
319
320impl IdentifiableAbstractionElement for EventHandler {}
321
322impl TryFrom<Element> for EventHandler {
323    type Error = AutosarAbstractionError;
324
325    fn try_from(element: Element) -> Result<Self, Self::Error> {
326        // hierarchy: ServiceInstanceCollectionSet(named) -> ServiceInstances -> ProvidedServiceInstance(named) -> EventHandlers -> EventHandler(named)
327        let parent_name = element
328            .named_parent()?
329            .and_then(|p| p.named_parent().ok().flatten())
330            .map(|p| p.element_name());
331        if !matches!(parent_name, Some(ElementName::ServiceInstanceCollectionSet)) {
332            return Err(AutosarAbstractionError::ConversionError {
333                element,
334                dest: "EventHandler".to_string(),
335            });
336        }
337
338        if element.element_name() == ElementName::EventHandler {
339            Ok(Self(element))
340        } else {
341            Err(AutosarAbstractionError::ConversionError {
342                element,
343                dest: "EventHandler".to_string(),
344            })
345        }
346    }
347}
348
349impl EventHandler {
350    pub(crate) fn new(
351        name: &str,
352        parent: &Element,
353        event_group_identifier: u32,
354    ) -> Result<Self, AutosarAbstractionError> {
355        let evgrp_elem = parent.create_named_sub_element(ElementName::EventHandler, name)?;
356        let evgrp = Self(evgrp_elem);
357
358        evgrp.set_event_group_identifier(event_group_identifier)?;
359
360        Ok(evgrp)
361    }
362
363    /// set the event group identifier of this `EventHandler`
364    pub fn set_event_group_identifier(&self, event_group_identifier: u32) -> Result<(), AutosarAbstractionError> {
365        self.0
366            .get_or_create_sub_element(ElementName::EventGroupIdentifier)?
367            .set_character_data(u64::from(event_group_identifier))?;
368        Ok(())
369    }
370
371    /// get the event group identifier of this `EventHandler`
372    #[must_use]
373    pub fn event_group_identifier(&self) -> Option<u32> {
374        self.0
375            .get_sub_element(ElementName::EventGroupIdentifier)
376            .and_then(|egi| egi.character_data())
377            .and_then(|cdata| cdata.parse_integer())
378    }
379
380    /// create a new `PduActivationRoutingGroup` in this `EventHandler`
381    pub fn create_pdu_activation_routing_group(
382        &self,
383        name: &str,
384        event_group_control_type: EventGroupControlType,
385    ) -> Result<PduActivationRoutingGroup, AutosarAbstractionError> {
386        let parent = self
387            .element()
388            .get_or_create_sub_element(ElementName::PduActivationRoutingGroups)?;
389        PduActivationRoutingGroup::new(name, &parent, event_group_control_type)
390    }
391
392    /// get the `PduActivationRoutingGroup`s in this `EventHandler`
393    pub fn pdu_activation_routing_groups(&self) -> impl Iterator<Item = PduActivationRoutingGroup> + Send + use<> {
394        self.element()
395            .get_sub_element(ElementName::PduActivationRoutingGroups)
396            .into_iter()
397            .flat_map(|pargs| pargs.sub_elements())
398            .filter_map(|parg| PduActivationRoutingGroup::try_from(parg).ok())
399    }
400
401    /// set the SD server event group timing configuration for this `EventHandler`
402    pub fn set_sd_server_event_group_timing_config(
403        &self,
404        config: &SomeipSdServerEventGroupTimingConfig,
405    ) -> Result<(), AutosarAbstractionError> {
406        self.element()
407            .get_or_create_sub_element(ElementName::SdServerEgTimingConfigs)?
408            .create_sub_element(ElementName::SomeipSdServerEventGroupTimingConfigRefConditional)?
409            .create_sub_element(ElementName::SomeipSdServerEventGroupTimingConfigRef)?
410            .set_reference_target(config.element())?;
411        Ok(())
412    }
413
414    /// get the SD server event group timing configuration for this `EventHandler`
415    #[must_use]
416    pub fn sd_server_event_group_timing_config(&self) -> Option<SomeipSdServerEventGroupTimingConfig> {
417        let ref_elem = self
418            .element()
419            .get_sub_element(ElementName::SdServerEgTimingConfigs)?
420            .get_sub_element(ElementName::SomeipSdServerEventGroupTimingConfigRefConditional)?
421            .get_sub_element(ElementName::SomeipSdServerEventGroupTimingConfigRef)?
422            .get_reference_target()
423            .ok()?;
424        SomeipSdServerEventGroupTimingConfig::try_from(ref_elem).ok()
425    }
426}
427
428//##################################################################
429
430/// A `ConsumedServiceInstance` is a service that is consumed by an ECU
431#[derive(Debug, Clone, PartialEq, Eq, Hash)]
432pub struct ConsumedServiceInstance(Element);
433
434impl AbstractionElement for ConsumedServiceInstance {
435    fn element(&self) -> &Element {
436        &self.0
437    }
438}
439
440impl IdentifiableAbstractionElement for ConsumedServiceInstance {}
441
442impl TryFrom<Element> for ConsumedServiceInstance {
443    type Error = AutosarAbstractionError;
444
445    fn try_from(element: Element) -> Result<Self, Self::Error> {
446        // hierarchy: ServiceInstances -> ConsumedServiceInstance
447        let parent_name = element.parent()?.map(|p| p.element_name());
448        if !matches!(parent_name, Some(ElementName::ServiceInstances)) {
449            return Err(AutosarAbstractionError::ConversionError {
450                element,
451                dest: "ConsumedServiceInstance".to_string(),
452            });
453        }
454
455        if element.element_name() == ElementName::ConsumedServiceInstance {
456            Ok(Self(element))
457        } else {
458            Err(AutosarAbstractionError::ConversionError {
459                element,
460                dest: "ConsumedServiceInstance".to_string(),
461            })
462        }
463    }
464}
465
466impl ConsumedServiceInstance {
467    pub(crate) fn new(
468        name: &str,
469        parent: &Element,
470        service_identifier: u16,
471        instance_identifier: u16,
472        major_version: u32,
473        minor_version: &str,
474    ) -> Result<Self, AutosarAbstractionError> {
475        let csi_elem = parent.create_named_sub_element(ElementName::ConsumedServiceInstance, name)?;
476        let csi = Self(csi_elem);
477
478        csi.set_service_identifier(service_identifier)?;
479        csi.set_instance_identifier(instance_identifier)?;
480        csi.set_major_version(major_version)?;
481        csi.set_minor_version(minor_version)?;
482
483        Ok(csi)
484    }
485
486    /// set the service identifier of this `ConsumedServiceInstance`
487    pub fn set_service_identifier(&self, service_identifier: u16) -> Result<(), AutosarAbstractionError> {
488        self.0
489            .get_or_create_sub_element(ElementName::ServiceIdentifier)?
490            .set_character_data(u64::from(service_identifier))?;
491        Ok(())
492    }
493
494    /// get the service identifier of this `ConsumedServiceInstance`
495    #[must_use]
496    pub fn service_identifier(&self) -> Option<u16> {
497        self.0
498            .get_sub_element(ElementName::ServiceIdentifier)
499            .and_then(|si| si.character_data())
500            .and_then(|cdata| cdata.parse_integer())
501    }
502
503    /// set the instance identifier of this `ConsumedServiceInstance`
504    pub fn set_instance_identifier(&self, instance_identifier: u16) -> Result<(), AutosarAbstractionError> {
505        self.0
506            .get_or_create_sub_element(ElementName::InstanceIdentifier)?
507            .set_character_data(u64::from(instance_identifier))?;
508        Ok(())
509    }
510
511    /// get the instance identifier of this `ConsumedServiceInstance`
512    #[must_use]
513    pub fn instance_identifier(&self) -> Option<u16> {
514        self.0
515            .get_sub_element(ElementName::InstanceIdentifier)
516            .and_then(|ii| ii.character_data())
517            .and_then(|cdata| cdata.parse_integer())
518    }
519
520    /// set the major version of this `ConsumedServiceInstance`
521    pub fn set_major_version(&self, major_version: u32) -> Result<(), AutosarAbstractionError> {
522        self.0
523            .get_or_create_sub_element(ElementName::MajorVersion)?
524            .set_character_data(u64::from(major_version))?;
525        Ok(())
526    }
527
528    /// get the major version of this `ConsumedServiceInstance`
529    #[must_use]
530    pub fn major_version(&self) -> Option<u32> {
531        self.0
532            .get_sub_element(ElementName::MajorVersion)
533            .and_then(|mv| mv.character_data())
534            .and_then(|cdata| cdata.parse_integer())
535    }
536
537    /// set the minor version of this `ConsumedServiceInstance`
538    ///
539    /// The minor version can be a number or the String "ANY".
540    pub fn set_minor_version(&self, minor_version: &str) -> Result<(), AutosarAbstractionError> {
541        self.0
542            .get_or_create_sub_element(ElementName::MinorVersion)?
543            .set_character_data(minor_version)?;
544        Ok(())
545    }
546
547    /// get the minor version of this `ConsumedServiceInstance`
548    ///
549    /// The minor version can be a number or the String "ANY".
550    #[must_use]
551    pub fn minor_version(&self) -> Option<String> {
552        self.0
553            .get_sub_element(ElementName::MinorVersion)
554            .and_then(|mv| mv.character_data())
555            .and_then(|cdata| cdata.string_value())
556    }
557
558    /// create a new `ConsumedEventGrup` in this `ConsumedServiceInstance`
559    pub fn create_consumed_event_group(
560        &self,
561        name: &str,
562        event_group_identifier: u32,
563    ) -> Result<ConsumedEventGroup, AutosarAbstractionError> {
564        let cegs = self
565            .element()
566            .get_or_create_sub_element(ElementName::ConsumedEventGroups)?;
567        ConsumedEventGroup::new(name, &cegs, event_group_identifier)
568    }
569
570    /// get the `ConsumedEventGroup`s in this `ConsumedServiceInstance`
571    pub fn consumed_event_groups(&self) -> impl Iterator<Item = ConsumedEventGroup> + Send + use<> {
572        self.element()
573            .get_sub_element(ElementName::ConsumedEventGroups)
574            .into_iter()
575            .flat_map(|cegs| cegs.sub_elements())
576            .filter_map(|ceg| ConsumedEventGroup::try_from(ceg).ok())
577    }
578
579    /// set a local unicast address for this `ConsumedServiceInstance`
580    ///
581    /// The CSI may use two local unicast addresses, one each for UDP and TCP.
582    /// If the consumed service instance does not specify a local unicast address
583    /// because it only receives multicast messages, then the `ConsumedEventGroup`
584    /// must have an eventMulticastAddress.
585    pub fn set_local_unicast_address(&self, address: &SocketAddress) -> Result<(), AutosarAbstractionError> {
586        set_local_unicast_address(self.element(), address)
587    }
588
589    /// get the local unicast addresses
590    pub fn local_unicast_addresses(&self) -> impl Iterator<Item = LocalUnicastAddress> + Send + use<> {
591        local_unicast_addresses_iter(self.element())
592    }
593
594    /// set the SD client instance configuration for this `ConsumedServiceInstance`
595    pub fn set_sd_client_instance_config(
596        &self,
597        config: &SomeipSdClientServiceInstanceConfig,
598    ) -> Result<(), AutosarAbstractionError> {
599        self.element()
600            .get_or_create_sub_element(ElementName::SdClientTimerConfigs)?
601            .create_sub_element(ElementName::SomeipSdClientServiceInstanceConfigRefConditional)?
602            .create_sub_element(ElementName::SomeipSdClientServiceInstanceConfigRef)?
603            .set_reference_target(config.element())?;
604        Ok(())
605    }
606
607    /// get the SD client instance configuration for this `ConsumedServiceInstance`
608    #[must_use]
609    pub fn sd_client_instance_config(&self) -> Option<SomeipSdClientServiceInstanceConfig> {
610        let ref_elem = self
611            .element()
612            .get_sub_element(ElementName::SdClientTimerConfigs)?
613            .get_sub_element(ElementName::SomeipSdClientServiceInstanceConfigRefConditional)?
614            .get_sub_element(ElementName::SomeipSdClientServiceInstanceConfigRef)?
615            .get_reference_target()
616            .ok()?;
617        SomeipSdClientServiceInstanceConfig::try_from(ref_elem).ok()
618    }
619}
620
621//##################################################################
622
623/// A `ConsumedEventGroup` is a group of events in a `ConsumedServiceInstance` that are consumed by an ECU
624#[derive(Debug, Clone, PartialEq, Eq, Hash)]
625pub struct ConsumedEventGroup(Element);
626
627impl AbstractionElement for ConsumedEventGroup {
628    fn element(&self) -> &Element {
629        &self.0
630    }
631}
632
633impl IdentifiableAbstractionElement for ConsumedEventGroup {}
634
635impl TryFrom<Element> for ConsumedEventGroup {
636    type Error = AutosarAbstractionError;
637
638    fn try_from(element: Element) -> Result<Self, Self::Error> {
639        // hierarchy: ServiceInstanceCollectionSet(named) -> ServiceInstances -> ConsumedServiceInstance(named) -> ConsumedEventGroups -> ConsumedEventGroup(named)
640        let parent_name = element
641            .named_parent()?
642            .and_then(|p| p.named_parent().ok().flatten())
643            .map(|p| p.element_name());
644        if !matches!(parent_name, Some(ElementName::ServiceInstanceCollectionSet)) {
645            return Err(AutosarAbstractionError::ConversionError {
646                element,
647                dest: "ConsumedEventGroup".to_string(),
648            });
649        }
650
651        if element.element_name() == ElementName::ConsumedEventGroup {
652            Ok(Self(element))
653        } else {
654            Err(AutosarAbstractionError::ConversionError {
655                element,
656                dest: "ConsumedEventGroup".to_string(),
657            })
658        }
659    }
660}
661
662impl ConsumedEventGroup {
663    pub(crate) fn new(
664        name: &str,
665        parent: &Element,
666        event_group_identifier: u32,
667    ) -> Result<Self, AutosarAbstractionError> {
668        let ceg_elem = parent.create_named_sub_element(ElementName::ConsumedEventGroup, name)?;
669        let ceg = Self(ceg_elem);
670        ceg.set_event_group_identifier(event_group_identifier)?;
671
672        Ok(ceg)
673    }
674
675    /// set the event group identifier of this `ConsumedEventGroup`
676    pub fn set_event_group_identifier(&self, event_group_identifier: u32) -> Result<(), AutosarAbstractionError> {
677        self.0
678            .get_or_create_sub_element(ElementName::EventGroupIdentifier)?
679            .set_character_data(u64::from(event_group_identifier))?;
680        Ok(())
681    }
682
683    /// get the event group identifier of this `ConsumedEventGroup`
684    #[must_use]
685    pub fn event_group_identifier(&self) -> Option<u32> {
686        self.0
687            .get_sub_element(ElementName::EventGroupIdentifier)
688            .and_then(|egi| egi.character_data())
689            .and_then(|cdata| cdata.parse_integer())
690    }
691
692    /// create a new `PduActivationRoutingGroup` in this `ConsumedEventGroup`
693    pub fn create_pdu_activation_routing_group(
694        &self,
695        name: &str,
696        event_group_control_type: EventGroupControlType,
697    ) -> Result<PduActivationRoutingGroup, AutosarAbstractionError> {
698        let parent = self
699            .element()
700            .get_or_create_sub_element(ElementName::PduActivationRoutingGroups)?;
701        PduActivationRoutingGroup::new(name, &parent, event_group_control_type)
702    }
703
704    /// iterate over the `PduActivationRoutingGroup`s in this `ConsumedEventGroup`
705    pub fn pdu_activation_routing_groups(&self) -> impl Iterator<Item = PduActivationRoutingGroup> + Send + use<> {
706        self.element()
707            .get_sub_element(ElementName::PduActivationRoutingGroups)
708            .into_iter()
709            .flat_map(|pargs| pargs.sub_elements())
710            .filter_map(|parg| PduActivationRoutingGroup::try_from(parg).ok())
711    }
712
713    /// add an event multicast address to this `ConsumedEventGroup`
714    pub fn add_event_multicast_address(&self, address: &SocketAddress) -> Result<(), AutosarAbstractionError> {
715        let Some(application_endpoint) = address.element().get_sub_element(ElementName::ApplicationEndpoint) else {
716            return Err(AutosarAbstractionError::InvalidParameter(
717                "Can't add the event multicast address: The target SocketAddress does not have an ApplicationEndpoint, so it can't be used".to_string(),
718            ));
719        };
720
721        let container = self
722            .element()
723            .get_or_create_sub_element(ElementName::EventMulticastAddresss)?;
724        container
725            .create_sub_element(ElementName::ApplicationEndpointRefConditional)?
726            .create_sub_element(ElementName::ApplicationEndpointRef)?
727            .set_reference_target(&application_endpoint)?;
728
729        Ok(())
730    }
731
732    /// get the event multicast addresses
733    pub fn event_multicast_addresses(&self) -> impl Iterator<Item = SocketAddress> + Send + use<> {
734        self.element()
735            .get_sub_element(ElementName::EventMulticastAddresss)
736            .into_iter()
737            .flat_map(|addresses| addresses.sub_elements())
738            .filter_map(|app_endpoint_ref_cond| {
739                app_endpoint_ref_cond.get_sub_element(ElementName::ApplicationEndpointRef)
740            })
741            .filter_map(|app_endpoint_ref| app_endpoint_ref.get_reference_target().ok())
742            .filter_map(|app_endpoint| app_endpoint.named_parent().ok().flatten())
743            .filter_map(|sockaddr| SocketAddress::try_from(sockaddr).ok())
744    }
745
746    /// set the SD client timer configuration for this `ConsumedEventGroup`
747    pub fn set_sd_client_timer_config(
748        &self,
749        config: &SomeipSdClientEventGroupTimingConfig,
750    ) -> Result<(), AutosarAbstractionError> {
751        self.element()
752            .get_or_create_sub_element(ElementName::SdClientTimerConfigs)?
753            .create_sub_element(ElementName::SomeipSdClientEventGroupTimingConfigRefConditional)?
754            .create_sub_element(ElementName::SomeipSdClientEventGroupTimingConfigRef)?
755            .set_reference_target(config.element())?;
756        Ok(())
757    }
758
759    /// get the SD client timer configuration for this `ConsumedEventGroup`
760    #[must_use]
761    pub fn sd_client_timer_config(&self) -> Option<SomeipSdClientEventGroupTimingConfig> {
762        let ref_elem = self
763            .element()
764            .get_sub_element(ElementName::SdClientTimerConfigs)?
765            .get_sub_element(ElementName::SomeipSdClientEventGroupTimingConfigRefConditional)?
766            .get_sub_element(ElementName::SomeipSdClientEventGroupTimingConfigRef)?
767            .get_reference_target()
768            .ok()?;
769        SomeipSdClientEventGroupTimingConfig::try_from(ref_elem).ok()
770    }
771}
772
773//##################################################################
774
775/// A `LocalUnicastAddress` is a local address (TCP or UDP) that can be used for a `ProvidedServiceInstance` or `ConsumedServiceInstance`
776#[derive(Debug, Clone, PartialEq, Eq, Hash)]
777pub enum LocalUnicastAddress {
778    /// A UDP address
779    Udp(SocketAddress),
780    /// A TCP address
781    Tcp(SocketAddress),
782}
783
784/// helper function for both `ConsumedServiceInstance` and `ProvidedServiceInstance`
785fn set_local_unicast_address(parent: &Element, target_socket: &SocketAddress) -> Result<(), AutosarAbstractionError> {
786    let Some(target_appendpoint) = target_socket
787        .element()
788        .get_sub_element(ElementName::ApplicationEndpoint)
789    else {
790        return Err(AutosarAbstractionError::InvalidParameter(
791            "Can't set the local address: The target SocketAddress does not have an ApplicationEndpoint, so it can't be used".to_string(),
792        ));
793    };
794    let Some(tp_config) = target_socket.tp_config() else {
795        return Err(AutosarAbstractionError::InvalidParameter(
796            "Can't set the local address: The target SocketAddress does not have a TP configuration, so it can't be used".to_string(),
797        ));
798    };
799
800    let addresses_container = match parent.get_sub_element(ElementName::LocalUnicastAddresss) {
801        Some(addresses_container) => {
802            // LOCAL-UNICAST-ADDRESSS -> collection of(APPLICATION-ENDPOINT-REF-CONDITIONAL -> APPLICATION-ENDPOINT-REF)
803            // check if an address of the given type already exists and remove it
804            for existing_ref_elem in addresses_container.sub_elements() {
805                // existing_ref_elem is an APPLICATION-ENDPOINT-REF-CONDITIONAL
806                // find the referenced APPLICATION-ENDPOINT, go up to the parent SocketAddress, and get the
807                // TP configuration in order to determine if this is a TCP or UDP address
808                if let Some(existing_tp_config) = existing_ref_elem
809                    .get_sub_element(ElementName::ApplicationEndpointRef)
810                    .and_then(|aer| aer.get_reference_target().ok())
811                    .and_then(|ae| ae.named_parent().ok().flatten())
812                    .and_then(|sockaddr| SocketAddress::try_from(sockaddr).ok())
813                    .and_then(|sa| sa.tp_config())
814                {
815                    // if the target socket address has the same type as the new address, remove the old one
816                    if matches!(
817                        (existing_tp_config, &tp_config),
818                        (TpConfig::TcpTp { .. }, &TpConfig::TcpTp { .. })
819                            | (TpConfig::UdpTp { .. }, &TpConfig::UdpTp { .. })
820                    ) {
821                        addresses_container.remove_sub_element(existing_ref_elem)?;
822                    }
823                }
824            }
825            addresses_container
826        }
827        None => parent.create_sub_element(ElementName::LocalUnicastAddresss)?,
828    };
829
830    // no distinction between TCP and UDP addresses is needed when creating the new reference
831    addresses_container
832        .create_sub_element(ElementName::ApplicationEndpointRefConditional)?
833        .create_sub_element(ElementName::ApplicationEndpointRef)?
834        .set_reference_target(&target_appendpoint)?;
835    Ok(())
836}
837
838fn local_unicast_addresses_iter(element: &Element) -> impl Iterator<Item = LocalUnicastAddress> + Send + use<> {
839    // first, build an iterator over all the ApplicationEndpoint Elements referenced by the LocalUnicastAddresss container
840    let app_endpoint_iter = element
841        .get_sub_element(ElementName::LocalUnicastAddresss)
842        .into_iter()
843        .flat_map(|addresses| addresses.sub_elements())
844        .filter_map(|app_endpoint_ref_cond| app_endpoint_ref_cond.get_sub_element(ElementName::ApplicationEndpointRef))
845        .filter_map(|app_endpoint_ref| app_endpoint_ref.get_reference_target().ok());
846
847    // (split for readability to avoid a long chain of filter_map calls)
848
849    // for each ApplicationEndpoint, get the containing SocketAddress, and then wrap it in a LocalUnicastAddress of the correct type
850    app_endpoint_iter
851        .filter_map(|ae| ae.named_parent().ok().flatten())
852        .filter_map(|sockaddr| SocketAddress::try_from(sockaddr).ok())
853        .filter_map(|sa| {
854            sa.tp_config().map(|tp_config| match tp_config {
855                TpConfig::TcpTp { .. } => LocalUnicastAddress::Tcp(sa),
856                TpConfig::UdpTp { .. } => LocalUnicastAddress::Udp(sa),
857            })
858        })
859}
860
861//##################################################################
862
863/// A group of Pdus that can be activated or deactivated for transmission over a socket connection.
864/// It is used by `EventHandler`s in `ProvidedServiceInstance`s and `ConsumedServiceInstance`s.
865#[derive(Debug, Clone, PartialEq, Eq, Hash)]
866pub struct PduActivationRoutingGroup(Element);
867abstraction_element!(PduActivationRoutingGroup, PduActivationRoutingGroup);
868impl IdentifiableAbstractionElement for PduActivationRoutingGroup {}
869
870impl PduActivationRoutingGroup {
871    pub(crate) fn new(
872        name: &str,
873        parent: &Element,
874        event_group_control_type: EventGroupControlType,
875    ) -> Result<Self, AutosarAbstractionError> {
876        let elem = parent.create_named_sub_element(ElementName::PduActivationRoutingGroup, name)?;
877        let parg = Self(elem);
878        parg.set_event_group_control_type(event_group_control_type)?;
879
880        Ok(parg)
881    }
882
883    /// set the event group control type of this `PduActivationRoutingGroup`
884    pub fn set_event_group_control_type(
885        &self,
886        event_group_control_type: EventGroupControlType,
887    ) -> Result<(), AutosarAbstractionError> {
888        self.0
889            .get_or_create_sub_element(ElementName::EventGroupControlType)?
890            .set_character_data::<EnumItem>(event_group_control_type.into())?;
891        Ok(())
892    }
893
894    /// get the event group control type of this `PduActivationRoutingGroup`
895    #[must_use]
896    pub fn event_group_control_type(&self) -> Option<EventGroupControlType> {
897        self.0
898            .get_sub_element(ElementName::EventGroupControlType)
899            .and_then(|egct| egct.character_data())
900            .and_then(|cdata| cdata.enum_value())
901            .and_then(|val| EventGroupControlType::try_from(val).ok())
902    }
903
904    /// add a reference to a `SoConIPduIdentifier` for UDP communication to this `PduActivationRoutingGroup`
905    pub fn add_ipdu_identifier_udp(
906        &self,
907        ipdu_identifier: &SoConIPduIdentifier,
908    ) -> Result<(), AutosarAbstractionError> {
909        let elem = self
910            .element()
911            .get_or_create_sub_element(ElementName::IPduIdentifierUdpRefs)?;
912        elem.create_sub_element(ElementName::IPduIdentifierUdpRef)?
913            .set_reference_target(ipdu_identifier.element())?;
914        Ok(())
915    }
916
917    /// get all `SoConIPduIdentifier`s for UDP communication in this `PduActivationRoutingGroup`
918    pub fn ipdu_identifiers_udp(&self) -> impl Iterator<Item = SoConIPduIdentifier> + Send + use<> {
919        self.element()
920            .get_sub_element(ElementName::IPduIdentifierUdpRefs)
921            .into_iter()
922            .flat_map(|refs| refs.sub_elements())
923            .filter_map(|ref_elem| ref_elem.get_reference_target().ok())
924            .filter_map(|target| SoConIPduIdentifier::try_from(target).ok())
925    }
926
927    /// add a reference to a `SoConIPduIdentifier` for TCP communication to this `PduActivationRoutingGroup`
928    pub fn add_ipdu_identifier_tcp(
929        &self,
930        ipdu_identifier: &SoConIPduIdentifier,
931    ) -> Result<(), AutosarAbstractionError> {
932        let elem = self
933            .element()
934            .get_or_create_sub_element(ElementName::IPduIdentifierTcpRefs)?;
935        elem.create_sub_element(ElementName::IPduIdentifierTcpRef)?
936            .set_reference_target(ipdu_identifier.element())?;
937        Ok(())
938    }
939
940    /// get all `SoConIPduIdentifier`s for TCP communication in this `PduActivationRoutingGroup`
941    pub fn ipdu_identifiers_tcp(&self) -> impl Iterator<Item = SoConIPduIdentifier> + Send + use<> {
942        self.element()
943            .get_sub_element(ElementName::IPduIdentifierTcpRefs)
944            .into_iter()
945            .flat_map(|refs| refs.sub_elements())
946            .filter_map(|ref_elem| ref_elem.get_reference_target().ok())
947            .filter_map(|target| SoConIPduIdentifier::try_from(target).ok())
948    }
949}
950
951//##################################################################
952
953/// A `SomeipSdServerServiceInstanceConfig` is a configuration for a `ProvidedServiceInstance`
954///
955/// This configuration is a named element that is created separately and can be used by multiple `ProvidedServiceInstance`s.
956///
957/// Use [`ArPackage::create_someip_sd_server_service_instance_config`] to create a new `SomeipSdServerServiceInstanceConfig`.
958#[derive(Debug, Clone, PartialEq, Eq, Hash)]
959pub struct SomeipSdServerServiceInstanceConfig(Element);
960abstraction_element!(SomeipSdServerServiceInstanceConfig, SomeipSdServerServiceInstanceConfig);
961impl IdentifiableAbstractionElement for SomeipSdServerServiceInstanceConfig {}
962
963impl SomeipSdServerServiceInstanceConfig {
964    /// create a new `SomeipSdServerServiceInstanceConfig` in the given package
965    pub(crate) fn new(name: &str, package: &ArPackage, ttl: u32) -> Result<Self, AutosarAbstractionError> {
966        let pkg_elem = package.element().get_or_create_sub_element(ElementName::Elements)?;
967        let elem = pkg_elem.create_named_sub_element(ElementName::SomeipSdServerServiceInstanceConfig, name)?;
968
969        elem.create_sub_element(ElementName::ServiceOfferTimeToLive)?
970            .set_character_data(u64::from(ttl))?;
971
972        Ok(Self(elem))
973    }
974
975    /// set the service offer time to live of this `SomeipSdServerServiceInstanceConfig`
976    pub fn set_service_offer_time_to_live(&self, ttl: u32) -> Result<(), AutosarAbstractionError> {
977        self.element()
978            .get_or_create_sub_element(ElementName::ServiceOfferTimeToLive)?
979            .set_character_data(u64::from(ttl))?;
980        Ok(())
981    }
982
983    /// get the service offer time to live of this `SomeipSdServerServiceInstanceConfig`
984    #[must_use]
985    pub fn service_offer_time_to_live(&self) -> Option<u32> {
986        self.element()
987            .get_sub_element(ElementName::ServiceOfferTimeToLive)
988            .and_then(|ttl| ttl.character_data())
989            .and_then(|cdata| cdata.parse_integer())
990    }
991
992    /// set the offer cyclic delay of this `SomeipSdServerServiceInstanceConfig`
993    pub fn set_offer_cyclic_delay(&self, delay: f64) -> Result<(), AutosarAbstractionError> {
994        self.element()
995            .get_or_create_sub_element(ElementName::OfferCyclicDelay)?
996            .set_character_data(delay)?;
997        Ok(())
998    }
999
1000    /// get the offer cyclic delay of this `SomeipSdServerServiceInstanceConfig`
1001    #[must_use]
1002    pub fn offer_cyclic_delay(&self) -> Option<f64> {
1003        self.element()
1004            .get_sub_element(ElementName::OfferCyclicDelay)
1005            .and_then(|ocd| ocd.character_data())
1006            .and_then(|cdata| cdata.parse_float())
1007    }
1008
1009    /// set the priority of this `SomeipSdServerServiceInstanceConfig`
1010    ///
1011    /// Available since R21-11 (`AUTOSAR_00050`)
1012    pub fn set_priority(&self, priority: u8) -> Result<(), AutosarAbstractionError> {
1013        // try to set it, but ignore the error if the element is not available
1014        if let Ok(priority_element) = self.element().get_or_create_sub_element(ElementName::Priority) {
1015            priority_element.set_character_data(u64::from(priority))?;
1016        }
1017        Ok(())
1018    }
1019
1020    /// get the priority of this `SomeipSdServerServiceInstanceConfig`
1021    #[must_use]
1022    pub fn priority(&self) -> Option<u8> {
1023        self.element()
1024            .get_sub_element(ElementName::Priority)
1025            .and_then(|p| p.character_data())
1026            .and_then(|cdata| cdata.parse_integer())
1027    }
1028
1029    /// set the initial offer behavior of this `SomeipSdServerServiceInstanceConfig`
1030    pub fn set_initial_offer_behavior(
1031        &self,
1032        initial_offer_behavior: &InitialSdDelayConfig,
1033    ) -> Result<(), AutosarAbstractionError> {
1034        let iob = self
1035            .element()
1036            .get_or_create_sub_element(ElementName::InitialOfferBehavior)?;
1037        initial_offer_behavior.set(&iob)?;
1038        Ok(())
1039    }
1040
1041    /// get the initial offer behavior of this `SomeipSdServerServiceInstanceConfig`
1042    #[must_use]
1043    pub fn initial_offer_behavior(&self) -> Option<InitialSdDelayConfig> {
1044        let iob = self.element().get_sub_element(ElementName::InitialOfferBehavior)?;
1045        InitialSdDelayConfig::get(&iob)
1046    }
1047
1048    /// set the request response delay of this `SomeipSdServerServiceInstanceConfig`
1049    pub fn set_request_response_delay(
1050        &self,
1051        request_response_delay: &RequestResponseDelay,
1052    ) -> Result<(), AutosarAbstractionError> {
1053        let rrd = self
1054            .element()
1055            .get_or_create_sub_element(ElementName::RequestResponseDelay)?;
1056        request_response_delay.set(&rrd)?;
1057        Ok(())
1058    }
1059
1060    /// get the request response delay of this `SomeipSdServerServiceInstanceConfig`
1061    #[must_use]
1062    pub fn request_response_delay(&self) -> Option<RequestResponseDelay> {
1063        let rrd = self.element().get_sub_element(ElementName::RequestResponseDelay)?;
1064        RequestResponseDelay::get(&rrd)
1065    }
1066}
1067
1068//##################################################################
1069
1070/// A `SomeipSdServerEventGroupTimingConfig` contains the configuration for the timing of an `EventHandler`
1071///
1072/// This configuration is a named element that is created separately and can be used by multiple `EventHandler`s.
1073///
1074/// Use [`ArPackage::create_someip_sd_server_event_group_timing_config`] to create a new `SomeipSdServerEventGroupTimingConfig`.
1075#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1076pub struct SomeipSdServerEventGroupTimingConfig(Element);
1077abstraction_element!(
1078    SomeipSdServerEventGroupTimingConfig,
1079    SomeipSdServerEventGroupTimingConfig
1080);
1081impl IdentifiableAbstractionElement for SomeipSdServerEventGroupTimingConfig {}
1082
1083impl SomeipSdServerEventGroupTimingConfig {
1084    /// create a new `SomeipSdServerEventGroupTimingConfig` in the given package
1085    pub(crate) fn new(
1086        name: &str,
1087        package: &ArPackage,
1088        request_response_delay: &RequestResponseDelay,
1089    ) -> Result<Self, AutosarAbstractionError> {
1090        let pkg_elem = package.element().get_or_create_sub_element(ElementName::Elements)?;
1091        let elem = pkg_elem.create_named_sub_element(ElementName::SomeipSdServerEventGroupTimingConfig, name)?;
1092        let rrd = elem.create_sub_element(ElementName::RequestResponseDelay)?;
1093        request_response_delay.set(&rrd)?;
1094
1095        Ok(Self(elem))
1096    }
1097
1098    /// set the request response delay of this `SomeipSdServerEventGroupTimingConfig`
1099    pub fn set_request_response_delay(
1100        &self,
1101        request_response_delay: &RequestResponseDelay,
1102    ) -> Result<(), AutosarAbstractionError> {
1103        let rrd = self
1104            .element()
1105            .get_or_create_sub_element(ElementName::RequestResponseDelay)?;
1106        request_response_delay.set(&rrd)?;
1107        Ok(())
1108    }
1109
1110    /// get the request response delay of this `SomeipSdServerEventGroupTimingConfig`
1111    #[must_use]
1112    pub fn request_response_delay(&self) -> Option<RequestResponseDelay> {
1113        let rrd = self.element().get_sub_element(ElementName::RequestResponseDelay)?;
1114        RequestResponseDelay::get(&rrd)
1115    }
1116}
1117
1118//##################################################################
1119
1120/// A `SomeipSdClientServiceInstanceConfig` is a configuration for a `ConsumedServiceInstance`
1121///
1122/// This configuration is a named element that is created separately and can be used by multiple `ConsumedServiceInstance`s.
1123///
1124/// Use [`ArPackage::create_someip_sd_client_service_instance_config`] to create a new `SomeipSdClientServiceInstanceConfig`.
1125#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1126pub struct SomeipSdClientServiceInstanceConfig(Element);
1127abstraction_element!(SomeipSdClientServiceInstanceConfig, SomeipSdClientServiceInstanceConfig);
1128impl IdentifiableAbstractionElement for SomeipSdClientServiceInstanceConfig {}
1129
1130impl SomeipSdClientServiceInstanceConfig {
1131    /// create a new `SomeipSdClientServiceInstanceConfig` in the given package
1132    pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
1133        let pkg_elem = package.element().get_or_create_sub_element(ElementName::Elements)?;
1134        let elem = pkg_elem.create_named_sub_element(ElementName::SomeipSdClientServiceInstanceConfig, name)?;
1135
1136        Ok(Self(elem))
1137    }
1138
1139    /// set the initial find behavior of this `SomeipSdClientServiceInstanceConfig`
1140    pub fn set_initial_find_behavior(
1141        &self,
1142        initial_find_behavior: &InitialSdDelayConfig,
1143    ) -> Result<(), AutosarAbstractionError> {
1144        let ifb = self
1145            .element()
1146            .get_or_create_sub_element(ElementName::InitialFindBehavior)?;
1147        initial_find_behavior.set(&ifb)?;
1148        Ok(())
1149    }
1150
1151    /// get the initial find behavior of this `SomeipSdClientServiceInstanceConfig`
1152    #[must_use]
1153    pub fn initial_find_behavior(&self) -> Option<InitialSdDelayConfig> {
1154        let ifb = self.element().get_sub_element(ElementName::InitialFindBehavior)?;
1155        InitialSdDelayConfig::get(&ifb)
1156    }
1157
1158    /// set the priority of this `SomeipSdClientServiceInstanceConfig`
1159    ///
1160    /// Available since R21-11 (`AUTOSAR_00050`)
1161    pub fn set_priority(&self, priority: u8) -> Result<(), AutosarAbstractionError> {
1162        // try to set it, but ignore the error if the element is not available
1163        if let Ok(priority_element) = self.element().get_or_create_sub_element(ElementName::Priority) {
1164            priority_element.set_character_data(u64::from(priority))?;
1165        }
1166        Ok(())
1167    }
1168
1169    /// get the priority of this `SomeipSdClientServiceInstanceConfig`
1170    #[must_use]
1171    pub fn priority(&self) -> Option<u8> {
1172        self.element()
1173            .get_sub_element(ElementName::Priority)
1174            .and_then(|p| p.character_data())
1175            .and_then(|cdata| cdata.parse_integer())
1176    }
1177}
1178
1179//##################################################################
1180
1181/// A `SomeipSdClientEventGroupTimingConfig` contains the configuration for the timing of a `ConsumedEventGroup`
1182///
1183/// This configuration is a named element that is created separately and can be used by multiple `ConsumedEventGroup`s.
1184///
1185/// Use [`ArPackage::create_someip_sd_client_event_group_timing_config`] to create a new `SomeipSdClientEventGroupTimingConfig`.
1186#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1187pub struct SomeipSdClientEventGroupTimingConfig(Element);
1188abstraction_element!(
1189    SomeipSdClientEventGroupTimingConfig,
1190    SomeipSdClientEventGroupTimingConfig
1191);
1192impl IdentifiableAbstractionElement for SomeipSdClientEventGroupTimingConfig {}
1193
1194impl SomeipSdClientEventGroupTimingConfig {
1195    /// create a new `SomeipSdClientEventGroupTimingConfig` in the given package
1196    pub(crate) fn new(name: &str, package: &ArPackage, time_to_live: u32) -> Result<Self, AutosarAbstractionError> {
1197        let pkg_elem = package.element().get_or_create_sub_element(ElementName::Elements)?;
1198        let elem = pkg_elem.create_named_sub_element(ElementName::SomeipSdClientEventGroupTimingConfig, name)?;
1199        elem.create_sub_element(ElementName::TimeToLive)?
1200            .set_character_data(u64::from(time_to_live))?;
1201
1202        Ok(Self(elem))
1203    }
1204
1205    /// set the time to live of this `SomeipSdClientEventGroupTimingConfig`
1206    pub fn set_time_to_live(&self, time_to_live: u32) -> Result<(), AutosarAbstractionError> {
1207        self.element()
1208            .get_or_create_sub_element(ElementName::TimeToLive)?
1209            .set_character_data(u64::from(time_to_live))?;
1210        Ok(())
1211    }
1212
1213    /// get the time to live of this `SomeipSdClientEventGroupTimingConfig`
1214    #[must_use]
1215    pub fn time_to_live(&self) -> Option<u32> {
1216        self.element()
1217            .get_sub_element(ElementName::TimeToLive)
1218            .and_then(|ttl| ttl.character_data())
1219            .and_then(|cdata| cdata.parse_integer())
1220    }
1221
1222    /// set the request response delay of this `SomeipSdClientEventGroupTimingConfig`
1223    pub fn set_request_response_delay(
1224        &self,
1225        request_response_delay: &RequestResponseDelay,
1226    ) -> Result<(), AutosarAbstractionError> {
1227        let rrd = self
1228            .element()
1229            .get_or_create_sub_element(ElementName::RequestResponseDelay)?;
1230        request_response_delay.set(&rrd)?;
1231        Ok(())
1232    }
1233
1234    /// get the request response delay of this `SomeipSdClientEventGroupTimingConfig`
1235    #[must_use]
1236    pub fn request_response_delay(&self) -> Option<RequestResponseDelay> {
1237        let rrd = self.element().get_sub_element(ElementName::RequestResponseDelay)?;
1238        RequestResponseDelay::get(&rrd)
1239    }
1240
1241    /// set the subscribe eventgroup retry delay of this `SomeipSdClientEventGroupTimingConfig`
1242    pub fn set_subscribe_eventgroup_retry_delay(
1243        &self,
1244        subscribe_eventgroup_retry_delay: f64,
1245    ) -> Result<(), AutosarAbstractionError> {
1246        self.element()
1247            .get_or_create_sub_element(ElementName::SubscribeEventgroupRetryDelay)?
1248            .set_character_data(subscribe_eventgroup_retry_delay)?;
1249        Ok(())
1250    }
1251
1252    /// get the subscribe eventgroup retry delay of this `SomeipSdClientEventGroupTimingConfig`
1253    #[must_use]
1254    pub fn subscribe_eventgroup_retry_delay(&self) -> Option<f64> {
1255        self.element()
1256            .get_sub_element(ElementName::SubscribeEventgroupRetryDelay)
1257            .and_then(|sgrd| sgrd.character_data())
1258            .and_then(|cdata| cdata.parse_float())
1259    }
1260
1261    /// set subscribe eventgroup retry max of this `SomeipSdClientEventGroupTimingConfig`
1262    pub fn set_subscribe_eventgroup_retry_max(
1263        &self,
1264        subscribe_eventgroup_retry_max: u32,
1265    ) -> Result<(), AutosarAbstractionError> {
1266        self.element()
1267            .get_or_create_sub_element(ElementName::SubscribeEventgroupRetryMax)?
1268            .set_character_data(u64::from(subscribe_eventgroup_retry_max))?;
1269        Ok(())
1270    }
1271
1272    /// get the value of subscribe eventgroup retry max of this `SomeipSdClientEventGroupTimingConfig`
1273    #[must_use]
1274    pub fn subscribe_eventgroup_retry_max(&self) -> Option<u32> {
1275        self.element()
1276            .get_sub_element(ElementName::SubscribeEventgroupRetryMax)
1277            .and_then(|sgrm| sgrm.character_data())
1278            .and_then(|cdata| cdata.parse_integer())
1279    }
1280}
1281
1282//##################################################################
1283
1284/// A `RequestResponseDelay` contains the minimum and maximum delay for a request-response cycle
1285#[derive(Debug, Clone, PartialEq)]
1286pub struct RequestResponseDelay {
1287    /// minimum value of the delay in seconds
1288    pub min_value: f64,
1289    /// maximum value of the delay in seconds
1290    pub max_value: f64,
1291}
1292
1293impl RequestResponseDelay {
1294    fn set(&self, element: &Element) -> Result<(), AutosarAbstractionError> {
1295        element
1296            .get_or_create_sub_element(ElementName::MinValue)?
1297            .set_character_data(self.min_value)?;
1298        element
1299            .get_or_create_sub_element(ElementName::MaxValue)?
1300            .set_character_data(self.max_value)?;
1301        Ok(())
1302    }
1303
1304    fn get(element: &Element) -> Option<Self> {
1305        let min_value = element
1306            .get_sub_element(ElementName::MinValue)
1307            .and_then(|rrd| rrd.character_data())
1308            .and_then(|cdata| cdata.parse_float())
1309            .unwrap_or(0.0);
1310        let max_value = element
1311            .get_sub_element(ElementName::MaxValue)
1312            .and_then(|rrd| rrd.character_data())
1313            .and_then(|cdata| cdata.parse_float())
1314            .unwrap_or(0.0);
1315        Some(Self { min_value, max_value })
1316    }
1317}
1318
1319//##################################################################
1320
1321/// A `InitialSdDelayConfig` contains the configuration for the initial delay of an SD client or server
1322#[derive(Debug, Clone, PartialEq)]
1323pub struct InitialSdDelayConfig {
1324    /// maximum value of the randomized delay in seconds
1325    pub initial_delay_max_value: f64,
1326    /// minimum value of the randomized delay in seconds
1327    pub initial_delay_min_value: f64,
1328    /// base delay for repetitions in seconds
1329    pub initial_repetitions_base_delay: Option<f64>,
1330    /// maximum number of repetitions
1331    pub initial_repetitions_max: Option<u32>,
1332}
1333
1334impl InitialSdDelayConfig {
1335    fn set(&self, element: &Element) -> Result<(), AutosarAbstractionError> {
1336        element
1337            .get_or_create_sub_element(ElementName::InitialDelayMaxValue)?
1338            .set_character_data(self.initial_delay_max_value)?;
1339        element
1340            .get_or_create_sub_element(ElementName::InitialDelayMinValue)?
1341            .set_character_data(self.initial_delay_min_value)?;
1342        if let Some(base_delay) = self.initial_repetitions_base_delay {
1343            element
1344                .get_or_create_sub_element(ElementName::InitialRepetitionsBaseDelay)?
1345                .set_character_data(base_delay)?;
1346        }
1347        if let Some(max_repetitions) = self.initial_repetitions_max {
1348            element
1349                .get_or_create_sub_element(ElementName::InitialRepetitionsMax)?
1350                .set_character_data(u64::from(max_repetitions))?;
1351        }
1352        Ok(())
1353    }
1354
1355    fn get(element: &Element) -> Option<Self> {
1356        let initial_delay_max_value = element
1357            .get_sub_element(ElementName::InitialDelayMaxValue)
1358            .and_then(|rrd| rrd.character_data())
1359            .and_then(|cdata| cdata.parse_float())?;
1360        let initial_delay_min_value = element
1361            .get_sub_element(ElementName::InitialDelayMinValue)
1362            .and_then(|rrd| rrd.character_data())
1363            .and_then(|cdata| cdata.parse_float())?;
1364        let initial_repetitions_base_delay = element
1365            .get_sub_element(ElementName::InitialRepetitionsBaseDelay)
1366            .and_then(|rrd| rrd.character_data())
1367            .and_then(|cdata| cdata.parse_float());
1368        let initial_repetitions_max = element
1369            .get_sub_element(ElementName::InitialRepetitionsMax)
1370            .and_then(|rrd| rrd.character_data())
1371            .and_then(|cdata| cdata.parse_integer());
1372        Some(Self {
1373            initial_delay_max_value,
1374            initial_delay_min_value,
1375            initial_repetitions_base_delay,
1376            initial_repetitions_max,
1377        })
1378    }
1379}
1380
1381//##################################################################
1382
1383/// A `SomipTpConfig` contains the configuration of individual `SomeIp` TP connections
1384#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1385pub struct SomeipTpConfig(Element);
1386abstraction_element!(SomeipTpConfig, SomeipTpConfig);
1387impl IdentifiableAbstractionElement for SomeipTpConfig {}
1388
1389impl SomeipTpConfig {
1390    pub(crate) fn new(name: &str, package: &ArPackage, cluster: &Cluster) -> Result<Self, AutosarAbstractionError> {
1391        let pkg_elem = package.element().get_or_create_sub_element(ElementName::Elements)?;
1392        let elem = pkg_elem.create_named_sub_element(ElementName::SomeipTpConfig, name)?;
1393
1394        elem.create_sub_element(ElementName::CommunicationClusterRef)?
1395            .set_reference_target(cluster.element())?;
1396
1397        Ok(Self(elem))
1398    }
1399
1400    /// get the communication cluster of this `SomeipTpConfig`
1401    #[must_use]
1402    pub fn cluster(&self) -> Option<Cluster> {
1403        self.element()
1404            .get_sub_element(ElementName::CommunicationClusterRef)
1405            .and_then(|ccr| ccr.get_reference_target().ok())
1406            .and_then(|target| Cluster::try_from(target).ok())
1407    }
1408
1409    /// create a new `SomeipTpChannel` in this `SomeipTpConfig`
1410    ///
1411    /// version >= `AUTOSAR_00046`
1412    pub fn create_someip_tp_channel(&self, name: &str) -> Result<SomeipTpChannel, AutosarAbstractionError> {
1413        let channels = self.element().get_or_create_sub_element(ElementName::TpChannels)?;
1414        SomeipTpChannel::new(name, &channels)
1415    }
1416
1417    /// iterate over all `SomeipTpChannel`s in this `SomeipTpConfig`
1418    pub fn someip_tp_channels(&self) -> impl Iterator<Item = SomeipTpChannel> + Send + use<> {
1419        self.element()
1420            .get_sub_element(ElementName::TpChannels)
1421            .into_iter()
1422            .flat_map(|channels| channels.sub_elements())
1423            .filter_map(|channel| SomeipTpChannel::try_from(channel).ok())
1424    }
1425
1426    /// create a new `SomeIp` TP connection in this `SomeipTpConfig`
1427    ///
1428    /// returns the `PduTriggering` that is created for the `TpSdu`
1429    pub fn create_someip_tp_connection(
1430        &self,
1431        tp_sdu: &ISignalIPdu,
1432        transport_pdu_triggering: &PduTriggering,
1433        tp_channel: Option<SomeipTpChannel>,
1434    ) -> Result<SomeipTpConnection, AutosarAbstractionError> {
1435        let connections = self.element().get_or_create_sub_element(ElementName::TpConnections)?;
1436        SomeipTpConnection::new(&connections, tp_sdu, transport_pdu_triggering, tp_channel)
1437    }
1438
1439    /// get all `SomeipTpConnection`s in this `SomeipTpConfig`
1440    pub fn someip_tp_connections(&self) -> impl Iterator<Item = SomeipTpConnection> + Send + use<> {
1441        self.element()
1442            .get_sub_element(ElementName::TpConnections)
1443            .into_iter()
1444            .flat_map(|connections| connections.sub_elements())
1445            .filter_map(|conn| SomeipTpConnection::try_from(conn).ok())
1446    }
1447}
1448
1449//##################################################################
1450
1451/// A `SomeipTpConnection` contains the configuration of a single `SomeIp` TP connection
1452#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1453pub struct SomeipTpConnection(Element);
1454abstraction_element!(SomeipTpConnection, SomeipTpConnection);
1455
1456impl SomeipTpConnection {
1457    pub(crate) fn new(
1458        parent: &Element,
1459        tp_sdu: &ISignalIPdu,
1460        transport_pdu_triggering: &PduTriggering,
1461        tp_channel: Option<SomeipTpChannel>,
1462    ) -> Result<Self, AutosarAbstractionError> {
1463        let conn_elem = parent.create_sub_element(ElementName::SomeipTpConnection)?;
1464        let conn = Self(conn_elem);
1465
1466        conn.set_transport_pdu_triggering(transport_pdu_triggering)?;
1467        conn.set_tp_sdu(tp_sdu)?;
1468        conn.set_tp_channel(tp_channel)?;
1469
1470        Ok(conn)
1471    }
1472
1473    /// get the `SomeipTpConfig` that contains this `SomeipTpConnection`
1474    pub fn someip_tp_config(&self) -> Result<SomeipTpConfig, AutosarAbstractionError> {
1475        let parent = self.element().named_parent()?.unwrap();
1476        SomeipTpConfig::try_from(parent)
1477    }
1478
1479    /// set the `PduTriggering` for the transport PDU of this `SomeipTpConnection`
1480    pub fn set_transport_pdu_triggering(
1481        &self,
1482        transport_pdu_triggering: &PduTriggering,
1483    ) -> Result<(), AutosarAbstractionError> {
1484        // check if the transport PDU is a GeneralPurposeIPdu
1485        let Some(Pdu::GeneralPurposeIPdu(gp_ipdu)) = transport_pdu_triggering.pdu() else {
1486            return Err(AutosarAbstractionError::InvalidParameter(
1487                "Invalid transport PDU for the SomeIpTpConnection: it must be a GeneralPurposeIPdu".to_string(),
1488            ));
1489        };
1490
1491        // check the category of the GeneralPurposeIPdu: according to the AUTOSAR standard, it must be SOMEIP_SEGMENTED_IPDU
1492        if gp_ipdu.category() != Some(GeneralPurposeIPduCategory::SomeipSegmentedIpdu) {
1493            return Err(AutosarAbstractionError::InvalidParameter(
1494                "Invalid transport PDU for the SomeIpTpConnection: it must be a segmented IPDU".to_string(),
1495            ));
1496        }
1497
1498        // get the physical channel of the transport PDU; this is currently the only link to the channel
1499        let channel = transport_pdu_triggering.physical_channel()?;
1500        // get the cluster of the physical channel and check if it matches the cluster of the SomeIpTpConfig
1501        let Some(channel_cluster) = channel
1502            .element()
1503            .named_parent()?
1504            .and_then(|p| Cluster::try_from(p).ok())
1505        else {
1506            return Err(AutosarAbstractionError::InvalidParameter(
1507                "Invalid physical channel or cluster of the transport PDU".to_string(),
1508            ));
1509        };
1510        let Some(cluster) = self.someip_tp_config()?.cluster() else {
1511            return Err(AutosarAbstractionError::InvalidParameter(
1512                "Invalid SomeIpTpConfig: missing cluster reference".to_string(),
1513            ));
1514        };
1515        if channel_cluster != cluster {
1516            return Err(AutosarAbstractionError::InvalidParameter(
1517                "The transport PDU must be in the same cluster as the SomeIpTpConfig".to_string(),
1518            ));
1519        }
1520
1521        self.element()
1522            .get_or_create_sub_element(ElementName::TransportPduRef)?
1523            .set_reference_target(transport_pdu_triggering.element())?;
1524        Ok(())
1525    }
1526
1527    /// get the `PduTriggering` for the transport PDU of this `SomeipTpConnection`
1528    #[must_use]
1529    pub fn transport_pdu_triggering(&self) -> Option<PduTriggering> {
1530        self.element()
1531            .get_sub_element(ElementName::TransportPduRef)
1532            .and_then(|ref_elem| ref_elem.get_reference_target().ok())
1533            .and_then(|target| PduTriggering::try_from(target).ok())
1534    }
1535
1536    /// set the `TpSdu` of this `SomeipTpConnection`
1537    pub fn set_tp_sdu(&self, tp_sdu: &ISignalIPdu) -> Result<(), AutosarAbstractionError> {
1538        let Some(transport_pdu_triggering) = self.transport_pdu_triggering() else {
1539            return Err(AutosarAbstractionError::InvalidParameter(
1540                "The transport PDU of the SomeipTpConnection is missing, so the TP-SDU can't be created".to_string(),
1541            ));
1542        };
1543        let channel = transport_pdu_triggering.physical_channel()?;
1544
1545        // create the PduTriggering for the TpSdu in the same cluster as the transport PDU
1546        let pt_tp_sdu = PduTriggering::new(&tp_sdu.clone().into(), &channel)?;
1547
1548        self.element()
1549            .get_or_create_sub_element(ElementName::TpSduRef)?
1550            .set_reference_target(pt_tp_sdu.element())?;
1551        Ok(())
1552    }
1553
1554    /// get the `TpSdu` of this `SomeipTpConnection`
1555    #[must_use]
1556    pub fn tp_sdu(&self) -> Option<ISignalIPdu> {
1557        let tp_sdu_triggering_elem = self
1558            .element()
1559            .get_sub_element(ElementName::TpSduRef)?
1560            .get_reference_target()
1561            .ok()?;
1562        let tp_sdu_triggering = PduTriggering::try_from(tp_sdu_triggering_elem).ok()?;
1563
1564        if let Some(Pdu::ISignalIPdu(tp_sdu)) = tp_sdu_triggering.pdu() {
1565            Some(tp_sdu)
1566        } else {
1567            None
1568        }
1569    }
1570
1571    /// set the `TpChannel` of this `SomeipTpConnection`
1572    pub fn set_tp_channel(&self, tp_channel: Option<SomeipTpChannel>) -> Result<(), AutosarAbstractionError> {
1573        if let Some(tp_channel) = tp_channel {
1574            self.element()
1575                .get_or_create_sub_element(ElementName::TpChannelRef)?
1576                .set_reference_target(tp_channel.element())?;
1577        } else {
1578            let _ = self.element().remove_sub_element_kind(ElementName::TpChannelRef);
1579        }
1580        Ok(())
1581    }
1582
1583    /// get the `TpChannel` of this `SomeipTpConnection`
1584    #[must_use]
1585    pub fn tp_channel(&self) -> Option<SomeipTpChannel> {
1586        self.element()
1587            .get_sub_element(ElementName::TpChannelRef)
1588            .and_then(|ref_elem| ref_elem.get_reference_target().ok())
1589            .and_then(|target| SomeipTpChannel::try_from(target).ok())
1590    }
1591}
1592
1593//##################################################################
1594
1595/// General settings for a `SomeIp` TP channel
1596///
1597/// version >= `AUTOSAR_00046`
1598#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1599pub struct SomeipTpChannel(Element);
1600abstraction_element!(SomeipTpChannel, SomeipTpChannel);
1601impl IdentifiableAbstractionElement for SomeipTpChannel {}
1602
1603impl SomeipTpChannel {
1604    pub(crate) fn new(name: &str, parent: &Element) -> Result<Self, AutosarAbstractionError> {
1605        let elem = parent.create_named_sub_element(ElementName::SomeipTpChannel, name)?;
1606        Ok(Self(elem))
1607    }
1608
1609    /// set the rxTimeoutTime for the `SomeIpTpChannel`
1610    pub fn set_rx_timeout_time(&self, rx_timeout_time: f64) -> Result<(), AutosarAbstractionError> {
1611        self.element()
1612            .get_or_create_sub_element(ElementName::RxTimeoutTime)?
1613            .set_character_data(rx_timeout_time)?;
1614        Ok(())
1615    }
1616
1617    /// get the rxTimeoutTime for the `SomeIpTpChannel`
1618    #[must_use]
1619    pub fn rx_timeout_time(&self) -> Option<f64> {
1620        self.element()
1621            .get_sub_element(ElementName::RxTimeoutTime)
1622            .and_then(|rtt| rtt.character_data())
1623            .and_then(|cdata| cdata.parse_float())
1624    }
1625
1626    /// set the separationTime for the `SomeIpTpChannel`
1627    pub fn set_separation_time(&self, separation_time: f64) -> Result<(), AutosarAbstractionError> {
1628        self.element()
1629            .get_or_create_sub_element(ElementName::SeparationTime)?
1630            .set_character_data(separation_time)?;
1631        Ok(())
1632    }
1633
1634    /// get the separationTime for the `SomeIpTpChannel`
1635    #[must_use]
1636    pub fn separation_time(&self) -> Option<f64> {
1637        self.element()
1638            .get_sub_element(ElementName::SeparationTime)
1639            .and_then(|st| st.character_data())
1640            .and_then(|cdata| cdata.parse_float())
1641    }
1642}
1643
1644//##################################################################
1645
1646#[cfg(test)]
1647mod test {
1648    use super::*;
1649    use crate::*;
1650    use autosar_data::AutosarVersion;
1651    use communication::{EthernetVlanInfo, NetworkEndpointAddress, PduCollectionTrigger, SocketAddressType};
1652
1653    /// helper function to create a test setup with:
1654    /// - a system
1655    /// - an ethernet cluster
1656    ///   - a physical channel
1657    ///   - a network endpoint
1658    ///   - a socket address
1659    fn helper_create_test_objects(model: &AutosarModelAbstraction) -> SocketAddress {
1660        let package = model.get_or_create_package("/ethernet").unwrap();
1661        let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1662        let cluster = system.create_ethernet_cluster("ethcluster", &package).unwrap();
1663        let channel = cluster
1664            .create_physical_channel(
1665                "channel",
1666                Some(&EthernetVlanInfo {
1667                    vlan_name: "VLAN_02".to_string(),
1668                    vlan_id: 2,
1669                }),
1670            )
1671            .unwrap();
1672        let network_endpoint_address = NetworkEndpointAddress::IPv4 {
1673            address: Some("192.168.2.222".to_string()),
1674            address_source: None,
1675            default_gateway: None,
1676            network_mask: None,
1677        };
1678        let network_endpoint = channel
1679            .create_network_endpoint("endpoint", network_endpoint_address, None)
1680            .unwrap();
1681        let tp_config = TpConfig::UdpTp {
1682            port_number: Some(1234),
1683            port_dynamically_assigned: None,
1684        };
1685        channel
1686            .create_socket_address(
1687                "socket",
1688                &network_endpoint,
1689                &tp_config,
1690                SocketAddressType::Unicast(None),
1691            )
1692            .unwrap()
1693    }
1694
1695    #[test]
1696    fn test_service_instance_collection_set() {
1697        let model = AutosarModelAbstraction::create("file", AutosarVersion::LATEST);
1698        let package = model.get_or_create_package("/package").unwrap();
1699        let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1700
1701        let si_set = system
1702            .create_service_instance_collection_set("service_instance_collection_set", &package)
1703            .unwrap();
1704        assert_eq!(si_set.name().unwrap(), "service_instance_collection_set");
1705
1706        let psi = si_set
1707            .create_provided_service_instance("ProvidedInstance", 1, 1, 1, 0)
1708            .unwrap();
1709        let csi = si_set
1710            .create_consumed_service_instance("ConsumedInstance", 1, 1, 1, "1")
1711            .unwrap();
1712
1713        assert_eq!(si_set.service_instances().count(), 2);
1714        let service_instances: Vec<ServiceInstance> = si_set.service_instances().collect();
1715        assert_eq!(service_instances[0].element(), psi.element());
1716        assert_eq!(service_instances[0], ServiceInstance::Provided(psi));
1717        assert_eq!(service_instances[1].element(), csi.element());
1718        assert_eq!(service_instances[1], ServiceInstance::Consumed(csi));
1719    }
1720
1721    #[test]
1722    fn test_provided_service_instance() {
1723        let model = AutosarModelAbstraction::create("file", AutosarVersion::LATEST);
1724        let package = model.get_or_create_package("/package").unwrap();
1725        let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1726
1727        let socket = helper_create_test_objects(&model);
1728
1729        let si_set = system
1730            .create_service_instance_collection_set("service_instance_collection_set", &package)
1731            .unwrap();
1732        let psi = si_set
1733            .create_provided_service_instance("ProvidedInstance", 1, 1, 1, 0)
1734            .unwrap();
1735
1736        psi.set_local_unicast_address(&socket).unwrap();
1737
1738        assert_eq!(psi.service_identifier().unwrap(), 1);
1739        assert_eq!(psi.instance_identifier().unwrap(), 1);
1740        assert_eq!(psi.major_version().unwrap(), 1);
1741        assert_eq!(psi.minor_version().unwrap(), 0);
1742        assert_eq!(
1743            psi.local_unicast_addresses().next(),
1744            Some(LocalUnicastAddress::Udp(socket.clone()))
1745        );
1746
1747        let eh = psi.create_event_handler("EventHandler", 1).unwrap();
1748        assert_eq!(eh.event_group_identifier().unwrap(), 1);
1749
1750        let sd_config_package = model.get_or_create_package("/SomeipSdTimingConfigs").unwrap();
1751        let server_service_instance_config =
1752            SomeipSdServerServiceInstanceConfig::new("ssssic", &sd_config_package, 10).unwrap();
1753        psi.set_sd_server_instance_config(&server_service_instance_config)
1754            .unwrap();
1755        assert_eq!(psi.sd_server_instance_config().unwrap(), server_service_instance_config);
1756    }
1757
1758    #[test]
1759    fn test_event_handler() {
1760        let model = AutosarModelAbstraction::create("file", AutosarVersion::LATEST);
1761        let package = model.get_or_create_package("/package").unwrap();
1762        let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1763
1764        let si_set = system
1765            .create_service_instance_collection_set("service_instance_collection_set", &package)
1766            .unwrap();
1767        let psi = si_set
1768            .create_provided_service_instance("ProvidedInstance", 1, 1, 1, 0)
1769            .unwrap();
1770        assert_eq!(psi.event_handlers().count(), 0);
1771        let eh = psi.create_event_handler("EventHandler", 1).unwrap();
1772        assert_eq!(psi.event_handlers().count(), 1);
1773        assert_eq!(eh.event_group_identifier().unwrap(), 1);
1774
1775        let prg = eh
1776            .create_pdu_activation_routing_group("PduActivationRoutingGroup", EventGroupControlType::ActivationUnicast)
1777            .unwrap();
1778        assert_eq!(eh.pdu_activation_routing_groups().count(), 1);
1779        assert_eq!(
1780            prg.event_group_control_type().unwrap(),
1781            EventGroupControlType::ActivationUnicast
1782        );
1783
1784        let sd_config_package = model.get_or_create_package("/SomeipSdTimingConfigs").unwrap();
1785        let rrd = RequestResponseDelay {
1786            min_value: 1.0,
1787            max_value: 2.0,
1788        };
1789        let server_event_group_timing_config =
1790            SomeipSdServerEventGroupTimingConfig::new("segtc", &sd_config_package, &rrd).unwrap();
1791        eh.set_sd_server_event_group_timing_config(&server_event_group_timing_config)
1792            .unwrap();
1793        assert_eq!(
1794            eh.sd_server_event_group_timing_config().unwrap(),
1795            server_event_group_timing_config
1796        );
1797    }
1798
1799    #[test]
1800    fn server_sd_config() {
1801        let model = AutosarModelAbstraction::create("file", AutosarVersion::LATEST);
1802        let package = model.get_or_create_package("/package").unwrap();
1803        let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1804
1805        let si_set = system
1806            .create_service_instance_collection_set("service_instance_collection_set", &package)
1807            .unwrap();
1808        let psi = si_set
1809            .create_provided_service_instance("ProvidedInstance", 1, 1, 1, 0)
1810            .unwrap();
1811        let eh = psi.create_event_handler("EventHandler", 1).unwrap();
1812
1813        let rrd = RequestResponseDelay {
1814            min_value: 1.0,
1815            max_value: 2.0,
1816        };
1817
1818        // SD server instance config for the ProvidedServiceInstance
1819        let sd_server_instance_config = SomeipSdServerServiceInstanceConfig::new("ssssic", &package, 10).unwrap();
1820        assert_eq!(sd_server_instance_config.service_offer_time_to_live().unwrap(), 10);
1821        sd_server_instance_config.set_service_offer_time_to_live(20).unwrap();
1822        assert_eq!(sd_server_instance_config.service_offer_time_to_live().unwrap(), 20);
1823        sd_server_instance_config.set_offer_cyclic_delay(1.0).unwrap();
1824        assert_eq!(sd_server_instance_config.offer_cyclic_delay().unwrap(), 1.0);
1825        // priority is only available since R21-11 (AUTOSAR_00050)! in older versions it will not be set
1826        sd_server_instance_config.set_priority(5).unwrap();
1827        assert_eq!(sd_server_instance_config.priority().unwrap(), 5);
1828
1829        let initial_offer_behavior = InitialSdDelayConfig {
1830            initial_delay_max_value: 1.0,
1831            initial_delay_min_value: 0.5,
1832            initial_repetitions_base_delay: Some(0.1),
1833            initial_repetitions_max: Some(5),
1834        };
1835        sd_server_instance_config
1836            .set_initial_offer_behavior(&initial_offer_behavior)
1837            .unwrap();
1838        assert_eq!(
1839            sd_server_instance_config.initial_offer_behavior().unwrap(),
1840            initial_offer_behavior
1841        );
1842        sd_server_instance_config.set_request_response_delay(&rrd).unwrap();
1843        assert_eq!(sd_server_instance_config.request_response_delay().unwrap(), rrd);
1844
1845        psi.set_sd_server_instance_config(&sd_server_instance_config).unwrap();
1846        assert_eq!(psi.sd_server_instance_config().unwrap(), sd_server_instance_config);
1847
1848        // SD server event group timing config for the EventHandler
1849        let sd_server_event_group_timing_config =
1850            SomeipSdServerEventGroupTimingConfig::new("segtc", &package, &rrd).unwrap();
1851        assert_eq!(
1852            sd_server_event_group_timing_config.request_response_delay().unwrap(),
1853            rrd
1854        );
1855        sd_server_event_group_timing_config
1856            .set_request_response_delay(&rrd)
1857            .unwrap();
1858        assert_eq!(
1859            sd_server_event_group_timing_config.request_response_delay().unwrap(),
1860            rrd
1861        );
1862
1863        eh.set_sd_server_event_group_timing_config(&sd_server_event_group_timing_config)
1864            .unwrap();
1865        assert_eq!(
1866            eh.sd_server_event_group_timing_config().unwrap(),
1867            sd_server_event_group_timing_config
1868        );
1869    }
1870
1871    #[test]
1872    fn test_consumed_service_instance() {
1873        let model = AutosarModelAbstraction::create("file", AutosarVersion::LATEST);
1874        let package = model.get_or_create_package("/package").unwrap();
1875        let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1876
1877        let socket = helper_create_test_objects(&model);
1878
1879        let si_set = system
1880            .create_service_instance_collection_set("service_instance_collection_set", &package)
1881            .unwrap();
1882        let csi = si_set
1883            .create_consumed_service_instance("ConsumedInstance", 1, 1, 1, "1")
1884            .unwrap();
1885
1886        csi.set_local_unicast_address(&socket).unwrap();
1887
1888        assert_eq!(csi.service_identifier().unwrap(), 1);
1889        assert_eq!(csi.instance_identifier().unwrap(), 1);
1890        assert_eq!(csi.major_version().unwrap(), 1);
1891        assert_eq!(csi.minor_version().unwrap(), "1");
1892        assert_eq!(
1893            csi.local_unicast_addresses().next(),
1894            Some(LocalUnicastAddress::Udp(socket.clone()))
1895        );
1896
1897        let ceg = csi.create_consumed_event_group("EventGroup", 1).unwrap();
1898        assert_eq!(ceg.event_group_identifier().unwrap(), 1);
1899
1900        let sd_config_package = model.get_or_create_package("/SomeipSdTimingConfigs").unwrap();
1901        let client_service_instance_config =
1902            SomeipSdClientServiceInstanceConfig::new("cscic", &sd_config_package).unwrap();
1903        csi.set_sd_client_instance_config(&client_service_instance_config)
1904            .unwrap();
1905        assert_eq!(csi.sd_client_instance_config().unwrap(), client_service_instance_config);
1906    }
1907
1908    #[test]
1909    fn test_consumed_event_group() {
1910        let model = AutosarModelAbstraction::create("file", AutosarVersion::LATEST);
1911        let package = model.get_or_create_package("/package").unwrap();
1912        let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1913
1914        let socket = helper_create_test_objects(&model);
1915
1916        let si_set = system
1917            .create_service_instance_collection_set("service_instance_collection_set", &package)
1918            .unwrap();
1919        let csi = si_set
1920            .create_consumed_service_instance("ConsumedInstance", 1, 1, 1, "1")
1921            .unwrap();
1922        assert_eq!(csi.consumed_event_groups().count(), 0);
1923        let ceg = csi.create_consumed_event_group("EventGroup", 1).unwrap();
1924        assert_eq!(csi.consumed_event_groups().count(), 1);
1925        assert_eq!(ceg.event_group_identifier().unwrap(), 1);
1926
1927        ceg.add_event_multicast_address(&socket).unwrap();
1928        assert_eq!(ceg.event_multicast_addresses().next().unwrap(), socket);
1929
1930        let prg = ceg
1931            .create_pdu_activation_routing_group(
1932                "PduActivationRoutingGroup",
1933                EventGroupControlType::ActivationMulticast,
1934            )
1935            .unwrap();
1936        assert_eq!(ceg.pdu_activation_routing_groups().count(), 1);
1937        assert_eq!(
1938            prg.event_group_control_type().unwrap(),
1939            EventGroupControlType::ActivationMulticast
1940        );
1941
1942        let sd_config_package = model.get_or_create_package("/SomeipSdTimingConfigs").unwrap();
1943        let client_event_group_timing_config =
1944            SomeipSdClientEventGroupTimingConfig::new("cegtc", &sd_config_package, 10).unwrap();
1945        ceg.set_sd_client_timer_config(&client_event_group_timing_config)
1946            .unwrap();
1947        assert_eq!(ceg.sd_client_timer_config().unwrap(), client_event_group_timing_config);
1948    }
1949
1950    #[test]
1951    fn client_sd_config() {
1952        let model = AutosarModelAbstraction::create("file", AutosarVersion::LATEST);
1953        let package = model.get_or_create_package("/package").unwrap();
1954        let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1955
1956        let si_set = system
1957            .create_service_instance_collection_set("service_instance_collection_set", &package)
1958            .unwrap();
1959        let csi = si_set
1960            .create_consumed_service_instance("ConsumedInstance", 1, 1, 1, "1")
1961            .unwrap();
1962        let ceg = csi.create_consumed_event_group("EventGroup", 1).unwrap();
1963
1964        let rrd = RequestResponseDelay {
1965            min_value: 1.0,
1966            max_value: 2.0,
1967        };
1968
1969        // SD client instance config for the ConsumedServiceInstance
1970        let sd_client_instance_config = SomeipSdClientServiceInstanceConfig::new("cscic", &package).unwrap();
1971        csi.set_sd_client_instance_config(&sd_client_instance_config).unwrap();
1972        assert_eq!(csi.sd_client_instance_config().unwrap(), sd_client_instance_config);
1973
1974        let initial_find_behavior = InitialSdDelayConfig {
1975            initial_delay_max_value: 1.0,
1976            initial_delay_min_value: 0.5,
1977            initial_repetitions_base_delay: Some(0.1),
1978            initial_repetitions_max: Some(5),
1979        };
1980        sd_client_instance_config
1981            .set_initial_find_behavior(&initial_find_behavior)
1982            .unwrap();
1983        assert_eq!(
1984            sd_client_instance_config.initial_find_behavior().unwrap(),
1985            initial_find_behavior
1986        );
1987        // priority is only available since R21-11 (AUTOSAR_00050)! in older versions it will not be set
1988        sd_client_instance_config.set_priority(5).unwrap();
1989        assert_eq!(sd_client_instance_config.priority().unwrap(), 5);
1990
1991        // SD client event group timing config for the ConsumedEventGroup
1992        let sd_client_event_group_timing_config =
1993            SomeipSdClientEventGroupTimingConfig::new("cegtc", &package, 10).unwrap();
1994        assert_eq!(sd_client_event_group_timing_config.time_to_live().unwrap(), 10);
1995        sd_client_event_group_timing_config.set_time_to_live(20).unwrap();
1996        assert_eq!(sd_client_event_group_timing_config.time_to_live().unwrap(), 20);
1997        sd_client_event_group_timing_config
1998            .set_request_response_delay(&rrd)
1999            .unwrap();
2000        assert_eq!(
2001            sd_client_event_group_timing_config.request_response_delay().unwrap(),
2002            rrd
2003        );
2004        sd_client_event_group_timing_config
2005            .set_subscribe_eventgroup_retry_delay(1.0)
2006            .unwrap();
2007        assert_eq!(
2008            sd_client_event_group_timing_config
2009                .subscribe_eventgroup_retry_delay()
2010                .unwrap(),
2011            1.0
2012        );
2013        sd_client_event_group_timing_config
2014            .set_subscribe_eventgroup_retry_max(5)
2015            .unwrap();
2016        assert_eq!(
2017            sd_client_event_group_timing_config
2018                .subscribe_eventgroup_retry_max()
2019                .unwrap(),
2020            5
2021        );
2022
2023        ceg.set_sd_client_timer_config(&sd_client_event_group_timing_config)
2024            .unwrap();
2025        assert_eq!(
2026            ceg.sd_client_timer_config().unwrap(),
2027            sd_client_event_group_timing_config
2028        );
2029    }
2030
2031    #[test]
2032    fn test_local_unicast_addresses() {
2033        let model = AutosarModelAbstraction::create("file", AutosarVersion::LATEST);
2034        let package = model.get_or_create_package("/package").unwrap();
2035        let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
2036
2037        let udp_socket = helper_create_test_objects(&model);
2038        let network_endpoint = udp_socket.network_endpoint().unwrap();
2039        let channel = udp_socket.physical_channel().unwrap();
2040        let tcp_socket = channel
2041            .create_socket_address(
2042                "tcp_socket",
2043                &network_endpoint,
2044                &TpConfig::TcpTp {
2045                    port_number: Some(1234),
2046                    port_dynamically_assigned: None,
2047                },
2048                SocketAddressType::Unicast(None),
2049            )
2050            .unwrap();
2051        let udp_socket_2 = channel
2052            .create_socket_address(
2053                "udp_socket_2",
2054                &network_endpoint,
2055                &TpConfig::UdpTp {
2056                    port_number: Some(1235),
2057                    port_dynamically_assigned: None,
2058                },
2059                SocketAddressType::Unicast(None),
2060            )
2061            .unwrap();
2062
2063        let si_set = system
2064            .create_service_instance_collection_set("service_instance_collection_set", &package)
2065            .unwrap();
2066        let psi = si_set
2067            .create_provided_service_instance("ProvidedInstance", 1, 1, 1, 0)
2068            .unwrap();
2069
2070        // there are no local unicast addresses yet
2071        assert_eq!(psi.local_unicast_addresses().count(), 0);
2072
2073        // add the UDP socket
2074        psi.set_local_unicast_address(&udp_socket).unwrap();
2075        assert_eq!(psi.local_unicast_addresses().count(), 1);
2076
2077        // add the TCP socket
2078        psi.set_local_unicast_address(&tcp_socket).unwrap();
2079        assert_eq!(psi.local_unicast_addresses().count(), 2);
2080
2081        // add the second UDP socket, replacing the first one
2082        psi.set_local_unicast_address(&udp_socket_2).unwrap();
2083        assert_eq!(psi.local_unicast_addresses().count(), 2);
2084    }
2085
2086    #[test]
2087    fn test_pdus() {
2088        let model = AutosarModelAbstraction::create("file", AutosarVersion::LATEST);
2089        let package = model.get_or_create_package("/package").unwrap();
2090        let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
2091        let cluster = system.create_ethernet_cluster("ethcluster", &package).unwrap();
2092        let channel = cluster
2093            .create_physical_channel(
2094                "channel",
2095                Some(&EthernetVlanInfo {
2096                    vlan_name: "VLAN_02".to_string(),
2097                    vlan_id: 2,
2098                }),
2099            )
2100            .unwrap();
2101        let ipdu = system.create_isignal_ipdu("pdu", &package, 222).unwrap();
2102
2103        let si_set = system
2104            .create_service_instance_collection_set("service_instance_collection_set", &package)
2105            .unwrap();
2106        let psi = si_set
2107            .create_provided_service_instance("ProvidedInstance", 1, 1, 1, 0)
2108            .unwrap();
2109        let eh = psi.create_event_handler("EventHandler", 1).unwrap();
2110        let csi = si_set
2111            .create_consumed_service_instance("ConsumedInstance", 1, 1, 1, "1")
2112            .unwrap();
2113        let ceg = csi.create_consumed_event_group("EventGroup", 1).unwrap();
2114
2115        let psi_prg = eh
2116            .create_pdu_activation_routing_group("PduActivationRoutingGroup", EventGroupControlType::ActivationUnicast)
2117            .unwrap();
2118        let _csi_pgr = ceg
2119            .create_pdu_activation_routing_group("PduActivationRoutingGroup", EventGroupControlType::ActivationUnicast)
2120            .unwrap();
2121
2122        let ipdu_identifier_set = system
2123            .create_socket_connection_ipdu_identifier_set("socon_ipdu_id", &package)
2124            .unwrap();
2125        let ipdu_identifier = ipdu_identifier_set
2126            .create_socon_ipdu_identifier(
2127                "ipdu_id",
2128                &ipdu,
2129                &channel,
2130                Some(1),
2131                None,
2132                Some(PduCollectionTrigger::Always),
2133            )
2134            .unwrap();
2135        assert_eq!(ipdu_identifier_set.socon_ipdu_identifiers().count(), 1);
2136        psi_prg.add_ipdu_identifier_udp(&ipdu_identifier).unwrap();
2137        assert_eq!(psi_prg.ipdu_identifiers_udp().count(), 1);
2138        psi_prg.add_ipdu_identifier_tcp(&ipdu_identifier).unwrap();
2139        assert_eq!(psi_prg.ipdu_identifiers_tcp().count(), 1);
2140    }
2141
2142    #[test]
2143    fn test_conversion() {
2144        let model = AutosarModelAbstraction::create("file", AutosarVersion::LATEST);
2145        let package = model.get_or_create_package("/package").unwrap();
2146        let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
2147
2148        let si_set = system
2149            .create_service_instance_collection_set("service_instance_collection_set", &package)
2150            .unwrap();
2151        let psi = si_set
2152            .create_provided_service_instance("ProvidedInstance", 1, 1, 1, 0)
2153            .unwrap();
2154        let element = psi.element().clone();
2155        let psi2 = ProvidedServiceInstance::try_from(element).unwrap();
2156        assert_eq!(psi, psi2);
2157
2158        let eh = psi.create_event_handler("EventHandler", 1).unwrap();
2159        let element = eh.element().clone();
2160        let eh2 = EventHandler::try_from(element).unwrap();
2161        assert_eq!(eh, eh2);
2162
2163        let csi = si_set
2164            .create_consumed_service_instance("ConsumedInstance", 1, 1, 1, "1")
2165            .unwrap();
2166        let element = csi.element().clone();
2167        let csi2 = ConsumedServiceInstance::try_from(element).unwrap();
2168        assert_eq!(csi, csi2);
2169
2170        let ceg = csi.create_consumed_event_group("EventGroup", 1).unwrap();
2171        let element = ceg.element().clone();
2172        let ceg2 = ConsumedEventGroup::try_from(element).unwrap();
2173        assert_eq!(ceg, ceg2);
2174
2175        // create someip configuration items using the old structure
2176        let socket = helper_create_test_objects(&model);
2177        let ae = socket
2178            .element()
2179            .get_sub_element(ElementName::ApplicationEndpoint)
2180            .unwrap();
2181
2182        // prove that the conversion of an old ProvidedServiceInstance fails
2183        let psi_old_elem = ae
2184            .create_sub_element(ElementName::ProvidedServiceInstances)
2185            .unwrap()
2186            .create_named_sub_element(ElementName::ProvidedServiceInstance, "PSI")
2187            .unwrap();
2188        let result = ProvidedServiceInstance::try_from(psi_old_elem.clone());
2189        assert!(result.is_err());
2190
2191        // prove that the conversion of an old EventHandler fails
2192        let eh_old_elem = psi_old_elem
2193            .create_sub_element(ElementName::EventHandlers)
2194            .unwrap()
2195            .create_named_sub_element(ElementName::EventHandler, "EH")
2196            .unwrap();
2197        let result = EventHandler::try_from(eh_old_elem);
2198        assert!(result.is_err());
2199
2200        // prove that the conversion of an old ConsumedServiceInstance fails
2201        let csi_old_elem = ae
2202            .create_sub_element(ElementName::ConsumedServiceInstances)
2203            .unwrap()
2204            .create_named_sub_element(ElementName::ConsumedServiceInstance, "CSI")
2205            .unwrap();
2206        let result = ConsumedServiceInstance::try_from(csi_old_elem.clone());
2207        assert!(result.is_err());
2208
2209        // prove that the conversion of an old ConsumedEventGroup fails
2210        let ceg_old_elem = csi_old_elem
2211            .create_sub_element(ElementName::ConsumedEventGroups)
2212            .unwrap()
2213            .create_named_sub_element(ElementName::ConsumedEventGroup, "CEG")
2214            .unwrap();
2215        let result = ConsumedEventGroup::try_from(ceg_old_elem);
2216        assert!(result.is_err());
2217    }
2218
2219    #[test]
2220    fn someip_tp() {
2221        let model = AutosarModelAbstraction::create("file", AutosarVersion::LATEST);
2222        let package = model.get_or_create_package("/package").unwrap();
2223
2224        let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
2225        let cluster = system.create_ethernet_cluster("ethcluster", &package).unwrap();
2226        let channel = cluster
2227            .create_physical_channel(
2228                "channel",
2229                Some(&EthernetVlanInfo {
2230                    vlan_name: "VLAN_02".to_string(),
2231                    vlan_id: 2,
2232                }),
2233            )
2234            .unwrap();
2235
2236        let gp_ipdu = system
2237            .create_general_purpose_ipdu(
2238                "gp_ipdu",
2239                &package,
2240                1400,
2241                GeneralPurposeIPduCategory::SomeipSegmentedIpdu,
2242            )
2243            .unwrap();
2244        let isignal_ipdu = system.create_isignal_ipdu("isignal_ipdu", &package, 12000).unwrap();
2245
2246        let ipdu_identifier_set = system
2247            .create_socket_connection_ipdu_identifier_set("socon_ipdu_id", &package)
2248            .unwrap();
2249        let ipdu_identifier = ipdu_identifier_set
2250            .create_socon_ipdu_identifier(
2251                "ipdu_id",
2252                &gp_ipdu,
2253                &channel,
2254                Some(1),
2255                None,
2256                Some(PduCollectionTrigger::Always),
2257            )
2258            .unwrap();
2259        let transport_pdu_triggering = ipdu_identifier.pdu_triggering().unwrap();
2260
2261        let tp_config = system
2262            .create_someip_tp_config("someip_tp_config", &package, &cluster)
2263            .unwrap();
2264
2265        let tp_channel = tp_config.create_someip_tp_channel("someip_tp_channel").unwrap();
2266        assert_eq!(tp_config.someip_tp_channels().count(), 1);
2267        tp_channel.set_rx_timeout_time(0.33).unwrap();
2268        assert_eq!(tp_channel.rx_timeout_time().unwrap(), 0.33);
2269        tp_channel.set_separation_time(0.44).unwrap();
2270        assert_eq!(tp_channel.separation_time().unwrap(), 0.44);
2271
2272        let tp_conn = tp_config
2273            .create_someip_tp_connection(&isignal_ipdu, &transport_pdu_triggering, Some(tp_channel.clone()))
2274            .unwrap();
2275        assert_eq!(tp_config.someip_tp_connections().count(), 1);
2276        assert_eq!(tp_config.someip_tp_connections().next().unwrap(), tp_conn);
2277        assert_eq!(tp_conn.tp_sdu(), Some(isignal_ipdu));
2278        assert_eq!(tp_conn.tp_channel(), Some(tp_channel));
2279        assert_eq!(tp_conn.transport_pdu_triggering(), Some(transport_pdu_triggering));
2280        assert_eq!(tp_conn.someip_tp_config().unwrap(), tp_config);
2281    }
2282}