1#![no_std]
78
79#[macro_use]
80extern crate alloc;
81use alloc::vec::Vec;
82use core::ops::BitXor;
83
84mod attributename;
85mod autosarversion;
86mod elementname;
87mod enumitem;
88mod regex;
89mod specification;
90
91pub use attributename::{AttributeName, ParseAttributeNameError};
92pub use autosarversion::{AutosarVersion, ParseAutosarVersionError};
93pub use elementname::{ElementName, ParseElementNameError};
94pub use enumitem::{EnumItem, ParseEnumItemError};
95use specification::{
96 ATTRIBUTES, AUTOSAR_ELEMENT, CHARACTER_DATA, DATATYPES, ELEMENTS, REF_ITEMS, REFERENCE_TYPE_IDX, SUBELEMENTS,
97 VERSION_INFO,
98};
99
100#[derive(Debug, Copy, Clone, Eq, PartialEq)]
102pub enum ElementMultiplicity {
103 ZeroOrOne,
104 One,
105 Any,
106}
107
108#[derive(Debug, Copy, Clone, Eq, PartialEq)]
110pub enum StdRestrict {
111 NotRestricted,
112 ClassicPlatform,
113 AdaptivePlatform,
114}
115
116#[derive(Debug, Copy, Clone, Eq, PartialEq)]
118pub enum ContentMode {
119 Sequence,
121 Choice,
124 Bag,
127 Characters,
129 Mixed,
131}
132
133pub enum CharacterDataSpec {
135 Enum {
137 items: &'static [(EnumItem, u32)],
138 },
139 Pattern {
141 check_fn: fn(&[u8]) -> bool,
143 regex: &'static str,
145 max_length: Option<usize>,
147 },
148 String {
150 preserve_whitespace: bool,
151 max_length: Option<usize>,
152 },
153 UnsignedInteger,
154 Float,
155}
156
157pub struct AttributeSpec {
159 pub spec: &'static CharacterDataSpec,
161 pub required: bool,
163 pub version: u32,
165}
166
167#[derive(Eq, PartialEq, Clone, Copy, Hash)]
171pub struct ElementType {
172 def: u16,
174 typ: u16,
176}
177
178#[derive(Debug, Clone, Copy)]
182pub struct GroupType(u16);
183
184#[derive(Debug)]
185enum SubElement {
186 Element(u16),
187 Group(u16),
188}
189
190struct ElementDefinition {
191 name: ElementName,
192 elemtype: u16,
193 multiplicity: ElementMultiplicity,
194 ordered: bool,
195 splittable: u32,
196 restrict_std: StdRestrict,
197 #[cfg(feature = "docstrings")]
198 docstring: Option<u16>,
199}
200
201struct ElementSpec {
202 sub_elements: (u16, u16),
203 sub_element_ver: u16,
204 attributes: (u16, u16),
205 attributes_ver: u16,
206 character_data: Option<u16>,
207 mode: ContentMode,
208 ref_info: (u16, u16),
209}
210
211impl AutosarVersion {
212 #[must_use]
213 pub fn compatible(&self, version_mask: u32) -> bool {
214 version_mask & *self as u32 != 0
215 }
216}
217
218impl ElementType {
219 #[must_use]
220 const fn new(def: u16) -> Self {
221 let typ = ELEMENTS[def as usize].elemtype;
222 Self { def, typ }
223 }
224
225 fn get_sub_elements(etype: u16) -> &'static [SubElement] {
226 let (idx_start, idx_end) = ElementType::get_sub_element_idx(etype);
227 &SUBELEMENTS[idx_start..idx_end]
228 }
229
230 const fn get_sub_element_idx(etype: u16) -> (usize, usize) {
231 let (start, end) = DATATYPES[etype as usize].sub_elements;
232 (start as usize, end as usize)
233 }
234
235 const fn get_sub_element_ver(etype: u16) -> usize {
236 DATATYPES[etype as usize].sub_element_ver as usize
237 }
238
239 const fn get_attributes_idx(etype: u16) -> (usize, usize) {
240 let (start, end) = DATATYPES[etype as usize].attributes;
241 (start as usize, end as usize)
242 }
243
244 const fn get_attributes_ver(etype: u16) -> usize {
245 DATATYPES[etype as usize].attributes_ver as usize
246 }
247
248 fn get_sub_element_spec<'a>(self, element_indices: &[usize]) -> Option<(&'a SubElement, u32)> {
250 if element_indices.is_empty() {
251 return None;
252 }
253
254 let spec = ElementType::get_sub_elements(self.typ);
255 let ver_list_start = ElementType::get_sub_element_ver(self.typ);
256 let mut current_spec = spec;
257 let mut current_ver_list_start = ver_list_start;
258 for idx in 0..(element_indices.len() - 1) {
260 match ¤t_spec[element_indices[idx]] {
261 SubElement::Element { .. } => {
262 return None;
264 }
265 SubElement::Group(groupid) => {
266 current_spec = ElementType::get_sub_elements(*groupid);
267 current_ver_list_start = ElementType::get_sub_element_ver(*groupid);
268 }
269 }
270 }
271
272 let last_idx = *element_indices.last().unwrap();
273 Some((¤t_spec[last_idx], VERSION_INFO[current_ver_list_start + last_idx]))
274 }
275
276 #[must_use]
278 pub fn get_sub_element_version_mask(&self, element_indices: &[usize]) -> Option<u32> {
279 match self.get_sub_element_spec(element_indices) {
280 Some((_, version_mask)) => Some(version_mask),
281 _ => None,
282 }
283 }
284
285 #[must_use]
289 pub fn get_sub_element_multiplicity(&self, element_indices: &[usize]) -> Option<ElementMultiplicity> {
290 match self.get_sub_element_spec(element_indices) {
291 Some((SubElement::Element(definiton_id), _)) => Some(ELEMENTS[*definiton_id as usize].multiplicity),
292 _ => None,
293 }
294 }
295
296 #[must_use]
300 pub fn get_sub_element_container_mode(&self, element_indices: &[usize]) -> ContentMode {
301 if element_indices.len() < 2 {
302 DATATYPES[self.typ as usize].mode
304 } else {
305 let len = element_indices.len() - 1;
306 if let Some((SubElement::Group(groupid), _)) = self.get_sub_element_spec(&element_indices[..len]) {
307 DATATYPES[*groupid as usize].mode
308 } else {
309 unreachable!("impossible: element container is not a group");
310 }
311 }
312 }
313
314 #[must_use]
343 pub fn find_sub_element(&self, target_name: ElementName, version: u32) -> Option<(ElementType, Vec<usize>)> {
344 ElementType::find_sub_element_internal(self.typ, target_name, version)
345 }
346
347 fn find_sub_element_internal(
348 etype: u16,
349 target_name: ElementName,
350 version: u32,
351 ) -> Option<(ElementType, Vec<usize>)> {
352 let spec = ElementType::get_sub_elements(etype);
353 for (cur_pos, sub_element) in spec.iter().enumerate() {
354 match sub_element {
355 SubElement::Element(definiton_id) => {
356 let name = ELEMENTS[*definiton_id as usize].name;
357 let ver_info_start = ElementType::get_sub_element_ver(etype);
358 let version_mask = VERSION_INFO[ver_info_start + cur_pos];
359 if (name == target_name) && (version & version_mask != 0) {
360 return Some((ElementType::new(*definiton_id), vec![cur_pos]));
361 }
362 }
363 SubElement::Group(groupid) => {
364 if let Some((elemtype, mut indices)) =
365 ElementType::find_sub_element_internal(*groupid, target_name, version)
366 {
367 indices.insert(0, cur_pos);
368 return Some((elemtype, indices));
369 }
370 }
371 }
372 }
373 None
374 }
375
376 #[must_use]
382 pub fn find_common_group(&self, element_indices: &[usize], element_indices2: &[usize]) -> GroupType {
383 let mut result = self.typ;
384 let mut prefix_len = 0;
385 while element_indices.len() > prefix_len
386 && element_indices2.len() > prefix_len
387 && element_indices[prefix_len] == element_indices2[prefix_len]
388 {
389 let sub_elem = &ElementType::get_sub_elements(result)[element_indices[prefix_len]];
390 match sub_elem {
391 SubElement::Element(_) => return GroupType(result),
392 SubElement::Group(groupid) => {
393 result = *groupid;
394 }
395 }
396 prefix_len += 1;
397 }
398
399 GroupType(result)
400 }
401
402 #[must_use]
404 pub fn is_named(&self) -> bool {
405 self.short_name_version_mask().is_some()
406 }
407
408 pub(crate) fn short_name_version_mask(self) -> Option<u32> {
409 let sub_elements = ElementType::get_sub_elements(self.typ);
410 if !sub_elements.is_empty()
411 && let SubElement::Element(idx) = sub_elements[0]
412 && ELEMENTS[idx as usize].name == ElementName::ShortName
413 {
414 let ver_idx = ElementType::get_sub_element_ver(self.typ);
415 return Some(VERSION_INFO[ver_idx]);
416 }
417 None
418 }
419
420 #[must_use]
428 pub fn is_named_in_version(&self, version: AutosarVersion) -> bool {
429 self.short_name_version_mask()
430 .is_some_and(|ver_mask| version.compatible(ver_mask))
431 }
432
433 #[must_use]
435 pub fn is_ref(&self) -> bool {
436 if let Some(idx) = DATATYPES[self.typ as usize].character_data {
437 idx == REFERENCE_TYPE_IDX
438 } else {
439 false
440 }
441 }
442
443 #[must_use]
445 pub const fn content_mode(&self) -> ContentMode {
446 DATATYPES[self.typ as usize].mode
447 }
448
449 #[must_use]
451 pub const fn chardata_spec(&self) -> Option<&'static CharacterDataSpec> {
452 if let Some(chardata_id) = DATATYPES[self.typ as usize].character_data {
453 Some(&CHARACTER_DATA[chardata_id as usize])
454 } else {
455 None
456 }
457 }
458
459 #[must_use]
461 pub fn find_attribute_spec(&self, attrname: AttributeName) -> Option<AttributeSpec> {
462 let (idx_start, idx_end) = ElementType::get_attributes_idx(self.typ);
463 let attributes = &ATTRIBUTES[idx_start..idx_end];
464 if let Some((find_pos, (_, chardata_id, required))) =
465 attributes.iter().enumerate().find(|(_, (name, ..))| *name == attrname)
466 {
467 let idx_ver_start = ElementType::get_attributes_ver(self.typ);
468 let version = VERSION_INFO[idx_ver_start + find_pos];
469 Some(AttributeSpec {
470 spec: &CHARACTER_DATA[*chardata_id as usize],
471 required: *required,
472 version,
473 })
474 } else {
475 None
476 }
477 }
478
479 #[must_use]
481 pub const fn attribute_spec_iter(&self) -> AttrDefinitionsIter {
482 AttrDefinitionsIter {
483 type_id: self.typ,
484 pos: 0,
485 }
486 }
487
488 #[must_use]
490 pub fn sub_element_spec_iter(&self) -> SubelemDefinitionsIter {
491 SubelemDefinitionsIter {
492 type_id_stack: vec![self.typ],
493 indices: vec![0],
494 }
495 }
496
497 #[must_use]
505 pub const fn is_ordered(&self) -> bool {
506 ELEMENTS[self.def as usize].ordered
507 }
508
509 #[must_use]
514 pub const fn splittable(&self) -> u32 {
515 ELEMENTS[self.def as usize].splittable
516 }
517
518 #[must_use]
522 pub const fn splittable_in(&self, version: AutosarVersion) -> bool {
523 (ELEMENTS[self.def as usize].splittable & (version as u32)) != 0
524 }
525
526 #[must_use]
530 pub const fn std_restriction(&self) -> StdRestrict {
531 ELEMENTS[self.def as usize].restrict_std
532 }
533
534 #[must_use]
543 pub fn reference_dest_value(&self, other: &ElementType) -> Option<EnumItem> {
544 if self.is_ref() && other.is_named() {
546 let dest_spec = self.find_attribute_spec(AttributeName::Dest)?.spec;
547 if let CharacterDataSpec::Enum { items } = dest_spec {
548 let (start, end) = DATATYPES[other.typ as usize].ref_info;
549 let ref_by = &REF_ITEMS[start as usize..end as usize];
550 for ref_target_value in ref_by {
551 for (enumitem, _) in *items {
552 if ref_target_value == enumitem {
553 return Some(*ref_target_value);
554 }
555 }
556 }
557 }
558 }
559 None
560 }
561
562 #[must_use]
564 pub fn verify_reference_dest(&self, dest_value: EnumItem) -> bool {
565 let (start, end) = DATATYPES[self.typ as usize].ref_info;
566 let values = &REF_ITEMS[start as usize..end as usize];
567 values.contains(&dest_value)
568 }
569
570 #[cfg(feature = "docstrings")]
571 #[must_use]
572 pub const fn docstring(&self) -> &str {
573 if let Some(docstring_id) = ELEMENTS[self.def as usize].docstring {
574 specification::ELEMENT_DOCSTRINGS[docstring_id as usize]
575 } else {
576 ""
577 }
578 }
579
580 pub const ROOT: Self = ElementType::new(AUTOSAR_ELEMENT);
582}
583
584impl core::fmt::Debug for ElementType {
586 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
587 write!(f, "ElementType({}, {})", self.def, self.typ)
588 }
589}
590
591impl GroupType {
592 #[must_use]
594 pub const fn content_mode(&self) -> ContentMode {
595 DATATYPES[self.0 as usize].mode
596 }
597}
598
599pub struct AttrDefinitionsIter {
601 type_id: u16,
602 pos: usize,
603}
604
605impl Iterator for AttrDefinitionsIter {
606 type Item = (AttributeName, &'static CharacterDataSpec, bool);
607
608 fn next(&mut self) -> Option<Self::Item> {
609 let (idx_start, idx_end) = ElementType::get_attributes_idx(self.type_id);
610 let cur_pos = self.pos;
611 self.pos += 1;
612 if idx_start + cur_pos < idx_end {
613 let (name, chardata_id, required) = ATTRIBUTES[idx_start + cur_pos];
614 Some((name, &CHARACTER_DATA[chardata_id as usize], required))
615 } else {
616 None
617 }
618 }
619}
620
621pub struct SubelemDefinitionsIter {
625 type_id_stack: Vec<u16>,
626 indices: Vec<usize>,
627}
628
629impl Iterator for SubelemDefinitionsIter {
630 type Item = (ElementName, ElementType, u32, u32);
632
633 fn next(&mut self) -> Option<Self::Item> {
634 if self.type_id_stack.is_empty() {
635 None
636 } else {
637 debug_assert_eq!(self.type_id_stack.len(), self.indices.len());
638
639 let depth = self.indices.len() - 1;
640 let current_type = self.type_id_stack[depth];
641 let cur_pos = self.indices[depth];
642 let (start_idx, end_idx) = ElementType::get_sub_element_idx(current_type);
643
644 if start_idx + cur_pos < end_idx {
645 match &SUBELEMENTS[start_idx + cur_pos] {
646 SubElement::Element(idx) => {
647 let name = ELEMENTS[*idx as usize].name;
649 self.indices[depth] += 1;
650 let ver_idx = ElementType::get_sub_element_ver(current_type);
651 let version_mask = VERSION_INFO[ver_idx + cur_pos];
652 let is_named = ElementType::new(*idx).short_name_version_mask().unwrap_or(0);
653 Some((name, ElementType::new(*idx), version_mask, is_named))
654 }
655 SubElement::Group(groupid) => {
656 self.type_id_stack.push(*groupid);
658 self.indices.push(0);
659 self.next()
660 }
661 }
662 } else {
663 self.indices.pop();
665 self.type_id_stack.pop();
666 if !self.indices.is_empty() {
667 self.indices[depth - 1] += 1;
668 }
669 self.next()
670 }
671 }
672 }
673}
674
675impl core::fmt::Debug for CharacterDataSpec {
678 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
679 match self {
680 Self::Enum { items } => f.debug_struct("Enum").field("items", items).finish(),
681 Self::Pattern { regex, max_length, .. } => f
682 .debug_struct("Pattern")
683 .field("regex", regex)
684 .field("max_length", max_length)
685 .finish(),
686 Self::String {
687 preserve_whitespace,
688 max_length,
689 } => f
690 .debug_struct("String")
691 .field("preserve_whitespace", preserve_whitespace)
692 .field("max_length", max_length)
693 .finish(),
694 Self::UnsignedInteger => write!(f, "UnsignedInteger"),
695 Self::Float => write!(f, "Double"),
696 }
697 }
698}
699
700#[must_use]
702pub fn expand_version_mask(version_mask: u32) -> Vec<AutosarVersion> {
703 let mut versions = vec![];
704 for i in 0..u32::BITS {
705 let val = 1u32 << i;
706 if version_mask & val != 0
707 && let Some(enum_value) = AutosarVersion::from_val(val)
708 {
709 versions.push(enum_value);
710 }
711 }
712
713 versions
714}
715
716pub(crate) fn hashfunc(mut data: &[u8]) -> (u32, u32, u32) {
717 const HASHCONST1: u32 = 0x541C_69B2; const HASHCONST2: u32 = 0x3B17_161B;
719
720 let mut f1 = 0x3314_3C63_u32;
721 let mut f2 = 0x88B0_B21E_u32;
722 while data.len() >= 4 {
723 let val = u32::from_ne_bytes(data[..4].try_into().unwrap());
724 f1 = f1.rotate_left(5).bitxor(val).wrapping_mul(HASHCONST1);
725 f2 = f2.rotate_left(6).bitxor(val).wrapping_mul(HASHCONST2);
726 data = &data[4..];
727 }
728 if data.len() >= 2 {
729 let val = u32::from(u16::from_ne_bytes(data[..2].try_into().unwrap()));
730 f1 = f1.rotate_left(5).bitxor(val).wrapping_mul(HASHCONST1);
731 f2 = f2.rotate_left(6).bitxor(val).wrapping_mul(HASHCONST2);
732 data = &data[2..];
733 }
734 if !data.is_empty() {
735 f1 = f1.rotate_left(5).bitxor(u32::from(data[0])).wrapping_mul(HASHCONST1);
736 f2 = f2.rotate_left(6).bitxor(u32::from(data[0])).wrapping_mul(HASHCONST2);
737 }
738 let g = f1.bitxor(f2);
739 (g, f1, f2)
740}
741
742#[cfg(test)]
743mod test {
744 extern crate std;
745 use alloc::string::ToString;
746 use core::str::FromStr;
747 use num_traits::FromPrimitive;
748 use std::collections::HashSet;
749
750 use super::*;
751
752 fn get_prm_char_element_type() -> ElementType {
753 let (ar_packages_type, _) = ElementType::ROOT
754 .find_sub_element(ElementName::ArPackages, u32::MAX)
755 .unwrap();
756 let (ar_package_type, _) = ar_packages_type
757 .find_sub_element(ElementName::ArPackage, u32::MAX)
758 .unwrap();
759 let (elements_type, _) = ar_package_type
760 .find_sub_element(ElementName::Elements, u32::MAX)
761 .unwrap();
762 let (documentation_type, _) = elements_type
763 .find_sub_element(ElementName::Documentation, u32::MAX)
764 .unwrap();
765 let (documentation_content_type, _) = documentation_type
766 .find_sub_element(ElementName::DocumentationContent, u32::MAX)
767 .unwrap();
768 let (prms_type, _) = documentation_content_type
769 .find_sub_element(ElementName::Prms, u32::MAX)
770 .unwrap();
771 let (prm_type, _) = prms_type.find_sub_element(ElementName::Prm, u32::MAX).unwrap();
772 let (prm_char_type, _) = prm_type.find_sub_element(ElementName::PrmChar, u32::MAX).unwrap();
773
774 prm_char_type
775 }
776
777 #[test]
778 fn find_sub_element() {
779 let prm_char_type = get_prm_char_element_type();
780 let (_, indices) = prm_char_type.find_sub_element(ElementName::Tol, 0xffffffff).unwrap();
781 assert_eq!(indices, vec![1, 0, 0, 0, 1]);
782 }
783
784 #[test]
785 fn find_sub_element_version_dependent() {
786 let (ar_packages_type, _) = ElementType::ROOT
787 .find_sub_element(ElementName::ArPackages, u32::MAX)
788 .unwrap();
789 let (ar_package_type, _) = ar_packages_type
790 .find_sub_element(ElementName::ArPackage, u32::MAX)
791 .unwrap();
792 let (elements_type, _) = ar_package_type
793 .find_sub_element(ElementName::Elements, u32::MAX)
794 .unwrap();
795 let (sw_base_type_type, _) = elements_type
796 .find_sub_element(ElementName::SwBaseType, u32::MAX)
797 .unwrap();
798 let (_, indices) = sw_base_type_type
799 .find_sub_element(ElementName::BaseTypeSize, AutosarVersion::Autosar_4_0_1 as u32)
800 .unwrap();
801 assert_eq!(indices, vec![11, 0]);
802
803 let (_, indices) = sw_base_type_type
804 .find_sub_element(ElementName::BaseTypeSize, AutosarVersion::Autosar_4_1_1 as u32)
805 .unwrap();
806 assert_eq!(indices, vec![13]);
807 }
808
809 #[test]
810 fn get_sub_element_spec() {
811 let prm_char_type = get_prm_char_element_type();
812 let (abs_type, indices) = prm_char_type.find_sub_element(ElementName::Abs, u32::MAX).unwrap();
813 let sub_elem_spec = prm_char_type.get_sub_element_spec(&indices);
814 let (sub_element, _) = sub_elem_spec.unwrap();
815 if let SubElement::Element(idx) = sub_element {
816 let name = ELEMENTS[*idx as usize].name;
817 assert_eq!(name, ElementName::Abs);
818 assert_eq!(ElementType::new(*idx), abs_type);
819 }
820
821 let sub_elem_spec2 = prm_char_type.get_sub_element_spec(&[]);
823 assert!(sub_elem_spec2.is_none());
824 let sub_elem_spec2 = prm_char_type.get_sub_element_spec(&[0, 0, 0, 0, 0, 0, 0, 0, 0]);
826 assert!(sub_elem_spec2.is_none());
827 }
828
829 #[test]
830 fn get_sub_element_version_mask() {
831 let prm_char_type = get_prm_char_element_type();
832 let (_, indices) = prm_char_type.find_sub_element(ElementName::Abs, u32::MAX).unwrap();
833 let sub_elem_spec = prm_char_type.get_sub_element_spec(&indices).unwrap();
834 let version_mask2 = prm_char_type.get_sub_element_version_mask(&indices).unwrap();
835 let (_, version_mask) = sub_elem_spec;
836 assert_eq!(version_mask, version_mask2);
837
838 let no_result = prm_char_type.get_sub_element_version_mask(&[]);
839 assert!(no_result.is_none());
840 }
841
842 #[test]
843 fn get_sub_element_multiplicity() {
844 let prm_char_type = get_prm_char_element_type();
845 let (_, indices) = prm_char_type.find_sub_element(ElementName::Abs, u32::MAX).unwrap();
846 let sub_elem_spec = prm_char_type.get_sub_element_spec(&indices).unwrap().0;
847 let multiplicity2 = prm_char_type.get_sub_element_multiplicity(&indices).unwrap();
848 if let SubElement::Element(idx) = sub_elem_spec {
849 let multiplicity = ELEMENTS[*idx as usize].multiplicity;
850 assert_eq!(multiplicity, multiplicity2);
851 }
852
853 let no_result = prm_char_type.get_sub_element_multiplicity(&[]);
854 assert!(no_result.is_none());
855 }
856
857 #[test]
858 fn get_sub_element_container_mode() {
859 let prm_char_type = get_prm_char_element_type();
860 let (_, indices) = prm_char_type.find_sub_element(ElementName::Abs, u32::MAX).unwrap();
861 let mode = prm_char_type.get_sub_element_container_mode(&indices);
862 assert_eq!(mode, ContentMode::Sequence);
863 }
864
865 #[test]
866 fn find_common_group() {
867 let prm_char_type = get_prm_char_element_type();
868 let (_, indices_abs) = prm_char_type.find_sub_element(ElementName::Abs, u32::MAX).unwrap();
869 let (_, indices_tol) = prm_char_type.find_sub_element(ElementName::Tol, u32::MAX).unwrap();
870 let (_, indices_min) = prm_char_type.find_sub_element(ElementName::Min, u32::MAX).unwrap();
871 let group1 = prm_char_type.find_common_group(&indices_abs, &indices_tol);
874 assert_eq!(group1.content_mode(), ContentMode::Sequence);
875 let group2 = prm_char_type.find_common_group(&indices_abs, &indices_min);
877 assert_eq!(group2.content_mode(), ContentMode::Choice);
878 }
879
880 #[test]
881 fn find_attribute_spec() {
882 let AttributeSpec {
883 spec,
884 required,
885 version,
886 } = ElementType::ROOT.find_attribute_spec(AttributeName::xmlns).unwrap();
887 let spec_dbgstr = format!("{:#?}", spec);
888 assert!(!spec_dbgstr.is_empty());
889 assert!(required);
891 assert_ne!(version & AutosarVersion::Autosar_00050 as u32, 0);
893 assert_ne!(version & AutosarVersion::Autosar_4_0_1 as u32, 0);
894 }
895
896 #[test]
897 fn subelement_definition_iterator() {
898 let (ar_packages_type, _) = ElementType::ROOT
899 .find_sub_element(ElementName::ArPackages, u32::MAX)
900 .unwrap();
901 let (ar_package_type, _) = ar_packages_type
902 .find_sub_element(ElementName::ArPackage, u32::MAX)
903 .unwrap();
904 let (elements_type, _) = ar_package_type
905 .find_sub_element(ElementName::Elements, u32::MAX)
906 .unwrap();
907
908 let se_iter = elements_type.sub_element_spec_iter();
909 assert_eq!(se_iter.count(), 692); let prm_char_type = get_prm_char_element_type();
912 let pc_iter = prm_char_type.sub_element_spec_iter();
913 let compatible_count = pc_iter
915 .filter(|(_, _, version_mask, _)| AutosarVersion::Autosar_00050.compatible(*version_mask))
916 .count();
917 assert_eq!(compatible_count, 9);
918 }
919
920 #[test]
921 fn autosar_version() {
922 assert_eq!(
924 AutosarVersion::from_str("AUTOSAR_4-0-1.xsd").unwrap(),
925 AutosarVersion::Autosar_4_0_1
926 );
927 assert_eq!(
928 AutosarVersion::from_str("AUTOSAR_4-0-2.xsd").unwrap(),
929 AutosarVersion::Autosar_4_0_2
930 );
931 assert_eq!(
932 AutosarVersion::from_str("AUTOSAR_4-0-3.xsd").unwrap(),
933 AutosarVersion::Autosar_4_0_3
934 );
935 assert_eq!(
936 AutosarVersion::from_str("AUTOSAR_4-1-1.xsd").unwrap(),
937 AutosarVersion::Autosar_4_1_1
938 );
939 assert_eq!(
940 AutosarVersion::from_str("AUTOSAR_4-1-2.xsd").unwrap(),
941 AutosarVersion::Autosar_4_1_2
942 );
943 assert_eq!(
944 AutosarVersion::from_str("AUTOSAR_4-1-3.xsd").unwrap(),
945 AutosarVersion::Autosar_4_1_3
946 );
947 assert_eq!(
948 AutosarVersion::from_str("AUTOSAR_4-2-1.xsd").unwrap(),
949 AutosarVersion::Autosar_4_2_1
950 );
951 assert_eq!(
952 AutosarVersion::from_str("AUTOSAR_4-2-2.xsd").unwrap(),
953 AutosarVersion::Autosar_4_2_2
954 );
955 assert_eq!(
956 AutosarVersion::from_str("AUTOSAR_4-3-0.xsd").unwrap(),
957 AutosarVersion::Autosar_4_3_0
958 );
959 assert_eq!(
960 AutosarVersion::from_str("AUTOSAR_00042.xsd").unwrap(),
961 AutosarVersion::Autosar_00042
962 );
963 assert_eq!(
964 AutosarVersion::from_str("AUTOSAR_00043.xsd").unwrap(),
965 AutosarVersion::Autosar_00043
966 );
967 assert_eq!(
968 AutosarVersion::from_str("AUTOSAR_00044.xsd").unwrap(),
969 AutosarVersion::Autosar_00044
970 );
971 assert_eq!(
972 AutosarVersion::from_str("AUTOSAR_00045.xsd").unwrap(),
973 AutosarVersion::Autosar_00045
974 );
975 assert_eq!(
976 AutosarVersion::from_str("AUTOSAR_00046.xsd").unwrap(),
977 AutosarVersion::Autosar_00046
978 );
979 assert_eq!(
980 AutosarVersion::from_str("AUTOSAR_00047.xsd").unwrap(),
981 AutosarVersion::Autosar_00047
982 );
983 assert_eq!(
984 AutosarVersion::from_str("AUTOSAR_00048.xsd").unwrap(),
985 AutosarVersion::Autosar_00048
986 );
987 assert_eq!(
988 AutosarVersion::from_str("AUTOSAR_00049.xsd").unwrap(),
989 AutosarVersion::Autosar_00049
990 );
991 assert_eq!(
992 AutosarVersion::from_str("AUTOSAR_00050.xsd").unwrap(),
993 AutosarVersion::Autosar_00050
994 );
995 assert_eq!(
996 AutosarVersion::from_str("AUTOSAR_00051.xsd").unwrap(),
997 AutosarVersion::Autosar_00051
998 );
999 assert_eq!(
1000 AutosarVersion::from_str("AUTOSAR_00052.xsd").unwrap(),
1001 AutosarVersion::Autosar_00052
1002 );
1003 assert_eq!(
1004 AutosarVersion::from_str("AUTOSAR_00053.xsd").unwrap(),
1005 AutosarVersion::Autosar_00053
1006 );
1007 assert_eq!(
1008 AutosarVersion::from_str("AUTOSAR_00054.xsd").unwrap(),
1009 AutosarVersion::Autosar_00054
1010 );
1011
1012 assert!(AutosarVersion::Autosar_4_0_1.describe().starts_with("AUTOSAR"));
1014 assert!(AutosarVersion::Autosar_4_0_2.describe().starts_with("AUTOSAR"));
1015 assert!(AutosarVersion::Autosar_4_0_3.describe().starts_with("AUTOSAR"));
1016 assert!(AutosarVersion::Autosar_4_1_1.describe().starts_with("AUTOSAR"));
1017 assert!(AutosarVersion::Autosar_4_1_2.describe().starts_with("AUTOSAR"));
1018 assert!(AutosarVersion::Autosar_4_1_3.describe().starts_with("AUTOSAR"));
1019 assert!(AutosarVersion::Autosar_4_2_1.describe().starts_with("AUTOSAR"));
1020 assert!(AutosarVersion::Autosar_4_2_2.describe().starts_with("AUTOSAR"));
1021 assert!(AutosarVersion::Autosar_4_3_0.describe().starts_with("AUTOSAR"));
1022 assert!(AutosarVersion::Autosar_00042.describe().starts_with("AUTOSAR"));
1023 assert!(AutosarVersion::Autosar_00043.describe().starts_with("AUTOSAR"));
1024 assert!(AutosarVersion::Autosar_00044.describe().starts_with("AUTOSAR"));
1025 assert!(AutosarVersion::Autosar_00045.describe().starts_with("AUTOSAR"));
1026 assert!(AutosarVersion::Autosar_00046.describe().starts_with("AUTOSAR"));
1027 assert!(AutosarVersion::Autosar_00047.describe().starts_with("AUTOSAR"));
1028 assert!(AutosarVersion::Autosar_00048.describe().starts_with("AUTOSAR"));
1029 assert!(AutosarVersion::Autosar_00049.describe().starts_with("AUTOSAR"));
1030 assert!(AutosarVersion::Autosar_00050.describe().starts_with("AUTOSAR"));
1031 assert!(AutosarVersion::Autosar_00051.describe().starts_with("AUTOSAR"));
1032 assert!(AutosarVersion::Autosar_00052.describe().starts_with("AUTOSAR"));
1033 assert!(AutosarVersion::Autosar_00053.describe().starts_with("AUTOSAR"));
1034 assert!(AutosarVersion::Autosar_00054.describe().starts_with("AUTOSAR"));
1035
1036 assert!(AutosarVersion::Autosar_4_0_1.filename().ends_with(".xsd"));
1038 assert!(AutosarVersion::Autosar_4_0_2.filename().ends_with(".xsd"));
1039 assert!(AutosarVersion::Autosar_4_0_3.filename().ends_with(".xsd"));
1040 assert!(AutosarVersion::Autosar_4_1_1.filename().ends_with(".xsd"));
1041 assert!(AutosarVersion::Autosar_4_1_2.filename().ends_with(".xsd"));
1042 assert!(AutosarVersion::Autosar_4_1_3.filename().ends_with(".xsd"));
1043 assert!(AutosarVersion::Autosar_4_2_1.filename().ends_with(".xsd"));
1044 assert!(AutosarVersion::Autosar_4_2_2.filename().ends_with(".xsd"));
1045 assert!(AutosarVersion::Autosar_4_3_0.filename().ends_with(".xsd"));
1046 assert!(AutosarVersion::Autosar_00042.filename().ends_with(".xsd"));
1047 assert!(AutosarVersion::Autosar_00043.filename().ends_with(".xsd"));
1048 assert!(AutosarVersion::Autosar_00044.filename().ends_with(".xsd"));
1049 assert!(AutosarVersion::Autosar_00045.filename().ends_with(".xsd"));
1050 assert!(AutosarVersion::Autosar_00046.filename().ends_with(".xsd"));
1051 assert!(AutosarVersion::Autosar_00047.filename().ends_with(".xsd"));
1052 assert!(AutosarVersion::Autosar_00048.filename().ends_with(".xsd"));
1053 assert!(AutosarVersion::Autosar_00049.filename().ends_with(".xsd"));
1054 assert!(AutosarVersion::Autosar_00050.filename().ends_with(".xsd"));
1055 assert!(AutosarVersion::Autosar_00051.filename().ends_with(".xsd"));
1056 assert!(AutosarVersion::Autosar_00052.filename().ends_with(".xsd"));
1057 assert!(AutosarVersion::Autosar_00053.filename().ends_with(".xsd"));
1058 assert!(AutosarVersion::Autosar_00054.filename().ends_with(".xsd"));
1059
1060 assert_eq!(
1062 AutosarVersion::Autosar_4_0_1.to_string(),
1063 AutosarVersion::Autosar_4_0_1.describe()
1064 );
1065
1066 let cloned = AutosarVersion::Autosar_00050;
1068 assert_eq!(cloned, AutosarVersion::Autosar_00050);
1069
1070 let error = AutosarVersion::from_str("something else");
1072 assert_eq!(format!("{:#?}", error.unwrap_err()), "ParseAutosarVersionError");
1073
1074 let mut hashset = HashSet::<AutosarVersion>::new();
1076 hashset.insert(AutosarVersion::Autosar_00050);
1077 }
1078
1079 #[test]
1080 fn attribute_name_basics() {
1081 assert_eq!(
1083 AttributeName::Uuid,
1084 AttributeName::from_str(AttributeName::Uuid.to_str()).unwrap()
1085 );
1086
1087 assert_eq!(AttributeName::Uuid.to_string(), "UUID");
1089
1090 let cloned = AttributeName::Uuid;
1092 assert_eq!(cloned, AttributeName::Uuid);
1093
1094 let error = AttributeName::from_str("unknown attribute name");
1096 assert_eq!(format!("{:#?}", error.unwrap_err()), "ParseAttributeNameError");
1097
1098 let mut hashset = HashSet::<AttributeName>::new();
1100 hashset.insert(AttributeName::Dest);
1101 }
1102
1103 #[test]
1104 fn element_name_basics() {
1105 assert_eq!(
1107 ElementName::Autosar,
1108 ElementName::from_str(ElementName::Autosar.to_str()).unwrap()
1109 );
1110
1111 assert_eq!(ElementName::Autosar.to_string(), "AUTOSAR");
1113
1114 let cloned = ElementName::Autosar;
1116 assert_eq!(cloned, ElementName::Autosar);
1117
1118 let error = ElementName::from_str("unknown element name");
1120 assert_eq!(format!("{:#?}", error.unwrap_err()), "ParseElementNameError");
1121
1122 let mut hashset = HashSet::<ElementName>::new();
1124 hashset.insert(ElementName::Autosar);
1125 }
1126
1127 #[test]
1128 fn enum_item_basics() {
1129 assert_eq!(
1131 EnumItem::Default,
1132 EnumItem::from_str(EnumItem::Default.to_str()).unwrap()
1133 );
1134
1135 assert_eq!(EnumItem::Default.to_string(), "DEFAULT");
1137
1138 let cloned = EnumItem::Abstract;
1140 assert_eq!(cloned, EnumItem::Abstract);
1141
1142 let error = EnumItem::from_str("unknown enum item");
1144 assert_eq!(format!("{:#?}", error.unwrap_err()), "ParseEnumItemError");
1145
1146 let mut hashset = HashSet::<EnumItem>::new();
1148 hashset.insert(EnumItem::Abstract);
1149 }
1150
1151 #[test]
1152 fn ordered() {
1153 let (ar_packages_type, _) = ElementType::ROOT
1154 .find_sub_element(ElementName::ArPackages, u32::MAX)
1155 .unwrap();
1156 let (ar_package_type, _) = ar_packages_type
1157 .find_sub_element(ElementName::ArPackage, u32::MAX)
1158 .unwrap();
1159 let (elements_type, _) = ar_package_type
1160 .find_sub_element(ElementName::Elements, u32::MAX)
1161 .unwrap();
1162 let (bsw_module_entry, _) = elements_type
1164 .find_sub_element(ElementName::BswModuleEntry, u32::MAX)
1165 .unwrap();
1166 let (arguments, _) = bsw_module_entry
1168 .find_sub_element(ElementName::Arguments, u32::MAX)
1169 .unwrap();
1170
1171 assert!(!bsw_module_entry.is_ordered());
1172 assert!(arguments.is_ordered());
1173 }
1174
1175 #[test]
1176 fn splittable() {
1177 let (ar_packages_type, _) = ElementType::ROOT
1178 .find_sub_element(ElementName::ArPackages, u32::MAX)
1179 .unwrap();
1180 let (ar_package_type, _) = ar_packages_type
1181 .find_sub_element(ElementName::ArPackage, u32::MAX)
1182 .unwrap();
1183 let (elements_type, _) = ar_package_type
1184 .find_sub_element(ElementName::Elements, u32::MAX)
1185 .unwrap();
1186
1187 assert!(!ar_package_type.splittable_in(AutosarVersion::Autosar_00051));
1188 assert_ne!(ar_packages_type.splittable() & AutosarVersion::Autosar_00051 as u32, 0);
1189 assert!(ar_packages_type.splittable_in(AutosarVersion::Autosar_00051));
1190 assert_ne!(elements_type.splittable() & AutosarVersion::Autosar_00051 as u32, 0);
1191 }
1192
1193 #[test]
1194 fn std_restriction() {
1195 let (ar_packages_type, _) = ElementType::ROOT
1196 .find_sub_element(ElementName::ArPackages, u32::MAX)
1197 .unwrap();
1198 let (ar_package_type, _) = ar_packages_type
1199 .find_sub_element(ElementName::ArPackage, u32::MAX)
1200 .unwrap();
1201 let (elements_type, _) = ar_package_type
1202 .find_sub_element(ElementName::Elements, u32::MAX)
1203 .unwrap();
1204 let (machine_type, _) = elements_type.find_sub_element(ElementName::Machine, u32::MAX).unwrap();
1205 let (defapp_timeout_type, _) = machine_type
1206 .find_sub_element(ElementName::DefaultApplicationTimeout, u32::MAX)
1207 .unwrap();
1208
1209 assert_eq!(ar_package_type.std_restriction(), StdRestrict::NotRestricted);
1210 assert_eq!(defapp_timeout_type.std_restriction(), StdRestrict::AdaptivePlatform);
1211 }
1212
1213 #[test]
1214 fn reference_dest() {
1215 let (ar_packages_type, _) = ElementType::ROOT
1216 .find_sub_element(ElementName::ArPackages, u32::MAX)
1217 .unwrap();
1218 let (ar_package_type, _) = ar_packages_type
1219 .find_sub_element(ElementName::ArPackage, u32::MAX)
1220 .unwrap();
1221 let (elements_type, _) = ar_package_type
1222 .find_sub_element(ElementName::Elements, u32::MAX)
1223 .unwrap();
1224 let (can_tp_config_type, _) = elements_type
1225 .find_sub_element(ElementName::CanTpConfig, u32::MAX)
1226 .unwrap();
1227 let (tp_connections_type, _) = can_tp_config_type
1228 .find_sub_element(ElementName::TpConnections, u32::MAX)
1229 .unwrap();
1230 let (can_tp_connection_type, _) = tp_connections_type
1231 .find_sub_element(ElementName::CanTpConnection, u32::MAX)
1232 .unwrap();
1233 let (ident_type, _) = can_tp_connection_type
1234 .find_sub_element(ElementName::Ident, u32::MAX)
1235 .unwrap();
1236
1237 let (diagnostic_connection_type, _) = elements_type
1238 .find_sub_element(ElementName::DiagnosticConnection, u32::MAX)
1239 .unwrap();
1240 let (physical_request_ref_type, _) = diagnostic_connection_type
1241 .find_sub_element(ElementName::PhysicalRequestRef, u32::MAX)
1242 .unwrap();
1243
1244 let ref_value = physical_request_ref_type.reference_dest_value(&ident_type).unwrap();
1245 assert_eq!(ref_value, EnumItem::TpConnectionIdent);
1246 assert!(ident_type.verify_reference_dest(ref_value));
1247 let invalid_ref = physical_request_ref_type.reference_dest_value(&tp_connections_type);
1248 assert!(invalid_ref.is_none());
1249 }
1250
1251 #[test]
1252 fn traits() {
1253 let mult = ElementMultiplicity::Any;
1257 let m2 = mult; assert_eq!(format!("{:#?}", mult), format!("{:#?}", m2));
1259
1260 let cm = ContentMode::Sequence;
1262 let cm2 = cm; assert_eq!(format!("{:#?}", cm), format!("{:#?}", cm2));
1264
1265 let et = ElementType::ROOT;
1267 let et2 = et; assert_eq!(format!("{:#?}", et), format!("{:#?}", et2));
1269 let mut hashset = HashSet::<ElementType>::new();
1270 hashset.insert(et);
1271 let inserted = hashset.insert(et2);
1272 assert!(!inserted);
1273
1274 let ver = AutosarVersion::LATEST;
1276 let ver2 = ver; assert_eq!(format!("{ver:#?}"), format!("{ver2:#?}"));
1278 let mut hashset = HashSet::<AutosarVersion>::new();
1279 hashset.insert(ver);
1280 let inserted = hashset.insert(ver2);
1281 assert!(!inserted);
1282
1283 let en = ElementName::Autosar;
1285 let en2 = en; assert_eq!(format!("{en:#?}"), format!("{en2:#?}"));
1287 let mut hashset = HashSet::<ElementName>::new();
1288 hashset.insert(en);
1289 let inserted = hashset.insert(en2);
1290 assert!(!inserted);
1291
1292 let cdata_spec = CharacterDataSpec::String {
1294 preserve_whitespace: true,
1295 max_length: None,
1296 };
1297 let txt = format!("{cdata_spec:#?}");
1298 assert!(txt.starts_with("String"));
1299 let cdata_spec = CharacterDataSpec::Pattern {
1300 check_fn: crate::regex::validate_regex_1,
1301 regex: r"0x[0-9a-z]*",
1302 max_length: None,
1303 };
1304 let txt = format!("{cdata_spec:#?}");
1305 assert!(txt.starts_with("Pattern"));
1306 let cdata_spec = CharacterDataSpec::Enum {
1307 items: &[(EnumItem::Custom, 0x7e000)],
1308 };
1309 let txt = format!("{cdata_spec:#?}");
1310 assert!(txt.starts_with("Enum"));
1311 let cdata_spec = CharacterDataSpec::Float;
1312 let txt = format!("{cdata_spec:#?}");
1313 assert!(txt.starts_with("Double"));
1314 let cdata_spec = CharacterDataSpec::UnsignedInteger;
1315 let txt = format!("{cdata_spec:#?}");
1316 assert!(txt.starts_with("UnsignedInteger"));
1317 }
1318
1319 #[test]
1320 fn test_expand_version_mask() {
1321 let (ar_packages_type, _) = ElementType::ROOT
1322 .find_sub_element(ElementName::ArPackages, u32::MAX)
1323 .unwrap();
1324 let (ar_package_type, _) = ar_packages_type
1325 .find_sub_element(ElementName::ArPackage, u32::MAX)
1326 .unwrap();
1327 let (elements_type, _) = ar_package_type
1328 .find_sub_element(ElementName::Elements, u32::MAX)
1329 .unwrap();
1330 let (_, element_indices) = elements_type
1331 .find_sub_element(ElementName::AdaptiveApplicationSwComponentType, u32::MAX)
1332 .unwrap();
1333 let version_mask = elements_type.get_sub_element_version_mask(&element_indices).unwrap();
1334
1335 assert_eq!(
1336 &[
1337 AutosarVersion::Autosar_00042,
1338 AutosarVersion::Autosar_00043,
1339 AutosarVersion::Autosar_00044,
1340 AutosarVersion::Autosar_00045,
1341 AutosarVersion::Autosar_00046,
1342 AutosarVersion::Autosar_00047,
1343 AutosarVersion::Autosar_00048,
1344 AutosarVersion::Autosar_00049,
1345 AutosarVersion::Autosar_00050,
1346 AutosarVersion::Autosar_00051,
1347 AutosarVersion::Autosar_00052,
1348 AutosarVersion::Autosar_00053,
1349 AutosarVersion::Autosar_00054,
1350 ],
1351 &*expand_version_mask(version_mask)
1352 );
1353 }
1354
1355 #[test]
1356 fn test_version_masks() {
1357 assert_eq!(AutosarVersion::from_u64(0x1), Some(AutosarVersion::Autosar_4_0_1));
1358 assert_eq!(AutosarVersion::from_u64(0x2), Some(AutosarVersion::Autosar_4_0_2));
1359 assert_eq!(AutosarVersion::from_u64(0x4), Some(AutosarVersion::Autosar_4_0_3));
1360 assert_eq!(AutosarVersion::from_u64(0x8), Some(AutosarVersion::Autosar_4_1_1));
1361 assert_eq!(AutosarVersion::from_u64(0x10), Some(AutosarVersion::Autosar_4_1_2));
1362 assert_eq!(AutosarVersion::from_u64(0x20), Some(AutosarVersion::Autosar_4_1_3));
1363 assert_eq!(AutosarVersion::from_u64(0x40), Some(AutosarVersion::Autosar_4_2_1));
1364 assert_eq!(AutosarVersion::from_u64(0x80), Some(AutosarVersion::Autosar_4_2_2));
1365 assert_eq!(AutosarVersion::from_u64(0x100), Some(AutosarVersion::Autosar_4_3_0));
1366 assert_eq!(AutosarVersion::from_u64(0x200), Some(AutosarVersion::Autosar_00042));
1367 assert_eq!(AutosarVersion::from_u64(0x400), Some(AutosarVersion::Autosar_00043));
1368 assert_eq!(AutosarVersion::from_u64(0x800), Some(AutosarVersion::Autosar_00044));
1369 assert_eq!(AutosarVersion::from_u64(0x1000), Some(AutosarVersion::Autosar_00045));
1370 assert_eq!(AutosarVersion::from_u64(0x2000), Some(AutosarVersion::Autosar_00046));
1371 assert_eq!(AutosarVersion::from_u64(0x4000), Some(AutosarVersion::Autosar_00047));
1372 assert_eq!(AutosarVersion::from_u64(0x8000), Some(AutosarVersion::Autosar_00048));
1373 assert_eq!(AutosarVersion::from_u64(0x10000), Some(AutosarVersion::Autosar_00049));
1374 assert_eq!(AutosarVersion::from_u64(0x20000), Some(AutosarVersion::Autosar_00050));
1375 assert_eq!(AutosarVersion::from_u64(0x40000), Some(AutosarVersion::Autosar_00051));
1376 assert_eq!(AutosarVersion::from_u64(0x80000), Some(AutosarVersion::Autosar_00052));
1377 assert_eq!(AutosarVersion::from_u64(0x100000), Some(AutosarVersion::Autosar_00053));
1378 assert_eq!(AutosarVersion::from_u64(0x200000), Some(AutosarVersion::Autosar_00054));
1379 assert_eq!(AutosarVersion::from_u64(0xF), None);
1381
1382 assert_eq!(AutosarVersion::from_i64(0x1), Some(AutosarVersion::Autosar_4_0_1));
1384 assert_eq!(AutosarVersion::from_i64(-1), None);
1385 }
1386
1387 #[cfg(feature = "docstrings")]
1388 #[test]
1389 fn test_docstring() {
1390 let (ar_packages_type, _) = ElementType::ROOT
1391 .find_sub_element(ElementName::ArPackages, u32::MAX)
1392 .unwrap();
1393 let docstring = ar_packages_type.docstring();
1394 assert_eq!(docstring, "This is the top level package in an AUTOSAR model.");
1395 }
1396}