1use crate::communication::{
2 AbstractIpdu, AbstractPdu, CommunicationDirection, DynamicPartAlternative, IPdu, ISignal, ISignalGroup,
3 MultiplexedIPdu, Pdu, PduToFrameMapping, TransferProperty,
4};
5use crate::{
6 AbstractionElement, ArPackage, AutosarAbstractionError, ByteOrder, IdentifiableAbstractionElement,
7 abstraction_element, get_reference_parents, is_used_system_element, make_unique_name,
8};
9use autosar_data::{Element, ElementName, EnumItem};
10
11pub trait SignalPdu: AbstractPdu {
15 fn mapped_signals(&self) -> impl Iterator<Item = ISignalToIPduMapping> + Send + use<Self>;
17
18 fn map_signal(
22 &self,
23 signal: &ISignal,
24 start_position: u32,
25 byte_order: ByteOrder,
26 update_bit: Option<u32>,
27 transfer_property: TransferProperty,
28 ) -> Result<ISignalToIPduMapping, AutosarAbstractionError>;
29
30 fn map_signal_group(&self, signal_group: &ISignalGroup) -> Result<ISignalToIPduMapping, AutosarAbstractionError>;
32}
33
34pub(crate) fn verify_signal_mapping(
36 pdu: &impl SignalPdu,
37 signal: &ISignal,
38 start_position: u32,
39 byte_order: ByteOrder,
40 update_bit: Option<u32>,
41 signal_name: &String,
42) -> Result<(), AutosarAbstractionError> {
43 let length = pdu.length().unwrap_or(0);
44 let mut validator = SignalMappingValidator::new(length);
45 for mapping in pdu.mapped_signals() {
46 if let (Some(m_signal), Some(m_start_pos), Some(m_byte_order)) =
47 (mapping.signal(), mapping.start_position(), mapping.byte_order())
48 {
49 let len = m_signal.length().unwrap_or(0);
50 validator.add_signal(m_start_pos, len, m_byte_order, mapping.update_bit());
51 }
52 }
53 if !validator.add_signal(start_position, signal.length().unwrap_or(0), byte_order, update_bit) {
54 return Err(AutosarAbstractionError::InvalidParameter(format!(
55 "Cannot map signal {signal_name} to an overlapping position in the pdu"
56 )));
57 }
58
59 if let Some(signal_group) = signal.signal_group()
62 && !pdu
63 .mapped_signals()
64 .filter_map(|mapping| mapping.signal_group())
65 .any(|grp| grp == signal_group)
66 {
67 return Err(AutosarAbstractionError::InvalidParameter(
68 "Cannot map signal to pdu, because it is part of an unmapped signal group.".to_string(),
69 ));
70 }
71 Ok(())
72}
73
74#[derive(Debug, Clone, PartialEq, Eq, Hash)]
78pub struct ISignalIPdu(Element);
79abstraction_element!(ISignalIPdu, ISignalIPdu);
80impl IdentifiableAbstractionElement for ISignalIPdu {}
81
82impl ISignalIPdu {
83 pub(crate) fn new(name: &str, package: &ArPackage, length: u32) -> Result<Self, AutosarAbstractionError> {
84 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
85 let elem_pdu = pkg_elements.create_named_sub_element(ElementName::ISignalIPdu, name)?;
86 elem_pdu
87 .create_sub_element(ElementName::Length)?
88 .set_character_data(length.to_string())?;
89
90 Ok(Self(elem_pdu))
91 }
92
93 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
95 for pdu_triggering in self.pdu_triggerings() {
97 let _ = pdu_triggering.element().remove_sub_element_kind(ElementName::IPduRef);
98 let _ = pdu_triggering.remove(deep);
99 }
100
101 for signal_mapping in self.mapped_signals() {
103 let _ = signal_mapping.remove(deep);
104 }
105
106 let ref_parents = get_reference_parents(self.element())?;
107
108 AbstractionElement::remove(self, deep)?;
109
110 for (named_parent, parent) in ref_parents {
111 match parent.element_name() {
112 ElementName::PduToFrameMapping => {
113 if let Ok(pdu_to_frame_mapping) = PduToFrameMapping::try_from(parent) {
114 pdu_to_frame_mapping.remove(deep)?;
115 }
116 }
117 ElementName::DynamicPartAlternative => {
119 if let Ok(dynamic_part_alternative) = DynamicPartAlternative::try_from(parent) {
120 dynamic_part_alternative.remove(deep)?;
121 }
122 }
123 ElementName::StaticPart => {
124 if let Ok(multiplexed_ipdu) = MultiplexedIPdu::try_from(named_parent) {
125 multiplexed_ipdu.remove(deep)?;
126 }
127 }
128 ElementName::ISignalIPduRefConditional => {
129 if let Ok(Some(parent_parent)) = parent.parent() {
130 parent_parent.remove_sub_element(parent)?;
131 }
132 }
133 _ => {}
134 }
135 }
136
137 Ok(())
138 }
139
140 pub fn map_signal(
144 &self,
145 signal: &ISignal,
146 start_position: u32,
147 byte_order: ByteOrder,
148 update_bit: Option<u32>,
149 transfer_property: TransferProperty,
150 ) -> Result<ISignalToIPduMapping, AutosarAbstractionError> {
151 let signal_name = signal
152 .name()
153 .ok_or(AutosarAbstractionError::InvalidParameter("invalid signal".to_string()))?;
154
155 verify_signal_mapping(self, signal, start_position, byte_order, update_bit, &signal_name)?;
156
157 for pt in self.pdu_triggerings() {
159 let st = pt.create_signal_triggering(signal)?;
160 for pdu_port in pt.pdu_ports() {
161 if let (Ok(ecu), Some(direction)) = (pdu_port.ecu(), pdu_port.communication_direction()) {
162 st.connect_to_ecu(&ecu, direction)?;
163 }
164 }
165 }
166
167 let model = self.element().model()?;
169 let base_path = self.element().path()?;
170 let name = make_unique_name(&model, &base_path, &signal_name);
171
172 let mappings = self
173 .element()
174 .get_or_create_sub_element(ElementName::ISignalToPduMappings)?;
175
176 ISignalToIPduMapping::new_with_signal(
177 &name,
178 &mappings,
179 signal,
180 start_position,
181 byte_order,
182 update_bit,
183 transfer_property,
184 )
185 }
186
187 pub fn map_signal_group(
189 &self,
190 signal_group: &ISignalGroup,
191 ) -> Result<ISignalToIPduMapping, AutosarAbstractionError> {
192 let signal_group_name = signal_group.name().ok_or(AutosarAbstractionError::InvalidParameter(
193 "invalid signal group".to_string(),
194 ))?;
195
196 for pt in self.pdu_triggerings() {
198 let st = pt.create_signal_group_triggering(signal_group)?;
199 for pdu_port in pt.pdu_ports() {
200 if let (Ok(ecu), Some(direction)) = (pdu_port.ecu(), pdu_port.communication_direction()) {
201 st.connect_to_ecu(&ecu, direction)?;
202 }
203 }
204 }
205
206 let model = self.element().model()?;
208 let base_path = self.element().path()?;
209 let name = make_unique_name(&model, &base_path, &signal_group_name);
210
211 let mappings = self
212 .element()
213 .get_or_create_sub_element(ElementName::ISignalToPduMappings)?;
214
215 ISignalToIPduMapping::new_with_group(&name, &mappings, signal_group)
216 }
217
218 pub fn set_timing(&self, timing_spec: &IpduTiming) -> Result<(), AutosarAbstractionError> {
220 let _ = self
221 .element()
222 .remove_sub_element_kind(ElementName::IPduTimingSpecifications);
223
224 let timing_elem = self
225 .element()
226 .create_sub_element(ElementName::IPduTimingSpecifications)?
227 .create_sub_element(ElementName::IPduTiming)?;
228 if let Some(min_delay) = timing_spec.minimum_delay {
229 timing_elem
230 .create_sub_element(ElementName::MinimumDelay)?
231 .set_character_data(min_delay)?;
232 }
233 if let Some(transmission_mode_true_timing) = &timing_spec.transmission_mode_true_timing {
234 let tmtt_elem = timing_elem
235 .get_or_create_sub_element(ElementName::TransmissionModeDeclaration)?
236 .create_sub_element(ElementName::TransmissionModeTrueTiming)?;
237 Self::set_transmission_mode_timinig(tmtt_elem, transmission_mode_true_timing)?;
238 }
239 if let Some(transmission_mode_false_timing) = &timing_spec.transmission_mode_false_timing {
240 let tmtf_elem = timing_elem
241 .get_or_create_sub_element(ElementName::TransmissionModeDeclaration)?
242 .create_sub_element(ElementName::TransmissionModeFalseTiming)?;
243 Self::set_transmission_mode_timinig(tmtf_elem, transmission_mode_false_timing)?;
244 }
245
246 Ok(())
247 }
248
249 fn set_transmission_mode_timinig(
251 timing_element: Element,
252 transmission_mode_timing: &TransmissionModeTiming,
253 ) -> Result<(), AutosarAbstractionError> {
254 if let Some(cyclic_timing) = &transmission_mode_timing.cyclic_timing {
255 let ct_elem = timing_element.create_sub_element(ElementName::CyclicTiming)?;
256 ct_elem
257 .create_sub_element(ElementName::TimePeriod)?
258 .create_sub_element(ElementName::Value)?
259 .set_character_data(cyclic_timing.time_period)?;
260 if let Some(time_offset) = cyclic_timing.time_offset {
261 ct_elem
262 .create_sub_element(ElementName::TimeOffset)?
263 .create_sub_element(ElementName::Value)?
264 .set_character_data(time_offset)?;
265 }
266 }
267 if let Some(event_controlled_timing) = &transmission_mode_timing.event_controlled_timing {
268 let ect_elem = timing_element.create_sub_element(ElementName::EventControlledTiming)?;
269 ect_elem
270 .create_sub_element(ElementName::NumberOfRepetitions)?
271 .set_character_data(u64::from(event_controlled_timing.number_of_repetitions))?;
272 if let Some(repetition_period) = event_controlled_timing.repetition_period {
273 ect_elem
274 .create_sub_element(ElementName::RepetitionPeriod)?
275 .create_sub_element(ElementName::Value)?
276 .set_character_data(repetition_period)?;
277 }
278 }
279
280 Ok(())
281 }
282
283 #[must_use]
285 pub fn timing(&self) -> Option<IpduTiming> {
286 let timing_elem = self
287 .element()
288 .get_sub_element(ElementName::IPduTimingSpecifications)?
289 .get_sub_element(ElementName::IPduTiming)?;
290 let minimum_delay = timing_elem
291 .get_sub_element(ElementName::MinimumDelay)
292 .and_then(|md| md.character_data())
293 .and_then(|cdata| cdata.parse_float());
294 let transmission_mode_true_timing = timing_elem
295 .get_sub_element(ElementName::TransmissionModeDeclaration)
296 .and_then(|tmd| tmd.get_sub_element(ElementName::TransmissionModeTrueTiming))
297 .and_then(|tmtt| Self::transmission_mode_timing(&tmtt));
298 let transmission_mode_false_timing = timing_elem
299 .get_sub_element(ElementName::TransmissionModeDeclaration)
300 .and_then(|tmd| tmd.get_sub_element(ElementName::TransmissionModeFalseTiming))
301 .and_then(|tmtf| Self::transmission_mode_timing(&tmtf));
302
303 Some(IpduTiming {
304 minimum_delay,
305 transmission_mode_true_timing,
306 transmission_mode_false_timing,
307 })
308 }
309
310 fn transmission_mode_timing(timing_elem: &Element) -> Option<TransmissionModeTiming> {
312 let cyclic_timing = timing_elem.get_sub_element(ElementName::CyclicTiming).and_then(|ct| {
313 let time_period = ct
314 .get_sub_element(ElementName::TimePeriod)
315 .and_then(|tp| tp.get_sub_element(ElementName::Value))
316 .and_then(|val| val.character_data())
317 .and_then(|cdata| cdata.parse_float());
318 let time_offset = ct
319 .get_sub_element(ElementName::TimeOffset)
320 .and_then(|to| to.get_sub_element(ElementName::Value))
321 .and_then(|val| val.character_data())
322 .and_then(|cdata| cdata.parse_float());
323 time_period.map(|tp| CyclicTiming {
324 time_period: tp,
325 time_offset,
326 })
327 });
328 let event_controlled_timing = timing_elem
329 .get_sub_element(ElementName::EventControlledTiming)
330 .and_then(|ect| {
331 let number_of_repetitions = ect
332 .get_sub_element(ElementName::NumberOfRepetitions)
333 .and_then(|nr| nr.character_data())
334 .and_then(|cdata| cdata.parse_integer());
335 let repetition_period = ect
336 .get_sub_element(ElementName::RepetitionPeriod)
337 .and_then(|rp| rp.get_sub_element(ElementName::Value))
338 .and_then(|val| val.character_data())
339 .and_then(|cdata| cdata.parse_float());
340 number_of_repetitions.map(|nr| EventControlledTiming {
341 number_of_repetitions: nr,
342 repetition_period,
343 })
344 });
345
346 Some(TransmissionModeTiming {
347 cyclic_timing,
348 event_controlled_timing,
349 })
350 }
351}
352
353impl SignalPdu for ISignalIPdu {
354 fn mapped_signals(&self) -> impl Iterator<Item = ISignalToIPduMapping> + Send + use<> {
356 self.element()
357 .get_sub_element(ElementName::ISignalToPduMappings)
358 .into_iter()
359 .flat_map(|mappings| mappings.sub_elements())
360 .filter_map(|elem| ISignalToIPduMapping::try_from(elem).ok())
361 }
362
363 fn map_signal(
364 &self,
365 signal: &ISignal,
366 start_position: u32,
367 byte_order: ByteOrder,
368 update_bit: Option<u32>,
369 transfer_property: TransferProperty,
370 ) -> Result<ISignalToIPduMapping, AutosarAbstractionError> {
371 ISignalIPdu::map_signal(self, signal, start_position, byte_order, update_bit, transfer_property)
372 }
373
374 fn map_signal_group(&self, signal_group: &ISignalGroup) -> Result<ISignalToIPduMapping, AutosarAbstractionError> {
375 ISignalIPdu::map_signal_group(self, signal_group)
376 }
377}
378
379impl AbstractPdu for ISignalIPdu {}
380
381impl AbstractIpdu for ISignalIPdu {}
382
383impl From<ISignalIPdu> for Pdu {
384 fn from(value: ISignalIPdu) -> Self {
385 Pdu::ISignalIPdu(value)
386 }
387}
388
389impl From<ISignalIPdu> for IPdu {
390 fn from(value: ISignalIPdu) -> Self {
391 IPdu::ISignalIPdu(value)
392 }
393}
394
395#[derive(Debug, Clone, PartialEq, Eq, Hash)]
399pub struct ISignalToIPduMapping(Element);
400abstraction_element!(ISignalToIPduMapping, ISignalToIPduMapping);
401impl IdentifiableAbstractionElement for ISignalToIPduMapping {}
402
403impl ISignalToIPduMapping {
404 pub(crate) fn new_with_signal(
405 name: &str,
406 mappings: &Element,
407 signal: &ISignal,
408 start_position: u32,
409 byte_order: ByteOrder,
410 update_bit: Option<u32>,
411 transfer_property: TransferProperty,
412 ) -> Result<Self, AutosarAbstractionError> {
413 let signal_mapping = mappings.create_named_sub_element(ElementName::ISignalToIPduMapping, name)?;
414 signal_mapping
415 .create_sub_element(ElementName::ISignalRef)?
416 .set_reference_target(signal.element())?;
417 signal_mapping
418 .create_sub_element(ElementName::PackingByteOrder)?
419 .set_character_data::<EnumItem>(byte_order.into())?;
420 signal_mapping
421 .create_sub_element(ElementName::StartPosition)?
422 .set_character_data(u64::from(start_position))?;
423 signal_mapping
424 .create_sub_element(ElementName::TransferProperty)?
425 .set_character_data::<EnumItem>(transfer_property.into())?;
426 if let Some(update_bit_pos) = update_bit {
427 signal_mapping
428 .create_sub_element(ElementName::UpdateIndicationBitPosition)?
429 .set_character_data(u64::from(update_bit_pos))?;
430 }
431
432 Ok(Self(signal_mapping))
433 }
434
435 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
437 let opt_signal = self.signal();
438 let opt_signal_group = self.signal_group();
439
440 AbstractionElement::remove(self, false)?;
441
442 if deep {
443 if let Some(signal) = opt_signal
445 && !is_used_system_element(signal.element())
446 {
447 signal.remove(true)?;
448 }
449
450 if let Some(signal_group) = opt_signal_group
452 && !is_used_system_element(signal_group.element())
453 {
454 signal_group.remove(true)?;
455 }
456 }
457
458 Ok(())
459 }
460
461 pub(crate) fn new_with_group(
462 name: &str,
463 mappings: &Element,
464 signal_group: &ISignalGroup,
465 ) -> Result<Self, AutosarAbstractionError> {
466 let signal_mapping = mappings.create_named_sub_element(ElementName::ISignalToIPduMapping, name)?;
467 signal_mapping
468 .create_sub_element(ElementName::ISignalGroupRef)?
469 .set_reference_target(signal_group.element())?;
470
471 Ok(Self(signal_mapping))
472 }
473
474 #[must_use]
477 pub fn signal(&self) -> Option<ISignal> {
478 self.element()
479 .get_sub_element(ElementName::ISignalRef)
480 .and_then(|sigref| sigref.get_reference_target().ok())
481 .and_then(|signal_elem| ISignal::try_from(signal_elem).ok())
482 }
483
484 pub fn set_byte_order(&self, byte_order: ByteOrder) -> Result<(), AutosarAbstractionError> {
486 self.element()
487 .get_or_create_sub_element(ElementName::PackingByteOrder)?
488 .set_character_data::<EnumItem>(byte_order.into())?;
489 Ok(())
490 }
491
492 #[must_use]
494 pub fn byte_order(&self) -> Option<ByteOrder> {
495 self.element()
496 .get_sub_element(ElementName::PackingByteOrder)
497 .and_then(|pbo| pbo.character_data())
498 .and_then(|cdata| cdata.enum_value())
499 .and_then(|enumval| enumval.try_into().ok())
500 }
501
502 #[must_use]
505 pub fn start_position(&self) -> Option<u32> {
506 self.element()
507 .get_sub_element(ElementName::StartPosition)
508 .and_then(|sp_elem| sp_elem.character_data())
509 .and_then(|cdata| cdata.parse_integer())
510 }
511
512 #[must_use]
515 pub fn update_bit(&self) -> Option<u32> {
516 self.element()
517 .get_sub_element(ElementName::UpdateIndicationBitPosition)
518 .and_then(|uibp| uibp.character_data())
519 .and_then(|cdata| cdata.parse_integer())
520 }
521
522 pub fn set_transfer_property(&self, transfer_property: TransferProperty) -> Result<(), AutosarAbstractionError> {
524 self.element()
525 .get_or_create_sub_element(ElementName::TransferProperty)?
526 .set_character_data::<EnumItem>(transfer_property.into())?;
527 Ok(())
528 }
529
530 #[must_use]
532 pub fn transfer_property(&self) -> Option<TransferProperty> {
533 self.element()
534 .get_sub_element(ElementName::TransferProperty)
535 .and_then(|pbo| pbo.character_data())
536 .and_then(|cdata| cdata.enum_value())
537 .and_then(|enumval| enumval.try_into().ok())
538 }
539
540 #[must_use]
543 pub fn signal_group(&self) -> Option<ISignalGroup> {
544 self.element()
545 .get_sub_element(ElementName::ISignalGroupRef)
546 .and_then(|sgref| sgref.get_reference_target().ok())
547 .and_then(|siggrp_elem| ISignalGroup::try_from(siggrp_elem).ok())
548 }
549}
550
551#[derive(Debug, Clone, PartialEq)]
555pub struct IpduTiming {
556 pub minimum_delay: Option<f64>,
558 pub transmission_mode_true_timing: Option<TransmissionModeTiming>,
560 pub transmission_mode_false_timing: Option<TransmissionModeTiming>,
562}
563
564#[derive(Debug, Clone, PartialEq)]
566pub struct TransmissionModeTiming {
567 pub cyclic_timing: Option<CyclicTiming>,
569 pub event_controlled_timing: Option<EventControlledTiming>,
571}
572
573#[derive(Debug, Clone, PartialEq)]
575pub struct CyclicTiming {
576 pub time_period: f64,
578 pub time_offset: Option<f64>,
580}
581
582#[derive(Debug, Clone, PartialEq)]
584pub struct EventControlledTiming {
585 pub number_of_repetitions: u32,
587 pub repetition_period: Option<f64>,
589}
590
591#[derive(Debug, Clone, PartialEq, Eq, Hash)]
595pub struct ISignalIPduGroup(Element);
596abstraction_element!(ISignalIPduGroup, ISignalIPduGroup);
597impl IdentifiableAbstractionElement for ISignalIPduGroup {}
598
599impl ISignalIPduGroup {
600 pub(crate) fn new(
601 name: &str,
602 package: &ArPackage,
603 communication_direction: CommunicationDirection,
604 ) -> Result<Self, AutosarAbstractionError> {
605 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
606 let elem_pdu_group = pkg_elements.create_named_sub_element(ElementName::ISignalIPduGroup, name)?;
607 let pdu_group = Self(elem_pdu_group);
608 pdu_group.set_communication_direction(communication_direction)?;
609
610 Ok(pdu_group)
611 }
612
613 pub fn set_communication_direction(
615 &self,
616 communication_direction: CommunicationDirection,
617 ) -> Result<(), AutosarAbstractionError> {
618 self.element()
619 .get_or_create_sub_element(ElementName::CommunicationDirection)
620 .and_then(|cd| cd.set_character_data::<EnumItem>(communication_direction.into()))?;
621 Ok(())
622 }
623
624 #[must_use]
626 pub fn communication_direction(&self) -> Option<CommunicationDirection> {
627 self.element()
628 .get_sub_element(ElementName::CommunicationDirection)
629 .and_then(|cd| cd.character_data())
630 .and_then(|cdata| cdata.enum_value())
631 .and_then(|enumval| enumval.try_into().ok())
632 }
633
634 pub fn add_pdu(&self, pdu: &ISignalIPdu) -> Result<(), AutosarAbstractionError> {
636 self.element()
637 .get_or_create_sub_element(ElementName::ISignalIPdus)?
638 .create_sub_element(ElementName::ISignalIPduRefConditional)?
639 .create_sub_element(ElementName::ISignalIPduRef)?
640 .set_reference_target(pdu.element())?;
641 Ok(())
642 }
643
644 pub fn pdus(&self) -> impl Iterator<Item = ISignalIPdu> + Send + use<> {
646 self.element()
647 .get_sub_element(ElementName::ISignalIPdus)
648 .into_iter()
649 .flat_map(|pdus_elem| pdus_elem.sub_elements())
650 .filter_map(|pdu_ref_cond| {
651 pdu_ref_cond
652 .get_sub_element(ElementName::ISignalIPduRef)
653 .and_then(|pdu_ref| pdu_ref.get_reference_target().ok())
654 .and_then(|pdu_elem| ISignalIPdu::try_from(pdu_elem).ok())
655 })
656 }
657}
658
659pub struct SignalMappingValidator {
663 bitmap: Vec<u8>,
664}
665
666impl SignalMappingValidator {
667 #[must_use]
669 pub fn new(length: u32) -> Self {
670 Self {
671 bitmap: vec![0; length as usize],
672 }
673 }
674
675 pub fn add_signal(
680 &mut self,
681 bit_position: u32,
682 bit_length: u64,
683 byte_order: ByteOrder,
684 update_bit: Option<u32>,
685 ) -> bool {
686 let bit_position = u64::from(bit_position);
687 let first_byte = (bit_position / 8) as usize;
688 let bit_offset = bit_position % 8; let first_byte_bits; let mut first_mask;
691
692 if byte_order == ByteOrder::MostSignificantByteFirst {
693 first_byte_bits = (bit_offset + 1).min(bit_length);
699 first_mask = ((1u16 << (bit_offset + 1)) - 1) as u8;
700 if bit_offset + 1 != first_byte_bits {
701 let pos2 = bit_offset - first_byte_bits;
702 let subtract_mask = (1u8 << pos2) - 1;
703 first_mask -= subtract_mask;
704 }
705 } else {
706 first_byte_bits = (8 - bit_offset).min(bit_length); first_mask = !((1u16 << bit_offset) - 1) as u8; if bit_offset + first_byte_bits < 8 {
714 let pos2 = bit_offset + first_byte_bits;
715 let subtract_mask = !((1u8 << pos2) - 1);
716 first_mask -= subtract_mask;
717 }
718 }
719 let full_bytes = (bit_length - first_byte_bits) as usize / 8;
720 let end_bits = (bit_length - first_byte_bits) % 8;
721
722 let mut result = self.apply_mask(first_mask, first_byte);
723 result &= self.apply_full_bytes(first_byte + 1, full_bytes);
724
725 if end_bits > 0 {
727 let end_mask = if byte_order == ByteOrder::MostSignificantByteFirst {
728 !((1u8 << end_bits) - 1)
729 } else {
730 (1u8 << end_bits) - 1
731 };
732 result &= self.apply_mask(end_mask, first_byte + full_bytes + 1);
733 }
734
735 if let Some(update_bit) = update_bit {
737 let position = (update_bit / 8) as usize;
738 let bit_pos = update_bit % 8;
739 let mask = 1 << bit_pos;
740 result &= self.apply_mask(mask, position);
741 }
742
743 result
744 }
745
746 fn apply_mask(&mut self, mask: u8, position: usize) -> bool {
747 if position < self.bitmap.len() {
748 let result = self.bitmap[position] & mask == 0;
750 self.bitmap[position] |= mask;
752 result
753 } else {
754 false
755 }
756 }
757
758 fn apply_full_bytes(&mut self, position: usize, count: usize) -> bool {
759 let mut result = true;
760 if count > 0 {
761 let limit = self.bitmap.len().min(position + count);
762 for idx in position..limit {
763 result &= self.apply_mask(0xff, idx);
764 }
765 result &= limit == position + count;
767 }
768 result
769 }
770}
771
772#[cfg(test)]
775mod test {
776 use super::*;
777 use crate::{AutosarModelAbstraction, ByteOrder, SystemCategory};
778 use autosar_data::AutosarVersion;
779
780 #[test]
781 fn isignal_ipdu() {
782 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
783 let package = model.get_or_create_package("/pkg").unwrap();
784 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
785
786 let pdu = system.create_isignal_ipdu("isignal_ipdu", &package, 8).unwrap();
787 assert_eq!(pdu.name().unwrap(), "isignal_ipdu");
788 assert_eq!(pdu.length().unwrap(), 8);
789
790 let syssignal = package.create_system_signal("syssignal").unwrap();
792 let isignal = system.create_isignal("isignal", &package, 4, &syssignal, None).unwrap();
793 let mapping = pdu
794 .map_signal(
795 &isignal,
796 0,
797 ByteOrder::MostSignificantByteFirst,
798 Some(5),
799 TransferProperty::Triggered,
800 )
801 .unwrap();
802 assert_eq!(mapping.signal().unwrap(), isignal);
803 assert_eq!(mapping.start_position().unwrap(), 0);
804 assert_eq!(mapping.update_bit(), Some(5));
805 assert_eq!(mapping.byte_order().unwrap(), ByteOrder::MostSignificantByteFirst);
806 mapping.set_byte_order(ByteOrder::MostSignificantByteLast).unwrap();
807 assert_eq!(mapping.byte_order().unwrap(), ByteOrder::MostSignificantByteLast);
808 assert_eq!(mapping.transfer_property().unwrap(), TransferProperty::Triggered);
809 mapping.set_transfer_property(TransferProperty::Pending).unwrap();
810 assert_eq!(mapping.transfer_property().unwrap(), TransferProperty::Pending);
811
812 let syssignal_group = package.create_system_signal_group("syssignal_group").unwrap();
814 let signal_group = system
815 .create_isignal_group("signal_group", &package, &syssignal_group)
816 .unwrap();
817 let grouped_syssignal = package.create_system_signal("groups_syssignal").unwrap();
818 syssignal_group.add_signal(&grouped_syssignal).unwrap();
819 let grouped_isignal = system
820 .create_isignal("grouped_isignal", &package, 4, &grouped_syssignal, None)
821 .unwrap();
822 signal_group.add_signal(&grouped_isignal).unwrap();
823 assert_eq!(grouped_isignal.signal_group().unwrap(), signal_group);
824
825 let result = pdu.map_signal(
827 &grouped_isignal,
828 9,
829 ByteOrder::MostSignificantByteFirst,
830 None,
831 TransferProperty::Triggered,
832 );
833 assert!(result.is_err());
834
835 let mapping = pdu.map_signal_group(&signal_group).unwrap();
837 assert_eq!(mapping.signal_group().unwrap(), signal_group);
838
839 let _mapping = pdu
841 .map_signal(
842 &grouped_isignal,
843 9,
844 ByteOrder::MostSignificantByteFirst,
845 None,
846 TransferProperty::Triggered,
847 )
848 .unwrap();
849 }
850
851 #[test]
852 fn validate_signal_mapping() {
853 let mut validator = SignalMappingValidator::new(4);
855 let result = validator.add_signal(0, 2, ByteOrder::MostSignificantByteLast, None);
856 assert!(result);
857 assert_eq!(validator.bitmap[0], 0x03);
858
859 let mut validator = SignalMappingValidator::new(4);
861 let result = validator.add_signal(5, 10, ByteOrder::MostSignificantByteLast, None);
862 assert!(result);
863 assert_eq!(validator.bitmap[0], 0xE0);
864 assert_eq!(validator.bitmap[1], 0x7F);
865
866 let mut validator = SignalMappingValidator::new(4);
868 let result = validator.add_signal(5, 10, ByteOrder::MostSignificantByteFirst, None);
869 assert!(result);
870 assert_eq!(validator.bitmap[0], 0x3F);
871 assert_eq!(validator.bitmap[1], 0xF0);
872
873 let result = validator.add_signal(5, 10, ByteOrder::MostSignificantByteLast, None);
875 assert!(!result);
877 assert_eq!(validator.bitmap[0], 0xFF);
878 assert_eq!(validator.bitmap[1], 0xFF);
879
880 let mut validator = SignalMappingValidator::new(4);
882 let result = validator.add_signal(0, 32, ByteOrder::MostSignificantByteLast, None);
883 assert!(result);
884 assert_eq!(validator.bitmap[0], 0xFF);
885 assert_eq!(validator.bitmap[1], 0xFF);
886 assert_eq!(validator.bitmap[2], 0xFF);
887 assert_eq!(validator.bitmap[3], 0xFF);
888
889 let mut validator = SignalMappingValidator::new(4);
891 let result = validator.add_signal(7, 32, ByteOrder::MostSignificantByteFirst, None);
892 assert!(result);
893 assert_eq!(validator.bitmap[0], 0xFF);
894 assert_eq!(validator.bitmap[1], 0xFF);
895 assert_eq!(validator.bitmap[2], 0xFF);
896 assert_eq!(validator.bitmap[3], 0xFF);
897
898 let mut validator = SignalMappingValidator::new(8);
900 let result = validator.add_signal(7, 16, ByteOrder::MostSignificantByteFirst, Some(60));
901 assert!(result);
902 let result = validator.add_signal(16, 3, ByteOrder::MostSignificantByteLast, Some(61));
903 assert!(result);
904 let result = validator.add_signal(19, 7, ByteOrder::MostSignificantByteLast, Some(62));
905 assert!(result);
906 let result = validator.add_signal(26, 30, ByteOrder::MostSignificantByteLast, Some(63));
907 assert!(result);
908 let result = validator.add_signal(59, 4, ByteOrder::MostSignificantByteFirst, None);
909 assert!(result);
910 assert_eq!(validator.bitmap, [0xFF; 8]);
911 }
912
913 #[test]
914 fn ipdu_timing() {
915 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
916 let package = model.get_or_create_package("/pkg").unwrap();
917 let pdu = ISignalIPdu::new("pdu_name", &package, 8).unwrap();
918
919 let timing_spec = IpduTiming {
920 minimum_delay: Some(0.1),
921 transmission_mode_true_timing: Some(TransmissionModeTiming {
922 cyclic_timing: Some(CyclicTiming {
923 time_period: 0.2,
924 time_offset: Some(0.3),
925 }),
926 event_controlled_timing: Some(EventControlledTiming {
927 number_of_repetitions: 4,
928 repetition_period: Some(0.5),
929 }),
930 }),
931 transmission_mode_false_timing: Some(TransmissionModeTiming {
932 cyclic_timing: Some(CyclicTiming {
933 time_period: 0.6,
934 time_offset: Some(0.7),
935 }),
936 event_controlled_timing: Some(EventControlledTiming {
937 number_of_repetitions: 8,
938 repetition_period: Some(0.9),
939 }),
940 }),
941 };
942 pdu.set_timing(&timing_spec).unwrap();
943 let timing_spec2 = pdu.timing().unwrap();
944 assert_eq!(timing_spec, timing_spec2);
945 }
946
947 #[test]
948 fn isignal_ipdu_group() {
949 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
950 let package = model.get_or_create_package("/pkg").unwrap();
951 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
952 let pdu_group = system
953 .create_isignal_ipdu_group("PduGroup", &package, CommunicationDirection::In)
954 .unwrap();
955
956 assert_eq!(system.isignal_ipdu_groups().count(), 1);
957
958 assert_eq!(pdu_group.name().unwrap(), "PduGroup");
959 assert_eq!(pdu_group.communication_direction().unwrap(), CommunicationDirection::In);
960
961 let isignal_ipdu1 = system.create_isignal_ipdu("Pdu1", &package, 8).unwrap();
962 let isignal_ipdu2 = system.create_isignal_ipdu("Pdu2", &package, 16).unwrap();
963
964 pdu_group.add_pdu(&isignal_ipdu1).unwrap();
965 pdu_group.add_pdu(&isignal_ipdu2).unwrap();
966
967 assert_eq!(pdu_group.pdus().count(), 2);
968 }
969}