autosar_data_abstraction/datatype/
basetype.rs

1use crate::{
2    AbstractionElement, ArPackage, AutosarAbstractionError, ByteOrder, Element, EnumItem,
3    IdentifiableAbstractionElement, abstraction_element,
4};
5use autosar_data::ElementName;
6use std::fmt::Display;
7
8//#########################################################
9
10/// `SwBaseType` is a basic data type.
11///
12/// It is used to define the data types of signals and variables.
13///
14/// Use [`ArPackage::create_sw_base_type`] to create a new `SwBaseType`.
15///
16/// # Example
17///
18/// ```
19/// # use autosar_data::*;
20/// # use autosar_data_abstraction::{*, datatype::*};
21/// # fn main() -> Result<(), AutosarAbstractionError> {
22/// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
23/// let package = model.get_or_create_package("/my/pkg")?;
24/// let base_type = package.create_sw_base_type("MyBaseType",
25///    8, BaseTypeEncoding::None, None, None, Some("uint8"))?;
26/// assert!(model.get_element_by_path("/my/pkg/MyBaseType").is_some());
27/// # Ok(())}
28/// ```
29#[derive(Debug, Clone, PartialEq, Eq, Hash)]
30pub struct SwBaseType(Element);
31abstraction_element!(SwBaseType, SwBaseType);
32impl IdentifiableAbstractionElement for SwBaseType {}
33
34impl SwBaseType {
35    /// create a new `SwBaseType` in the given package
36    pub(crate) fn new(
37        name: &str,
38        package: &ArPackage,
39        bit_length: u32,
40        base_type_encoding: BaseTypeEncoding,
41        byte_order: Option<ByteOrder>,
42        mem_alignment: Option<u32>,
43        native_declaration: Option<&str>,
44    ) -> Result<Self, AutosarAbstractionError> {
45        let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
46        let sw_base_type = Self(elements.create_named_sub_element(ElementName::SwBaseType, name)?);
47        sw_base_type
48            .element()
49            .create_sub_element(ElementName::Category)?
50            .set_character_data("FIXED_LENGTH")?;
51        sw_base_type.set_base_type_encoding(base_type_encoding)?;
52        sw_base_type.set_bit_length(bit_length)?;
53        if let Some(byte_order) = byte_order {
54            sw_base_type.set_byte_order(byte_order)?;
55        }
56        if let Some(mem_alignment) = mem_alignment {
57            sw_base_type.set_mem_alignment(mem_alignment)?;
58        }
59        if let Some(native_declaration) = native_declaration {
60            sw_base_type.set_native_declaration(native_declaration)?;
61        }
62
63        Ok(sw_base_type)
64    }
65
66    /// set the base type size (in bits) of the `SwBaseType`
67    pub fn set_bit_length(&self, bit_length: u32) -> Result<(), AutosarAbstractionError> {
68        self.element()
69            .get_or_create_sub_element(ElementName::BaseTypeSize)?
70            .set_character_data(bit_length.to_string())?;
71        Ok(())
72    }
73
74    /// get the bit length of the `SwBaseType`
75    #[must_use]
76    pub fn bit_length(&self) -> Option<u32> {
77        self.element()
78            .get_sub_element(ElementName::BaseTypeSize)?
79            .character_data()?
80            .parse_integer()
81    }
82
83    /// set the base type encoding of the `SwBaseType`
84    pub fn set_base_type_encoding(&self, base_type_encoding: BaseTypeEncoding) -> Result<(), AutosarAbstractionError> {
85        self.element()
86            .get_or_create_sub_element(ElementName::BaseTypeEncoding)?
87            .set_character_data(base_type_encoding.to_string())?;
88        Ok(())
89    }
90
91    /// get the base type encoding of the `SwBaseType`
92    #[must_use]
93    pub fn base_type_encoding(&self) -> Option<BaseTypeEncoding> {
94        let encoding_text = self
95            .element()
96            .get_sub_element(ElementName::BaseTypeEncoding)?
97            .character_data()?
98            .string_value()?;
99        BaseTypeEncoding::try_from(&*encoding_text).ok()
100    }
101
102    /// set the byte order of the `SwBaseType`
103    ///
104    /// The byte order is platform specific and should only be set when it is really needed.
105    pub fn set_byte_order(&self, byte_order: ByteOrder) -> Result<(), AutosarAbstractionError> {
106        self.element()
107            .get_or_create_sub_element(ElementName::ByteOrder)?
108            .set_character_data::<EnumItem>(byte_order.into())?;
109        Ok(())
110    }
111
112    /// get the byte order of the `SwBaseType`
113    #[must_use]
114    pub fn byte_order(&self) -> Option<ByteOrder> {
115        self.element()
116            .get_sub_element(ElementName::ByteOrder)?
117            .character_data()?
118            .enum_value()?
119            .try_into()
120            .ok()
121    }
122
123    /// set the memory alignment of the `SwBaseType`
124    ///
125    /// The memory alignment describes the slignement in bits. Example: 8 means that the type is aligned to a byte.
126    /// Since the memory alignment is platform specific, it should only be set when it is really needed.
127    pub fn set_mem_alignment(&self, mem_alignment: u32) -> Result<(), AutosarAbstractionError> {
128        self.element()
129            .get_or_create_sub_element(ElementName::MemAlignment)?
130            .set_character_data(mem_alignment.to_string())?;
131        Ok(())
132    }
133
134    /// get the memory alignment of the `SwBaseType`
135    #[must_use]
136    pub fn mem_alignment(&self) -> Option<u32> {
137        self.element()
138            .get_sub_element(ElementName::MemAlignment)?
139            .character_data()?
140            .parse_integer()
141    }
142
143    /// set the native declaration of the `SwBaseType`
144    ///
145    /// The native declaration is a string that represents the type in the native programming language.
146    pub fn set_native_declaration(&self, native_declaration: &str) -> Result<(), AutosarAbstractionError> {
147        self.element()
148            .get_or_create_sub_element(ElementName::NativeDeclaration)?
149            .set_character_data(native_declaration)?;
150        Ok(())
151    }
152
153    /// get the native declaration of the `SwBaseType`
154    #[must_use]
155    pub fn native_declaration(&self) -> Option<String> {
156        self.element()
157            .get_sub_element(ElementName::NativeDeclaration)?
158            .character_data()?
159            .string_value()
160    }
161}
162
163//#########################################################
164
165/// `BaseTypeEncoding` describes the encoding of a basic data type.
166#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
167pub enum BaseTypeEncoding {
168    /// `OnesComplement` is used for signed integers
169    OnesComplement,
170    /// `TwosComplement` is used for signed integers
171    TwosComplement,
172    /// `SignMagnitude` is used for signed integers
173    SignMagnitude,
174    /// `BcdPacked` is used for packed binary coded decimals
175    BcdPacked,
176    /// `BcdUnpacked` is used for unpacked binary coded decimals
177    BcdUnpacked,
178    /// `DspFractional` is used for values in a digital signal processor
179    DspFractional,
180    /// Ieee754 is used for floating point numbers
181    Ieee754,
182    /// encoding: `Iso8859_1` is used for strings
183    Iso8859_1,
184    /// encoding: `Iso8859_2` is used for strings
185    Iso8859_2,
186    /// encoding: Windows1252 is used for strings
187    Windows1252,
188    /// encoding: Utf8 is used for strings
189    Utf8,
190    /// encoding: Utf16 is used for strings - byte order must be specified
191    Utf16,
192    /// encoding: Ucs2 is used for strings
193    Ucs2,
194    /// encoding: Boolean is used for boolean values
195    Boolean,
196    /// encoding: Void is used for C void types
197    Void,
198    /// encoding: None is used for unsigned integers
199    None,
200}
201
202impl Display for BaseTypeEncoding {
203    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
204        match self {
205            BaseTypeEncoding::OnesComplement => f.write_str("1C"),
206            BaseTypeEncoding::TwosComplement => f.write_str("2C"),
207            BaseTypeEncoding::SignMagnitude => f.write_str("SM"),
208            BaseTypeEncoding::BcdPacked => f.write_str("BCD-P"),
209            BaseTypeEncoding::BcdUnpacked => f.write_str("BCD-UP"),
210            BaseTypeEncoding::DspFractional => f.write_str("DSP-FRACTIONAL"),
211            BaseTypeEncoding::Ieee754 => f.write_str("IEEE754"),
212            BaseTypeEncoding::Iso8859_1 => f.write_str("ISO-8859-1"),
213            BaseTypeEncoding::Iso8859_2 => f.write_str("ISO-8859-2"),
214            BaseTypeEncoding::Windows1252 => f.write_str("WINDOWS-1252"),
215            BaseTypeEncoding::Utf8 => f.write_str("UTF-8"),
216            BaseTypeEncoding::Utf16 => f.write_str("UTF-16"),
217            BaseTypeEncoding::Ucs2 => f.write_str("UCS-2"),
218            BaseTypeEncoding::Boolean => f.write_str("BOOLEAN"),
219            BaseTypeEncoding::Void => f.write_str("VOID"),
220            BaseTypeEncoding::None => f.write_str("NONE"),
221        }
222    }
223}
224
225impl TryFrom<&str> for BaseTypeEncoding {
226    type Error = AutosarAbstractionError;
227
228    fn try_from(value: &str) -> Result<Self, Self::Error> {
229        match value {
230            "1C" => Ok(BaseTypeEncoding::OnesComplement),
231            "2C" => Ok(BaseTypeEncoding::TwosComplement),
232            "SM" => Ok(BaseTypeEncoding::SignMagnitude),
233            "BCD-P" => Ok(BaseTypeEncoding::BcdPacked),
234            "BCD-UP" => Ok(BaseTypeEncoding::BcdUnpacked),
235            "DSP-FRACTIONAL" => Ok(BaseTypeEncoding::DspFractional),
236            "IEEE754" => Ok(BaseTypeEncoding::Ieee754),
237            "ISO-8859-1" => Ok(BaseTypeEncoding::Iso8859_1),
238            "ISO-8859-2" => Ok(BaseTypeEncoding::Iso8859_2),
239            "WINDOWS-1252" => Ok(BaseTypeEncoding::Windows1252),
240            "UTF-8" => Ok(BaseTypeEncoding::Utf8),
241            "UTF-16" => Ok(BaseTypeEncoding::Utf16),
242            "UCS-2" => Ok(BaseTypeEncoding::Ucs2),
243            "BOOLEAN" => Ok(BaseTypeEncoding::Boolean),
244            "VOID" => Ok(BaseTypeEncoding::Void),
245            "NONE" => Ok(BaseTypeEncoding::None),
246            _ => Err(AutosarAbstractionError::ValueConversionError {
247                value: value.to_string(),
248                dest: "BaseTypeEncoding".to_string(),
249            }),
250        }
251    }
252}
253
254//#########################################################
255
256#[cfg(test)]
257mod tests {
258    use crate::AutosarModelAbstraction;
259
260    use super::*;
261    use autosar_data::AutosarVersion;
262
263    #[test]
264    fn test_base_type_encoding() {
265        let encoding = BaseTypeEncoding::OnesComplement;
266        assert_eq!(encoding.to_string(), "1C");
267        assert_eq!(BaseTypeEncoding::try_from("1C").unwrap(), encoding);
268    }
269
270    #[test]
271    fn test_sw_base_type() {
272        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
273        let package = model.get_or_create_package("/BaseTypes").unwrap();
274
275        let sw_base_type = SwBaseType::new(
276            "TestType",
277            &package,
278            32,
279            BaseTypeEncoding::None,
280            Some(ByteOrder::MostSignificantByteFirst),
281            Some(8),
282            Some("uint32"),
283        )
284        .unwrap();
285        assert_eq!(sw_base_type.bit_length(), Some(32));
286        assert_eq!(sw_base_type.base_type_encoding(), Some(BaseTypeEncoding::None));
287        assert_eq!(sw_base_type.byte_order(), Some(ByteOrder::MostSignificantByteFirst));
288        assert_eq!(sw_base_type.mem_alignment(), Some(8));
289        assert_eq!(sw_base_type.native_declaration(), Some("uint32".to_string()));
290    }
291}