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