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 if let SubElement::Element(idx) = sub_elements[0] {
412 if ELEMENTS[idx as usize].name == ElementName::ShortName {
413 let ver_idx = ElementType::get_sub_element_ver(self.typ);
414 return Some(VERSION_INFO[ver_idx]);
415 }
416 }
417 }
418 None
419 }
420
421 #[must_use]
429 pub fn is_named_in_version(&self, version: AutosarVersion) -> bool {
430 self.short_name_version_mask()
431 .is_some_and(|ver_mask| version.compatible(ver_mask))
432 }
433
434 #[must_use]
436 pub fn is_ref(&self) -> bool {
437 if let Some(idx) = DATATYPES[self.typ as usize].character_data {
438 idx == REFERENCE_TYPE_IDX
439 } else {
440 false
441 }
442 }
443
444 #[must_use]
446 pub const fn content_mode(&self) -> ContentMode {
447 DATATYPES[self.typ as usize].mode
448 }
449
450 #[must_use]
452 pub const fn chardata_spec(&self) -> Option<&'static CharacterDataSpec> {
453 if let Some(chardata_id) = DATATYPES[self.typ as usize].character_data {
454 Some(&CHARACTER_DATA[chardata_id as usize])
455 } else {
456 None
457 }
458 }
459
460 #[must_use]
462 pub fn find_attribute_spec(&self, attrname: AttributeName) -> Option<AttributeSpec> {
463 let (idx_start, idx_end) = ElementType::get_attributes_idx(self.typ);
464 let attributes = &ATTRIBUTES[idx_start..idx_end];
465 if let Some((find_pos, (_, chardata_id, required))) =
466 attributes.iter().enumerate().find(|(_, (name, ..))| *name == attrname)
467 {
468 let idx_ver_start = ElementType::get_attributes_ver(self.typ);
469 let version = VERSION_INFO[idx_ver_start + find_pos];
470 Some(AttributeSpec {
471 spec: &CHARACTER_DATA[*chardata_id as usize],
472 required: *required,
473 version,
474 })
475 } else {
476 None
477 }
478 }
479
480 #[must_use]
482 pub const fn attribute_spec_iter(&self) -> AttrDefinitionsIter {
483 AttrDefinitionsIter {
484 type_id: self.typ,
485 pos: 0,
486 }
487 }
488
489 #[must_use]
491 pub fn sub_element_spec_iter(&self) -> SubelemDefinitionsIter {
492 SubelemDefinitionsIter {
493 type_id_stack: vec![self.typ],
494 indices: vec![0],
495 }
496 }
497
498 #[must_use]
506 pub const fn is_ordered(&self) -> bool {
507 ELEMENTS[self.def as usize].ordered
508 }
509
510 #[must_use]
515 pub const fn splittable(&self) -> u32 {
516 ELEMENTS[self.def as usize].splittable
517 }
518
519 #[must_use]
523 pub const fn splittable_in(&self, version: AutosarVersion) -> bool {
524 (ELEMENTS[self.def as usize].splittable & (version as u32)) != 0
525 }
526
527 #[must_use]
531 pub const fn std_restriction(&self) -> StdRestrict {
532 ELEMENTS[self.def as usize].restrict_std
533 }
534
535 #[must_use]
544 pub fn reference_dest_value(&self, other: &ElementType) -> Option<EnumItem> {
545 if self.is_ref() && other.is_named() {
547 let dest_spec = self.find_attribute_spec(AttributeName::Dest)?.spec;
548 if let CharacterDataSpec::Enum { items } = dest_spec {
549 let (start, end) = DATATYPES[other.typ as usize].ref_info;
550 let ref_by = &REF_ITEMS[start as usize..end as usize];
551 for ref_target_value in ref_by {
552 for (enumitem, _) in *items {
553 if ref_target_value == enumitem {
554 return Some(*ref_target_value);
555 }
556 }
557 }
558 }
559 }
560 None
561 }
562
563 #[must_use]
565 pub fn verify_reference_dest(&self, dest_value: EnumItem) -> bool {
566 let (start, end) = DATATYPES[self.typ as usize].ref_info;
567 let values = &REF_ITEMS[start as usize..end as usize];
568 values.contains(&dest_value)
569 }
570
571 #[cfg(feature = "docstrings")]
572 #[must_use]
573 pub const fn docstring(&self) -> &str {
574 if let Some(docstring_id) = ELEMENTS[self.def as usize].docstring {
575 specification::ELEMENT_DOCSTRINGS[docstring_id as usize]
576 } else {
577 ""
578 }
579 }
580
581 pub const ROOT: Self = ElementType::new(AUTOSAR_ELEMENT);
583}
584
585impl core::fmt::Debug for ElementType {
587 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
588 write!(f, "ElementType({}, {})", self.def, self.typ)
589 }
590}
591
592impl GroupType {
593 #[must_use]
595 pub const fn content_mode(&self) -> ContentMode {
596 DATATYPES[self.0 as usize].mode
597 }
598}
599
600pub struct AttrDefinitionsIter {
602 type_id: u16,
603 pos: usize,
604}
605
606impl Iterator for AttrDefinitionsIter {
607 type Item = (AttributeName, &'static CharacterDataSpec, bool);
608
609 fn next(&mut self) -> Option<Self::Item> {
610 let (idx_start, idx_end) = ElementType::get_attributes_idx(self.type_id);
611 let cur_pos = self.pos;
612 self.pos += 1;
613 if idx_start + cur_pos < idx_end {
614 let (name, chardata_id, required) = ATTRIBUTES[idx_start + cur_pos];
615 Some((name, &CHARACTER_DATA[chardata_id as usize], required))
616 } else {
617 None
618 }
619 }
620}
621
622pub struct SubelemDefinitionsIter {
626 type_id_stack: Vec<u16>,
627 indices: Vec<usize>,
628}
629
630impl Iterator for SubelemDefinitionsIter {
631 type Item = (ElementName, ElementType, u32, u32);
633
634 fn next(&mut self) -> Option<Self::Item> {
635 if self.type_id_stack.is_empty() {
636 None
637 } else {
638 debug_assert_eq!(self.type_id_stack.len(), self.indices.len());
639
640 let depth = self.indices.len() - 1;
641 let current_type = self.type_id_stack[depth];
642 let cur_pos = self.indices[depth];
643 let (start_idx, end_idx) = ElementType::get_sub_element_idx(current_type);
644
645 if start_idx + cur_pos < end_idx {
646 match &SUBELEMENTS[start_idx + cur_pos] {
647 SubElement::Element(idx) => {
648 let name = ELEMENTS[*idx as usize].name;
650 self.indices[depth] += 1;
651 let ver_idx = ElementType::get_sub_element_ver(current_type);
652 let version_mask = VERSION_INFO[ver_idx + cur_pos];
653 let is_named = ElementType::new(*idx).short_name_version_mask().unwrap_or(0);
654 Some((name, ElementType::new(*idx), version_mask, is_named))
655 }
656 SubElement::Group(groupid) => {
657 self.type_id_stack.push(*groupid);
659 self.indices.push(0);
660 self.next()
661 }
662 }
663 } else {
664 self.indices.pop();
666 self.type_id_stack.pop();
667 if !self.indices.is_empty() {
668 self.indices[depth - 1] += 1;
669 }
670 self.next()
671 }
672 }
673 }
674}
675
676impl core::fmt::Debug for CharacterDataSpec {
679 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
680 match self {
681 Self::Enum { items } => f.debug_struct("Enum").field("items", items).finish(),
682 Self::Pattern { regex, max_length, .. } => f
683 .debug_struct("Pattern")
684 .field("regex", regex)
685 .field("max_length", max_length)
686 .finish(),
687 Self::String {
688 preserve_whitespace,
689 max_length,
690 } => f
691 .debug_struct("String")
692 .field("preserve_whitespace", preserve_whitespace)
693 .field("max_length", max_length)
694 .finish(),
695 Self::UnsignedInteger => write!(f, "UnsignedInteger"),
696 Self::Float => write!(f, "Double"),
697 }
698 }
699}
700
701#[must_use]
703pub fn expand_version_mask(version_mask: u32) -> Vec<AutosarVersion> {
704 let mut versions = vec![];
705 for i in 0..u32::BITS {
706 let val = 1u32 << i;
707 if version_mask & val != 0 {
708 if let Some(enum_value) = AutosarVersion::from_val(val) {
709 versions.push(enum_value);
710 }
711 }
712 }
713
714 versions
715}
716
717pub(crate) fn hashfunc(mut data: &[u8]) -> (u32, u32, u32) {
718 const HASHCONST1: u32 = 0x541C_69B2; const HASHCONST2: u32 = 0x3B17_161B;
720
721 let mut f1 = 0x3314_3C63_u32;
722 let mut f2 = 0x88B0_B21E_u32;
723 while data.len() >= 4 {
724 let val = u32::from_ne_bytes(data[..4].try_into().unwrap());
725 f1 = f1.rotate_left(5).bitxor(val).wrapping_mul(HASHCONST1);
726 f2 = f2.rotate_left(6).bitxor(val).wrapping_mul(HASHCONST2);
727 data = &data[4..];
728 }
729 if data.len() >= 2 {
730 let val = u32::from(u16::from_ne_bytes(data[..2].try_into().unwrap()));
731 f1 = f1.rotate_left(5).bitxor(val).wrapping_mul(HASHCONST1);
732 f2 = f2.rotate_left(6).bitxor(val).wrapping_mul(HASHCONST2);
733 data = &data[2..];
734 }
735 if !data.is_empty() {
736 f1 = f1.rotate_left(5).bitxor(u32::from(data[0])).wrapping_mul(HASHCONST1);
737 f2 = f2.rotate_left(6).bitxor(u32::from(data[0])).wrapping_mul(HASHCONST2);
738 }
739 let g = f1.bitxor(f2);
740 (g, f1, f2)
741}
742
743#[cfg(test)]
744mod test {
745 extern crate std;
746 use alloc::string::ToString;
747 use core::str::FromStr;
748 use num_traits::FromPrimitive;
749 use std::collections::HashSet;
750
751 use super::*;
752
753 fn get_prm_char_element_type() -> ElementType {
754 let (ar_packages_type, _) = ElementType::ROOT
755 .find_sub_element(ElementName::ArPackages, u32::MAX)
756 .unwrap();
757 let (ar_package_type, _) = ar_packages_type
758 .find_sub_element(ElementName::ArPackage, u32::MAX)
759 .unwrap();
760 let (elements_type, _) = ar_package_type
761 .find_sub_element(ElementName::Elements, u32::MAX)
762 .unwrap();
763 let (documentation_type, _) = elements_type
764 .find_sub_element(ElementName::Documentation, u32::MAX)
765 .unwrap();
766 let (documentation_content_type, _) = documentation_type
767 .find_sub_element(ElementName::DocumentationContent, u32::MAX)
768 .unwrap();
769 let (prms_type, _) = documentation_content_type
770 .find_sub_element(ElementName::Prms, u32::MAX)
771 .unwrap();
772 let (prm_type, _) = prms_type.find_sub_element(ElementName::Prm, u32::MAX).unwrap();
773 let (prm_char_type, _) = prm_type.find_sub_element(ElementName::PrmChar, u32::MAX).unwrap();
774
775 prm_char_type
776 }
777
778 #[test]
779 fn find_sub_element() {
780 let prm_char_type = get_prm_char_element_type();
781 let (_, indices) = prm_char_type.find_sub_element(ElementName::Tol, 0xffffffff).unwrap();
782 assert_eq!(indices, vec![1, 0, 0, 0, 1]);
783 }
784
785 #[test]
786 fn find_sub_element_version_dependent() {
787 let (ar_packages_type, _) = ElementType::ROOT
788 .find_sub_element(ElementName::ArPackages, u32::MAX)
789 .unwrap();
790 let (ar_package_type, _) = ar_packages_type
791 .find_sub_element(ElementName::ArPackage, u32::MAX)
792 .unwrap();
793 let (elements_type, _) = ar_package_type
794 .find_sub_element(ElementName::Elements, u32::MAX)
795 .unwrap();
796 let (sw_base_type_type, _) = elements_type
797 .find_sub_element(ElementName::SwBaseType, u32::MAX)
798 .unwrap();
799 let (_, indices) = sw_base_type_type
800 .find_sub_element(ElementName::BaseTypeSize, AutosarVersion::Autosar_4_0_1 as u32)
801 .unwrap();
802 assert_eq!(indices, vec![11, 0]);
803
804 let (_, indices) = sw_base_type_type
805 .find_sub_element(ElementName::BaseTypeSize, AutosarVersion::Autosar_4_1_1 as u32)
806 .unwrap();
807 assert_eq!(indices, vec![13]);
808 }
809
810 #[test]
811 fn get_sub_element_spec() {
812 let prm_char_type = get_prm_char_element_type();
813 let (abs_type, indices) = prm_char_type.find_sub_element(ElementName::Abs, u32::MAX).unwrap();
814 let sub_elem_spec = prm_char_type.get_sub_element_spec(&indices);
815 let (sub_element, _) = sub_elem_spec.unwrap();
816 if let SubElement::Element(idx) = sub_element {
817 let name = ELEMENTS[*idx as usize].name;
818 assert_eq!(name, ElementName::Abs);
819 assert_eq!(ElementType::new(*idx), abs_type);
820 }
821
822 let sub_elem_spec2 = prm_char_type.get_sub_element_spec(&[]);
824 assert!(sub_elem_spec2.is_none());
825 let sub_elem_spec2 = prm_char_type.get_sub_element_spec(&[0, 0, 0, 0, 0, 0, 0, 0, 0]);
827 assert!(sub_elem_spec2.is_none());
828 }
829
830 #[test]
831 fn get_sub_element_version_mask() {
832 let prm_char_type = get_prm_char_element_type();
833 let (_, indices) = prm_char_type.find_sub_element(ElementName::Abs, u32::MAX).unwrap();
834 let sub_elem_spec = prm_char_type.get_sub_element_spec(&indices).unwrap();
835 let version_mask2 = prm_char_type.get_sub_element_version_mask(&indices).unwrap();
836 let (_, version_mask) = sub_elem_spec;
837 assert_eq!(version_mask, version_mask2);
838
839 let no_result = prm_char_type.get_sub_element_version_mask(&[]);
840 assert!(no_result.is_none());
841 }
842
843 #[test]
844 fn get_sub_element_multiplicity() {
845 let prm_char_type = get_prm_char_element_type();
846 let (_, indices) = prm_char_type.find_sub_element(ElementName::Abs, u32::MAX).unwrap();
847 let sub_elem_spec = prm_char_type.get_sub_element_spec(&indices).unwrap().0;
848 let multiplicity2 = prm_char_type.get_sub_element_multiplicity(&indices).unwrap();
849 if let SubElement::Element(idx) = sub_elem_spec {
850 let multiplicity = ELEMENTS[*idx as usize].multiplicity;
851 assert_eq!(multiplicity, multiplicity2);
852 }
853
854 let no_result = prm_char_type.get_sub_element_multiplicity(&[]);
855 assert!(no_result.is_none());
856 }
857
858 #[test]
859 fn get_sub_element_container_mode() {
860 let prm_char_type = get_prm_char_element_type();
861 let (_, indices) = prm_char_type.find_sub_element(ElementName::Abs, u32::MAX).unwrap();
862 let mode = prm_char_type.get_sub_element_container_mode(&indices);
863 assert_eq!(mode, ContentMode::Sequence);
864 }
865
866 #[test]
867 fn find_common_group() {
868 let prm_char_type = get_prm_char_element_type();
869 let (_, indices_abs) = prm_char_type.find_sub_element(ElementName::Abs, u32::MAX).unwrap();
870 let (_, indices_tol) = prm_char_type.find_sub_element(ElementName::Tol, u32::MAX).unwrap();
871 let (_, indices_min) = prm_char_type.find_sub_element(ElementName::Min, u32::MAX).unwrap();
872 let group1 = prm_char_type.find_common_group(&indices_abs, &indices_tol);
875 assert_eq!(group1.content_mode(), ContentMode::Sequence);
876 let group2 = prm_char_type.find_common_group(&indices_abs, &indices_min);
878 assert_eq!(group2.content_mode(), ContentMode::Choice);
879 }
880
881 #[test]
882 fn find_attribute_spec() {
883 let AttributeSpec {
884 spec,
885 required,
886 version,
887 } = ElementType::ROOT.find_attribute_spec(AttributeName::xmlns).unwrap();
888 let spec_dbgstr = format!("{:#?}", spec);
889 assert!(!spec_dbgstr.is_empty());
890 assert!(required);
892 assert_ne!(version & AutosarVersion::Autosar_00050 as u32, 0);
894 assert_ne!(version & AutosarVersion::Autosar_4_0_1 as u32, 0);
895 }
896
897 #[test]
898 fn subelement_definition_iterator() {
899 let (ar_packages_type, _) = ElementType::ROOT
900 .find_sub_element(ElementName::ArPackages, u32::MAX)
901 .unwrap();
902 let (ar_package_type, _) = ar_packages_type
903 .find_sub_element(ElementName::ArPackage, u32::MAX)
904 .unwrap();
905 let (elements_type, _) = ar_package_type
906 .find_sub_element(ElementName::Elements, u32::MAX)
907 .unwrap();
908
909 let se_iter = elements_type.sub_element_spec_iter();
910 assert_eq!(se_iter.count(), 664); let prm_char_type = get_prm_char_element_type();
913 let pc_iter = prm_char_type.sub_element_spec_iter();
914 let compatible_count = pc_iter
916 .filter(|(_, _, version_mask, _)| AutosarVersion::Autosar_00050.compatible(*version_mask))
917 .count();
918 assert_eq!(compatible_count, 9);
919 }
920
921 #[test]
922 fn autosar_version() {
923 assert_eq!(
925 AutosarVersion::from_str("AUTOSAR_4-0-1.xsd").unwrap(),
926 AutosarVersion::Autosar_4_0_1
927 );
928 assert_eq!(
929 AutosarVersion::from_str("AUTOSAR_4-0-2.xsd").unwrap(),
930 AutosarVersion::Autosar_4_0_2
931 );
932 assert_eq!(
933 AutosarVersion::from_str("AUTOSAR_4-0-3.xsd").unwrap(),
934 AutosarVersion::Autosar_4_0_3
935 );
936 assert_eq!(
937 AutosarVersion::from_str("AUTOSAR_4-1-1.xsd").unwrap(),
938 AutosarVersion::Autosar_4_1_1
939 );
940 assert_eq!(
941 AutosarVersion::from_str("AUTOSAR_4-1-2.xsd").unwrap(),
942 AutosarVersion::Autosar_4_1_2
943 );
944 assert_eq!(
945 AutosarVersion::from_str("AUTOSAR_4-1-3.xsd").unwrap(),
946 AutosarVersion::Autosar_4_1_3
947 );
948 assert_eq!(
949 AutosarVersion::from_str("AUTOSAR_4-2-1.xsd").unwrap(),
950 AutosarVersion::Autosar_4_2_1
951 );
952 assert_eq!(
953 AutosarVersion::from_str("AUTOSAR_4-2-2.xsd").unwrap(),
954 AutosarVersion::Autosar_4_2_2
955 );
956 assert_eq!(
957 AutosarVersion::from_str("AUTOSAR_4-3-0.xsd").unwrap(),
958 AutosarVersion::Autosar_4_3_0
959 );
960 assert_eq!(
961 AutosarVersion::from_str("AUTOSAR_00042.xsd").unwrap(),
962 AutosarVersion::Autosar_00042
963 );
964 assert_eq!(
965 AutosarVersion::from_str("AUTOSAR_00043.xsd").unwrap(),
966 AutosarVersion::Autosar_00043
967 );
968 assert_eq!(
969 AutosarVersion::from_str("AUTOSAR_00044.xsd").unwrap(),
970 AutosarVersion::Autosar_00044
971 );
972 assert_eq!(
973 AutosarVersion::from_str("AUTOSAR_00045.xsd").unwrap(),
974 AutosarVersion::Autosar_00045
975 );
976 assert_eq!(
977 AutosarVersion::from_str("AUTOSAR_00046.xsd").unwrap(),
978 AutosarVersion::Autosar_00046
979 );
980 assert_eq!(
981 AutosarVersion::from_str("AUTOSAR_00047.xsd").unwrap(),
982 AutosarVersion::Autosar_00047
983 );
984 assert_eq!(
985 AutosarVersion::from_str("AUTOSAR_00048.xsd").unwrap(),
986 AutosarVersion::Autosar_00048
987 );
988 assert_eq!(
989 AutosarVersion::from_str("AUTOSAR_00049.xsd").unwrap(),
990 AutosarVersion::Autosar_00049
991 );
992 assert_eq!(
993 AutosarVersion::from_str("AUTOSAR_00050.xsd").unwrap(),
994 AutosarVersion::Autosar_00050
995 );
996 assert_eq!(
997 AutosarVersion::from_str("AUTOSAR_00051.xsd").unwrap(),
998 AutosarVersion::Autosar_00051
999 );
1000 assert_eq!(
1001 AutosarVersion::from_str("AUTOSAR_00052.xsd").unwrap(),
1002 AutosarVersion::Autosar_00052
1003 );
1004 assert_eq!(
1005 AutosarVersion::from_str("AUTOSAR_00053.xsd").unwrap(),
1006 AutosarVersion::Autosar_00053
1007 );
1008
1009 assert!(AutosarVersion::Autosar_4_0_1.describe().starts_with("AUTOSAR"));
1011 assert!(AutosarVersion::Autosar_4_0_2.describe().starts_with("AUTOSAR"));
1012 assert!(AutosarVersion::Autosar_4_0_3.describe().starts_with("AUTOSAR"));
1013 assert!(AutosarVersion::Autosar_4_1_1.describe().starts_with("AUTOSAR"));
1014 assert!(AutosarVersion::Autosar_4_1_2.describe().starts_with("AUTOSAR"));
1015 assert!(AutosarVersion::Autosar_4_1_3.describe().starts_with("AUTOSAR"));
1016 assert!(AutosarVersion::Autosar_4_2_1.describe().starts_with("AUTOSAR"));
1017 assert!(AutosarVersion::Autosar_4_2_2.describe().starts_with("AUTOSAR"));
1018 assert!(AutosarVersion::Autosar_4_3_0.describe().starts_with("AUTOSAR"));
1019 assert!(AutosarVersion::Autosar_00042.describe().starts_with("AUTOSAR"));
1020 assert!(AutosarVersion::Autosar_00043.describe().starts_with("AUTOSAR"));
1021 assert!(AutosarVersion::Autosar_00044.describe().starts_with("AUTOSAR"));
1022 assert!(AutosarVersion::Autosar_00045.describe().starts_with("AUTOSAR"));
1023 assert!(AutosarVersion::Autosar_00046.describe().starts_with("AUTOSAR"));
1024 assert!(AutosarVersion::Autosar_00047.describe().starts_with("AUTOSAR"));
1025 assert!(AutosarVersion::Autosar_00048.describe().starts_with("AUTOSAR"));
1026 assert!(AutosarVersion::Autosar_00049.describe().starts_with("AUTOSAR"));
1027 assert!(AutosarVersion::Autosar_00050.describe().starts_with("AUTOSAR"));
1028 assert!(AutosarVersion::Autosar_00051.describe().starts_with("AUTOSAR"));
1029 assert!(AutosarVersion::Autosar_00052.describe().starts_with("AUTOSAR"));
1030 assert!(AutosarVersion::Autosar_00053.describe().starts_with("AUTOSAR"));
1031
1032 assert!(AutosarVersion::Autosar_4_0_1.filename().ends_with(".xsd"));
1034 assert!(AutosarVersion::Autosar_4_0_2.filename().ends_with(".xsd"));
1035 assert!(AutosarVersion::Autosar_4_0_3.filename().ends_with(".xsd"));
1036 assert!(AutosarVersion::Autosar_4_1_1.filename().ends_with(".xsd"));
1037 assert!(AutosarVersion::Autosar_4_1_2.filename().ends_with(".xsd"));
1038 assert!(AutosarVersion::Autosar_4_1_3.filename().ends_with(".xsd"));
1039 assert!(AutosarVersion::Autosar_4_2_1.filename().ends_with(".xsd"));
1040 assert!(AutosarVersion::Autosar_4_2_2.filename().ends_with(".xsd"));
1041 assert!(AutosarVersion::Autosar_4_3_0.filename().ends_with(".xsd"));
1042 assert!(AutosarVersion::Autosar_00042.filename().ends_with(".xsd"));
1043 assert!(AutosarVersion::Autosar_00043.filename().ends_with(".xsd"));
1044 assert!(AutosarVersion::Autosar_00044.filename().ends_with(".xsd"));
1045 assert!(AutosarVersion::Autosar_00045.filename().ends_with(".xsd"));
1046 assert!(AutosarVersion::Autosar_00046.filename().ends_with(".xsd"));
1047 assert!(AutosarVersion::Autosar_00047.filename().ends_with(".xsd"));
1048 assert!(AutosarVersion::Autosar_00048.filename().ends_with(".xsd"));
1049 assert!(AutosarVersion::Autosar_00049.filename().ends_with(".xsd"));
1050 assert!(AutosarVersion::Autosar_00050.filename().ends_with(".xsd"));
1051 assert!(AutosarVersion::Autosar_00051.filename().ends_with(".xsd"));
1052 assert!(AutosarVersion::Autosar_00052.filename().ends_with(".xsd"));
1053 assert!(AutosarVersion::Autosar_00053.filename().ends_with(".xsd"));
1054
1055 assert_eq!(
1057 AutosarVersion::Autosar_4_0_1.to_string(),
1058 AutosarVersion::Autosar_4_0_1.describe()
1059 );
1060
1061 let cloned = AutosarVersion::Autosar_00050;
1063 assert_eq!(cloned, AutosarVersion::Autosar_00050);
1064
1065 let error = AutosarVersion::from_str("something else");
1067 assert_eq!(format!("{:#?}", error.unwrap_err()), "ParseAutosarVersionError");
1068
1069 let mut hashset = HashSet::<AutosarVersion>::new();
1071 hashset.insert(AutosarVersion::Autosar_00050);
1072 }
1073
1074 #[test]
1075 fn attribute_name_basics() {
1076 assert_eq!(
1078 AttributeName::Uuid,
1079 AttributeName::from_str(AttributeName::Uuid.to_str()).unwrap()
1080 );
1081
1082 assert_eq!(AttributeName::Uuid.to_string(), "UUID");
1084
1085 let cloned = AttributeName::Uuid;
1087 assert_eq!(cloned, AttributeName::Uuid);
1088
1089 let error = AttributeName::from_str("unknown attribute name");
1091 assert_eq!(format!("{:#?}", error.unwrap_err()), "ParseAttributeNameError");
1092
1093 let mut hashset = HashSet::<AttributeName>::new();
1095 hashset.insert(AttributeName::Dest);
1096 }
1097
1098 #[test]
1099 fn element_name_basics() {
1100 assert_eq!(
1102 ElementName::Autosar,
1103 ElementName::from_str(ElementName::Autosar.to_str()).unwrap()
1104 );
1105
1106 assert_eq!(ElementName::Autosar.to_string(), "AUTOSAR");
1108
1109 let cloned = ElementName::Autosar;
1111 assert_eq!(cloned, ElementName::Autosar);
1112
1113 let error = ElementName::from_str("unknown element name");
1115 assert_eq!(format!("{:#?}", error.unwrap_err()), "ParseElementNameError");
1116
1117 let mut hashset = HashSet::<ElementName>::new();
1119 hashset.insert(ElementName::Autosar);
1120 }
1121
1122 #[test]
1123 fn enum_item_basics() {
1124 assert_eq!(
1126 EnumItem::Default,
1127 EnumItem::from_str(EnumItem::Default.to_str()).unwrap()
1128 );
1129
1130 assert_eq!(EnumItem::Default.to_string(), "DEFAULT");
1132
1133 let cloned = EnumItem::Abstract;
1135 assert_eq!(cloned, EnumItem::Abstract);
1136
1137 let error = EnumItem::from_str("unknown enum item");
1139 assert_eq!(format!("{:#?}", error.unwrap_err()), "ParseEnumItemError");
1140
1141 let mut hashset = HashSet::<EnumItem>::new();
1143 hashset.insert(EnumItem::Abstract);
1144 }
1145
1146 #[test]
1147 fn ordered() {
1148 let (ar_packages_type, _) = ElementType::ROOT
1149 .find_sub_element(ElementName::ArPackages, u32::MAX)
1150 .unwrap();
1151 let (ar_package_type, _) = ar_packages_type
1152 .find_sub_element(ElementName::ArPackage, u32::MAX)
1153 .unwrap();
1154 let (elements_type, _) = ar_package_type
1155 .find_sub_element(ElementName::Elements, u32::MAX)
1156 .unwrap();
1157 let (bsw_module_entry, _) = elements_type
1159 .find_sub_element(ElementName::BswModuleEntry, u32::MAX)
1160 .unwrap();
1161 let (arguments, _) = bsw_module_entry
1163 .find_sub_element(ElementName::Arguments, u32::MAX)
1164 .unwrap();
1165
1166 assert!(!bsw_module_entry.is_ordered());
1167 assert!(arguments.is_ordered());
1168 }
1169
1170 #[test]
1171 fn splittable() {
1172 let (ar_packages_type, _) = ElementType::ROOT
1173 .find_sub_element(ElementName::ArPackages, u32::MAX)
1174 .unwrap();
1175 let (ar_package_type, _) = ar_packages_type
1176 .find_sub_element(ElementName::ArPackage, u32::MAX)
1177 .unwrap();
1178 let (elements_type, _) = ar_package_type
1179 .find_sub_element(ElementName::Elements, u32::MAX)
1180 .unwrap();
1181
1182 assert!(!ar_package_type.splittable_in(AutosarVersion::Autosar_00051));
1183 assert_ne!(ar_packages_type.splittable() & AutosarVersion::Autosar_00051 as u32, 0);
1184 assert!(ar_packages_type.splittable_in(AutosarVersion::Autosar_00051));
1185 assert_ne!(elements_type.splittable() & AutosarVersion::Autosar_00051 as u32, 0);
1186 }
1187
1188 #[test]
1189 fn std_restriction() {
1190 let (ar_packages_type, _) = ElementType::ROOT
1191 .find_sub_element(ElementName::ArPackages, u32::MAX)
1192 .unwrap();
1193 let (ar_package_type, _) = ar_packages_type
1194 .find_sub_element(ElementName::ArPackage, u32::MAX)
1195 .unwrap();
1196 let (elements_type, _) = ar_package_type
1197 .find_sub_element(ElementName::Elements, u32::MAX)
1198 .unwrap();
1199 let (machine_type, _) = elements_type.find_sub_element(ElementName::Machine, u32::MAX).unwrap();
1200 let (defapp_timeout_type, _) = machine_type
1201 .find_sub_element(ElementName::DefaultApplicationTimeout, u32::MAX)
1202 .unwrap();
1203
1204 assert_eq!(ar_package_type.std_restriction(), StdRestrict::NotRestricted);
1205 assert_eq!(defapp_timeout_type.std_restriction(), StdRestrict::AdaptivePlatform);
1206 }
1207
1208 #[test]
1209 fn reference_dest() {
1210 let (ar_packages_type, _) = ElementType::ROOT
1211 .find_sub_element(ElementName::ArPackages, u32::MAX)
1212 .unwrap();
1213 let (ar_package_type, _) = ar_packages_type
1214 .find_sub_element(ElementName::ArPackage, u32::MAX)
1215 .unwrap();
1216 let (elements_type, _) = ar_package_type
1217 .find_sub_element(ElementName::Elements, u32::MAX)
1218 .unwrap();
1219 let (can_tp_config_type, _) = elements_type
1220 .find_sub_element(ElementName::CanTpConfig, u32::MAX)
1221 .unwrap();
1222 let (tp_connections_type, _) = can_tp_config_type
1223 .find_sub_element(ElementName::TpConnections, u32::MAX)
1224 .unwrap();
1225 let (can_tp_connection_type, _) = tp_connections_type
1226 .find_sub_element(ElementName::CanTpConnection, u32::MAX)
1227 .unwrap();
1228 let (ident_type, _) = can_tp_connection_type
1229 .find_sub_element(ElementName::Ident, u32::MAX)
1230 .unwrap();
1231
1232 let (diagnostic_connection_type, _) = elements_type
1233 .find_sub_element(ElementName::DiagnosticConnection, u32::MAX)
1234 .unwrap();
1235 let (physical_request_ref_type, _) = diagnostic_connection_type
1236 .find_sub_element(ElementName::PhysicalRequestRef, u32::MAX)
1237 .unwrap();
1238
1239 let ref_value = physical_request_ref_type.reference_dest_value(&ident_type).unwrap();
1240 assert_eq!(ref_value, EnumItem::TpConnectionIdent);
1241 assert!(ident_type.verify_reference_dest(ref_value));
1242 let invalid_ref = physical_request_ref_type.reference_dest_value(&tp_connections_type);
1243 assert!(invalid_ref.is_none());
1244 }
1245
1246 #[test]
1247 fn traits() {
1248 let mult = ElementMultiplicity::Any;
1252 let m2 = mult; assert_eq!(format!("{:#?}", mult), format!("{:#?}", m2));
1254
1255 let cm = ContentMode::Sequence;
1257 let cm2 = cm; assert_eq!(format!("{:#?}", cm), format!("{:#?}", cm2));
1259
1260 let et = ElementType::ROOT;
1262 let et2 = et; assert_eq!(format!("{:#?}", et), format!("{:#?}", et2));
1264 let mut hashset = HashSet::<ElementType>::new();
1265 hashset.insert(et);
1266 let inserted = hashset.insert(et2);
1267 assert!(!inserted);
1268
1269 let ver = AutosarVersion::LATEST;
1271 let ver2 = ver; assert_eq!(format!("{ver:#?}"), format!("{ver2:#?}"));
1273 let mut hashset = HashSet::<AutosarVersion>::new();
1274 hashset.insert(ver);
1275 let inserted = hashset.insert(ver2);
1276 assert!(!inserted);
1277
1278 let en = ElementName::Autosar;
1280 let en2 = en; assert_eq!(format!("{en:#?}"), format!("{en2:#?}"));
1282 let mut hashset = HashSet::<ElementName>::new();
1283 hashset.insert(en);
1284 let inserted = hashset.insert(en2);
1285 assert!(!inserted);
1286
1287 let cdata_spec = CharacterDataSpec::String {
1289 preserve_whitespace: true,
1290 max_length: None,
1291 };
1292 let txt = format!("{cdata_spec:#?}");
1293 assert!(txt.starts_with("String"));
1294 let cdata_spec = CharacterDataSpec::Pattern {
1295 check_fn: crate::regex::validate_regex_1,
1296 regex: r"0x[0-9a-z]*",
1297 max_length: None,
1298 };
1299 let txt = format!("{cdata_spec:#?}");
1300 assert!(txt.starts_with("Pattern"));
1301 let cdata_spec = CharacterDataSpec::Enum {
1302 items: &[(EnumItem::Custom, 0x7e000)],
1303 };
1304 let txt = format!("{cdata_spec:#?}");
1305 assert!(txt.starts_with("Enum"));
1306 let cdata_spec = CharacterDataSpec::Float;
1307 let txt = format!("{cdata_spec:#?}");
1308 assert!(txt.starts_with("Double"));
1309 let cdata_spec = CharacterDataSpec::UnsignedInteger;
1310 let txt = format!("{cdata_spec:#?}");
1311 assert!(txt.starts_with("UnsignedInteger"));
1312 }
1313
1314 #[test]
1315 fn test_expand_version_mask() {
1316 let (ar_packages_type, _) = ElementType::ROOT
1317 .find_sub_element(ElementName::ArPackages, u32::MAX)
1318 .unwrap();
1319 let (ar_package_type, _) = ar_packages_type
1320 .find_sub_element(ElementName::ArPackage, u32::MAX)
1321 .unwrap();
1322 let (elements_type, _) = ar_package_type
1323 .find_sub_element(ElementName::Elements, u32::MAX)
1324 .unwrap();
1325 let (_, element_indices) = elements_type
1326 .find_sub_element(ElementName::AdaptiveApplicationSwComponentType, u32::MAX)
1327 .unwrap();
1328 let version_mask = elements_type.get_sub_element_version_mask(&element_indices).unwrap();
1329
1330 assert_eq!(
1331 &[
1332 AutosarVersion::Autosar_00042,
1333 AutosarVersion::Autosar_00043,
1334 AutosarVersion::Autosar_00044,
1335 AutosarVersion::Autosar_00045,
1336 AutosarVersion::Autosar_00046,
1337 AutosarVersion::Autosar_00047,
1338 AutosarVersion::Autosar_00048,
1339 AutosarVersion::Autosar_00049,
1340 AutosarVersion::Autosar_00050,
1341 AutosarVersion::Autosar_00051,
1342 AutosarVersion::Autosar_00052,
1343 AutosarVersion::Autosar_00053,
1344 ],
1345 &*expand_version_mask(version_mask)
1346 );
1347 }
1348
1349 #[test]
1350 fn test_version_masks() {
1351 assert_eq!(AutosarVersion::from_u64(0x1), Some(AutosarVersion::Autosar_4_0_1));
1352 assert_eq!(AutosarVersion::from_u64(0x2), Some(AutosarVersion::Autosar_4_0_2));
1353 assert_eq!(AutosarVersion::from_u64(0x4), Some(AutosarVersion::Autosar_4_0_3));
1354 assert_eq!(AutosarVersion::from_u64(0x8), Some(AutosarVersion::Autosar_4_1_1));
1355 assert_eq!(AutosarVersion::from_u64(0x10), Some(AutosarVersion::Autosar_4_1_2));
1356 assert_eq!(AutosarVersion::from_u64(0x20), Some(AutosarVersion::Autosar_4_1_3));
1357 assert_eq!(AutosarVersion::from_u64(0x40), Some(AutosarVersion::Autosar_4_2_1));
1358 assert_eq!(AutosarVersion::from_u64(0x80), Some(AutosarVersion::Autosar_4_2_2));
1359 assert_eq!(AutosarVersion::from_u64(0x100), Some(AutosarVersion::Autosar_4_3_0));
1360 assert_eq!(AutosarVersion::from_u64(0x200), Some(AutosarVersion::Autosar_00042));
1361 assert_eq!(AutosarVersion::from_u64(0x400), Some(AutosarVersion::Autosar_00043));
1362 assert_eq!(AutosarVersion::from_u64(0x800), Some(AutosarVersion::Autosar_00044));
1363 assert_eq!(AutosarVersion::from_u64(0x1000), Some(AutosarVersion::Autosar_00045));
1364 assert_eq!(AutosarVersion::from_u64(0x2000), Some(AutosarVersion::Autosar_00046));
1365 assert_eq!(AutosarVersion::from_u64(0x4000), Some(AutosarVersion::Autosar_00047));
1366 assert_eq!(AutosarVersion::from_u64(0x8000), Some(AutosarVersion::Autosar_00048));
1367 assert_eq!(AutosarVersion::from_u64(0x10000), Some(AutosarVersion::Autosar_00049));
1368 assert_eq!(AutosarVersion::from_u64(0x20000), Some(AutosarVersion::Autosar_00050));
1369 assert_eq!(AutosarVersion::from_u64(0x40000), Some(AutosarVersion::Autosar_00051));
1370 assert_eq!(AutosarVersion::from_u64(0x80000), Some(AutosarVersion::Autosar_00052));
1371 assert_eq!(AutosarVersion::from_u64(0x100000), Some(AutosarVersion::Autosar_00053));
1372 assert_eq!(AutosarVersion::from_u64(0xF), None);
1374
1375 assert_eq!(AutosarVersion::from_i64(0x1), Some(AutosarVersion::Autosar_4_0_1));
1377 assert_eq!(AutosarVersion::from_i64(-1), None);
1378 }
1379
1380 #[cfg(feature = "docstrings")]
1381 #[test]
1382 fn test_docstring() {
1383 let (ar_packages_type, _) = ElementType::ROOT
1384 .find_sub_element(ElementName::ArPackages, u32::MAX)
1385 .unwrap();
1386 let docstring = ar_packages_type.docstring();
1387 assert_eq!(docstring, "This is the top level package in an AUTOSAR model.");
1388 }
1389}