autosar_data_abstraction/ecu_configuration/definition/
parameter.rs

1use crate::ecu_configuration::{EcucCommonAttributes, EcucDefinitionElement};
2use crate::{AbstractionElement, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element};
3use autosar_data::{Element, ElementName};
4
5//#########################################################
6
7/// This trait provides the common operation shared by all string parameter definitions
8pub trait EcucAbstractStringParamDef: EcucCommonAttributes {
9    /// set or remove the max length attribute
10    fn set_max_length(&self, max_length: Option<u32>) -> Result<(), AutosarAbstractionError>;
11
12    /// get the max length attribute
13    fn max_length(&self) -> Option<u32>;
14
15    /// set or remove the min length attribute
16    fn set_min_length(&self, min_length: Option<u32>) -> Result<(), AutosarAbstractionError>;
17
18    /// get the min length attribute
19    fn min_length(&self) -> Option<u32>;
20
21    /// set or remove the regular expression attribute
22    /// The regular expression is a string that is used to validate the string parameter
23    fn set_regular_expression(&self, regular_expression: Option<&str>) -> Result<(), AutosarAbstractionError>;
24
25    /// get the regular expression attribute
26    /// The regular expression is a string that is used to validate the string parameter
27    fn regular_expression(&self) -> Option<String>;
28
29    /// set or remove the default value attribute
30    fn set_default_value(&self, default_value: Option<&str>) -> Result<(), AutosarAbstractionError>;
31
32    /// get the default value attribute
33    fn default_value(&self) -> Option<String>;
34}
35
36macro_rules! string_param {
37    ($name: ident, $elemname_variants: ident, $elemname_conditional: ident) => {
38        impl EcucAbstractStringParamDef for $name {
39            fn set_max_length(&self, max_length: Option<u32>) -> Result<(), AutosarAbstractionError> {
40                if let Some(max_length) = max_length {
41                    self.element()
42                        .get_or_create_sub_element(ElementName::$elemname_variants)?
43                        .get_or_create_sub_element(ElementName::$elemname_conditional)?
44                        .get_or_create_sub_element(ElementName::MaxLength)?
45                        .set_character_data(max_length as u64)?;
46                } else {
47                    if let Some(espdc) = self
48                        .element()
49                        .get_sub_element(ElementName::$elemname_variants)
50                        .and_then(|espdv| espdv.get_sub_element(ElementName::$elemname_conditional))
51                    {
52                        let _ = espdc.remove_sub_element_kind(ElementName::MaxLength);
53                    }
54                }
55
56                Ok(())
57            }
58
59            /// get the max length attribute
60            fn max_length(&self) -> Option<u32> {
61                self.element()
62                    .get_sub_element(ElementName::$elemname_variants)?
63                    .get_sub_element(ElementName::$elemname_conditional)?
64                    .get_sub_element(ElementName::MaxLength)?
65                    .character_data()?
66                    .parse_integer()
67            }
68
69            /// set or remove the min length attribute
70            fn set_min_length(&self, min_length: Option<u32>) -> Result<(), AutosarAbstractionError> {
71                if let Some(min_length) = min_length {
72                    self.element()
73                        .get_or_create_sub_element(ElementName::$elemname_variants)?
74                        .get_or_create_sub_element(ElementName::$elemname_conditional)?
75                        .get_or_create_sub_element(ElementName::MinLength)?
76                        .set_character_data(min_length as u64)?;
77                } else {
78                    if let Some(espdc) = self
79                        .element()
80                        .get_sub_element(ElementName::$elemname_variants)
81                        .and_then(|espdv| espdv.get_sub_element(ElementName::$elemname_conditional))
82                    {
83                        let _ = espdc.remove_sub_element_kind(ElementName::MinLength);
84                    }
85                }
86
87                Ok(())
88            }
89
90            /// get the min length attribute
91            fn min_length(&self) -> Option<u32> {
92                self.element()
93                    .get_sub_element(ElementName::$elemname_variants)?
94                    .get_sub_element(ElementName::$elemname_conditional)?
95                    .get_sub_element(ElementName::MinLength)?
96                    .character_data()?
97                    .parse_integer()
98            }
99
100            /// set or remove the regular expression attribute
101            /// The regular expression is a string that is used to validate the string parameter
102            fn set_regular_expression(&self, regular_expression: Option<&str>) -> Result<(), AutosarAbstractionError> {
103                if let Some(regular_expression) = regular_expression {
104                    self.element()
105                        .get_or_create_sub_element(ElementName::$elemname_variants)?
106                        .get_or_create_sub_element(ElementName::$elemname_conditional)?
107                        .get_or_create_sub_element(ElementName::RegularExpression)?
108                        .set_character_data(regular_expression)?;
109                } else {
110                    if let Some(espdc) = self
111                        .element()
112                        .get_sub_element(ElementName::$elemname_variants)
113                        .and_then(|espdv| espdv.get_sub_element(ElementName::$elemname_conditional))
114                    {
115                        let _ = espdc.remove_sub_element_kind(ElementName::RegularExpression);
116                    }
117                }
118
119                Ok(())
120            }
121
122            /// get the regular expression attribute
123            /// The regular expression is a string that is used to validate the string parameter
124            fn regular_expression(&self) -> Option<String> {
125                self.element()
126                    .get_sub_element(ElementName::$elemname_variants)?
127                    .get_sub_element(ElementName::$elemname_conditional)?
128                    .get_sub_element(ElementName::RegularExpression)?
129                    .character_data()?
130                    .string_value()
131            }
132
133            /// set or remove the default value attribute
134            fn set_default_value(&self, default_value: Option<&str>) -> Result<(), AutosarAbstractionError> {
135                if let Some(default_value) = default_value {
136                    self.element()
137                        .get_or_create_sub_element(ElementName::$elemname_variants)?
138                        .get_or_create_sub_element(ElementName::$elemname_conditional)?
139                        .get_or_create_sub_element(ElementName::DefaultValue)?
140                        .set_character_data(default_value)?;
141                } else {
142                    if let Some(espdc) = self
143                        .element()
144                        .get_sub_element(ElementName::$elemname_variants)
145                        .and_then(|espdv| espdv.get_sub_element(ElementName::$elemname_conditional))
146                    {
147                        let _ = espdc.remove_sub_element_kind(ElementName::DefaultValue);
148                    }
149                }
150
151                Ok(())
152            }
153
154            /// get the default value attribute
155            fn default_value(&self) -> Option<String> {
156                self.element()
157                    .get_sub_element(ElementName::$elemname_variants)?
158                    .get_sub_element(ElementName::$elemname_conditional)?
159                    .get_sub_element(ElementName::DefaultValue)?
160                    .character_data()?
161                    .string_value()
162            }
163        }
164        impl EcucTextualParamDef for $name {}
165    };
166}
167
168//#########################################################
169
170/// marker trait for all parameter defintions
171pub trait EcucParamDef: EcucCommonAttributes {}
172
173//#########################################################
174
175/// marker trait for numerical parameter defintions: `EcucFloatParamDef`, `EcucIntegerParamDef`, `EcucBooleanParamDef`
176pub trait EcucNumericalParamDef: EcucParamDef {}
177
178//#########################################################
179
180/// marker trait for textual parameter defintions: `EcucEnumerationParamDef`,
181/// `EcucFunctionNameDef`, `EcucLinkerSymbolDef`, `EcucMultilineStringParamDef`, `EcucStringParamDef`
182///
183/// This grouping is determined by the usage in the value definition: `EcucTextualParamValue` can refer to any of these
184pub trait EcucTextualParamDef: EcucParamDef {}
185
186//#########################################################
187
188/// `EcucAddInfoParamDef` is used to specify the need for formated text in the ECU configuration value description
189#[derive(Debug, Clone, PartialEq, Eq, Hash)]
190pub struct EcucAddInfoParamDef(Element);
191abstraction_element!(EcucAddInfoParamDef, EcucAddInfoParamDef);
192impl IdentifiableAbstractionElement for EcucAddInfoParamDef {}
193impl EcucCommonAttributes for EcucAddInfoParamDef {}
194impl EcucDefinitionElement for EcucAddInfoParamDef {}
195
196impl EcucAddInfoParamDef {
197    pub(crate) fn new(name: &str, parameters_elem: &Element, origin: &str) -> Result<Self, AutosarAbstractionError> {
198        let addinfo_def_elem = parameters_elem.create_named_sub_element(ElementName::EcucAddInfoParamDef, name)?;
199
200        let addinfo_def = Self(addinfo_def_elem);
201        addinfo_def.set_origin(origin)?;
202
203        Ok(addinfo_def)
204    }
205}
206
207//#########################################################
208
209/// `EcucBooleanParamDef` is used to specify a boolean parameter in the ECU configuration
210#[derive(Debug, Clone, PartialEq, Eq, Hash)]
211pub struct EcucBooleanParamDef(Element);
212abstraction_element!(EcucBooleanParamDef, EcucBooleanParamDef);
213impl IdentifiableAbstractionElement for EcucBooleanParamDef {}
214impl EcucCommonAttributes for EcucBooleanParamDef {}
215impl EcucDefinitionElement for EcucBooleanParamDef {}
216impl EcucParamDef for EcucBooleanParamDef {}
217impl EcucNumericalParamDef for EcucBooleanParamDef {}
218
219impl EcucBooleanParamDef {
220    pub(crate) fn new(name: &str, parameters_elem: &Element, origin: &str) -> Result<Self, AutosarAbstractionError> {
221        let boolean_def_elem = parameters_elem.create_named_sub_element(ElementName::EcucBooleanParamDef, name)?;
222
223        let boolean_def = Self(boolean_def_elem);
224        boolean_def.set_origin(origin)?;
225
226        Ok(boolean_def)
227    }
228
229    /// set the default value of the boolean parameter
230    pub fn set_default_value(&self, default_value: Option<bool>) -> Result<(), AutosarAbstractionError> {
231        if let Some(default_value) = default_value {
232            self.element()
233                .get_or_create_sub_element(ElementName::DefaultValue)?
234                .set_character_data(default_value)?;
235        } else {
236            let _ = self.element().remove_sub_element_kind(ElementName::DefaultValue);
237        }
238
239        Ok(())
240    }
241
242    /// get the default value of the boolean parameter
243    #[must_use]
244    pub fn default_value(&self) -> Option<bool> {
245        self.element()
246            .get_sub_element(ElementName::DefaultValue)?
247            .character_data()?
248            .parse_bool()
249    }
250}
251
252//#########################################################
253
254/// `EcucEnumerationParamDef` is used to specify an enumeration parameter in the ECU configuration
255#[derive(Debug, Clone, PartialEq, Eq, Hash)]
256pub struct EcucEnumerationParamDef(Element);
257abstraction_element!(EcucEnumerationParamDef, EcucEnumerationParamDef);
258impl IdentifiableAbstractionElement for EcucEnumerationParamDef {}
259impl EcucCommonAttributes for EcucEnumerationParamDef {}
260impl EcucDefinitionElement for EcucEnumerationParamDef {}
261impl EcucParamDef for EcucEnumerationParamDef {}
262impl EcucTextualParamDef for EcucEnumerationParamDef {}
263
264impl EcucEnumerationParamDef {
265    pub(crate) fn new(name: &str, parameters_elem: &Element, origin: &str) -> Result<Self, AutosarAbstractionError> {
266        let enumeration_def_elem =
267            parameters_elem.create_named_sub_element(ElementName::EcucEnumerationParamDef, name)?;
268
269        let enumeration_def = Self(enumeration_def_elem);
270        enumeration_def.set_origin(origin)?;
271
272        Ok(enumeration_def)
273    }
274
275    /// create a new enumeration literal
276    pub fn create_enumeration_literal(&self, name: &str) -> Result<EcucEnumerationLiteralDef, AutosarAbstractionError> {
277        let literals_elem = self.element().get_or_create_sub_element(ElementName::Literals)?;
278
279        EcucEnumerationLiteralDef::new(name, &literals_elem)
280    }
281
282    /// iterate over all enumeration literals
283    pub fn enumeration_literals(&self) -> impl Iterator<Item = EcucEnumerationLiteralDef> + Send + use<> {
284        self.element()
285            .get_sub_element(ElementName::Literals)
286            .into_iter()
287            .flat_map(|literals_elem| literals_elem.sub_elements())
288            .filter_map(|elem| elem.try_into().ok())
289    }
290
291    /// set the default value of the enumeration parameter
292    ///
293    /// Note: enumeration literals must be created first, since the default value must match one of the literals
294    pub fn set_default_value(&self, default_value: Option<&str>) -> Result<(), AutosarAbstractionError> {
295        if let Some(default_value) = default_value {
296            if !self
297                .enumeration_literals()
298                .any(|literal| literal.name().as_deref() == Some(default_value))
299            {
300                return Err(AutosarAbstractionError::InvalidParameter(format!(
301                    "Default value {default_value} not found in enumeration literals"
302                )));
303            }
304            self.element()
305                .get_or_create_sub_element(ElementName::DefaultValue)?
306                .set_character_data(default_value)?;
307        } else {
308            let _ = self.element().remove_sub_element_kind(ElementName::DefaultValue);
309        }
310
311        Ok(())
312    }
313
314    /// get the default value of the enumeration parameter
315    #[must_use]
316    pub fn default_value(&self) -> Option<String> {
317        self.element()
318            .get_sub_element(ElementName::DefaultValue)?
319            .character_data()?
320            .string_value()
321    }
322}
323
324//#########################################################
325
326/// `EcucEnumerationLiteralDef` is used to specify an enumeration literal in the ECU configuration
327#[derive(Debug, Clone, PartialEq, Eq, Hash)]
328pub struct EcucEnumerationLiteralDef(Element);
329abstraction_element!(EcucEnumerationLiteralDef, EcucEnumerationLiteralDef);
330impl IdentifiableAbstractionElement for EcucEnumerationLiteralDef {}
331
332impl EcucEnumerationLiteralDef {
333    pub(crate) fn new(name: &str, literals_elem: &Element) -> Result<Self, AutosarAbstractionError> {
334        let enumeration_literal_def_elem =
335            literals_elem.create_named_sub_element(ElementName::EcucEnumerationLiteralDef, name)?;
336
337        Ok(Self(enumeration_literal_def_elem))
338    }
339}
340
341//#########################################################
342
343/// `EcucFloatParamDef` is used to specify a float parameter in the ECU configuration
344#[derive(Debug, Clone, PartialEq, Eq, Hash)]
345pub struct EcucFloatParamDef(Element);
346abstraction_element!(EcucFloatParamDef, EcucFloatParamDef);
347impl IdentifiableAbstractionElement for EcucFloatParamDef {}
348impl EcucCommonAttributes for EcucFloatParamDef {}
349impl EcucDefinitionElement for EcucFloatParamDef {}
350impl EcucParamDef for EcucFloatParamDef {}
351impl EcucNumericalParamDef for EcucFloatParamDef {}
352
353impl EcucFloatParamDef {
354    pub(crate) fn new(name: &str, parameters_elem: &Element, origin: &str) -> Result<Self, AutosarAbstractionError> {
355        let float_def_elem = parameters_elem.create_named_sub_element(ElementName::EcucFloatParamDef, name)?;
356
357        let float_def = Self(float_def_elem);
358        float_def.set_origin(origin)?;
359
360        Ok(float_def)
361    }
362
363    /// set the default value of the float parameter
364    pub fn set_default_value(&self, default_value: Option<f64>) -> Result<(), AutosarAbstractionError> {
365        if let Some(default_value) = default_value {
366            self.element()
367                .get_or_create_sub_element(ElementName::DefaultValue)?
368                .set_character_data(default_value)?;
369        } else {
370            let _ = self.element().remove_sub_element_kind(ElementName::DefaultValue);
371        }
372
373        Ok(())
374    }
375
376    /// get the default value of the float parameter
377    #[must_use]
378    pub fn default_value(&self) -> Option<f64> {
379        self.element()
380            .get_sub_element(ElementName::DefaultValue)?
381            .character_data()?
382            .parse_float()
383    }
384
385    /// set the min value of the float parameter
386    pub fn set_min(&self, min: Option<f64>) -> Result<(), AutosarAbstractionError> {
387        if let Some(min) = min {
388            self.element()
389                .get_or_create_sub_element(ElementName::Min)?
390                .set_character_data(min)?;
391        } else {
392            let _ = self.element().remove_sub_element_kind(ElementName::Min);
393        }
394
395        Ok(())
396    }
397
398    /// get the min value of the float parameter
399    #[must_use]
400    pub fn min(&self) -> Option<f64> {
401        self.element()
402            .get_sub_element(ElementName::Min)?
403            .character_data()?
404            .parse_float()
405    }
406
407    /// set the max value of the float parameter
408    pub fn set_max(&self, max: Option<f64>) -> Result<(), AutosarAbstractionError> {
409        if let Some(max) = max {
410            self.element()
411                .get_or_create_sub_element(ElementName::Max)?
412                .set_character_data(max)?;
413        } else {
414            let _ = self.element().remove_sub_element_kind(ElementName::Max);
415        }
416
417        Ok(())
418    }
419
420    /// get the max value of the float parameter
421    #[must_use]
422    pub fn max(&self) -> Option<f64> {
423        self.element()
424            .get_sub_element(ElementName::Max)?
425            .character_data()?
426            .parse_float()
427    }
428}
429
430//#########################################################
431
432/// `EcucIntegerParamDef` is used to specify an integer parameter in the ECU configuration
433#[derive(Debug, Clone, PartialEq, Eq, Hash)]
434pub struct EcucIntegerParamDef(Element);
435abstraction_element!(EcucIntegerParamDef, EcucIntegerParamDef);
436impl IdentifiableAbstractionElement for EcucIntegerParamDef {}
437impl EcucCommonAttributes for EcucIntegerParamDef {}
438impl EcucDefinitionElement for EcucIntegerParamDef {}
439impl EcucParamDef for EcucIntegerParamDef {}
440impl EcucNumericalParamDef for EcucIntegerParamDef {}
441
442impl EcucIntegerParamDef {
443    pub(crate) fn new(name: &str, parameters_elem: &Element, origin: &str) -> Result<Self, AutosarAbstractionError> {
444        let integer_def_elem = parameters_elem.create_named_sub_element(ElementName::EcucIntegerParamDef, name)?;
445
446        let integer_def = Self(integer_def_elem);
447        integer_def.set_origin(origin)?;
448
449        Ok(integer_def)
450    }
451
452    /// set the default value of the integer parameter
453    pub fn set_default_value(&self, default_value: Option<i64>) -> Result<(), AutosarAbstractionError> {
454        if let Some(default_value) = default_value {
455            self.element()
456                .get_or_create_sub_element(ElementName::DefaultValue)?
457                .set_character_data(default_value.to_string())?;
458        } else {
459            let _ = self.element().remove_sub_element_kind(ElementName::DefaultValue);
460        }
461
462        Ok(())
463    }
464
465    /// get the default value of the integer parameter
466    #[must_use]
467    pub fn default_value(&self) -> Option<i64> {
468        self.element()
469            .get_sub_element(ElementName::DefaultValue)?
470            .character_data()?
471            .parse_integer()
472    }
473
474    /// set the min value of the integer parameter
475    pub fn set_min(&self, min: Option<i64>) -> Result<(), AutosarAbstractionError> {
476        if let Some(min) = min {
477            self.element()
478                .get_or_create_sub_element(ElementName::Min)?
479                .set_character_data(min.to_string())?;
480        } else {
481            let _ = self.element().remove_sub_element_kind(ElementName::Min);
482        }
483
484        Ok(())
485    }
486
487    /// get the min value of the integer parameter
488    #[must_use]
489    pub fn min(&self) -> Option<i64> {
490        self.element()
491            .get_sub_element(ElementName::Min)?
492            .character_data()?
493            .parse_integer()
494    }
495
496    /// set the max value of the integer parameter
497    pub fn set_max(&self, max: Option<i64>) -> Result<(), AutosarAbstractionError> {
498        if let Some(max) = max {
499            self.element()
500                .get_or_create_sub_element(ElementName::Max)?
501                .set_character_data(max.to_string())?;
502        } else {
503            let _ = self.element().remove_sub_element_kind(ElementName::Max);
504        }
505
506        Ok(())
507    }
508
509    /// get the max value of the integer parameter
510    #[must_use]
511    pub fn max(&self) -> Option<i64> {
512        self.element()
513            .get_sub_element(ElementName::Max)?
514            .character_data()?
515            .parse_integer()
516    }
517}
518
519//#########################################################
520
521/// `EcucFunctionNameDef` is used to specify a function name parameter in the ECU configuration
522#[derive(Debug, Clone, PartialEq, Eq, Hash)]
523pub struct EcucFunctionNameDef(Element);
524abstraction_element!(EcucFunctionNameDef, EcucFunctionNameDef);
525impl IdentifiableAbstractionElement for EcucFunctionNameDef {}
526impl EcucCommonAttributes for EcucFunctionNameDef {}
527impl EcucDefinitionElement for EcucFunctionNameDef {}
528impl EcucParamDef for EcucFunctionNameDef {}
529
530string_param!(
531    EcucFunctionNameDef,
532    EcucFunctionNameDefVariants,
533    EcucFunctionNameDefConditional
534);
535
536impl EcucFunctionNameDef {
537    pub(crate) fn new(name: &str, parameters_elem: &Element, origin: &str) -> Result<Self, AutosarAbstractionError> {
538        let function_name_def_elem =
539            parameters_elem.create_named_sub_element(ElementName::EcucFunctionNameDef, name)?;
540
541        let function_name_def = Self(function_name_def_elem);
542        function_name_def.set_origin(origin)?;
543
544        Ok(function_name_def)
545    }
546}
547
548//#########################################################
549
550/// `EcucLinkerSymbolDef` is used to specify a linker symbol parameter in the ECU configuration
551#[derive(Debug, Clone, PartialEq, Eq, Hash)]
552pub struct EcucLinkerSymbolDef(Element);
553abstraction_element!(EcucLinkerSymbolDef, EcucLinkerSymbolDef);
554impl IdentifiableAbstractionElement for EcucLinkerSymbolDef {}
555impl EcucCommonAttributes for EcucLinkerSymbolDef {}
556impl EcucDefinitionElement for EcucLinkerSymbolDef {}
557impl EcucParamDef for EcucLinkerSymbolDef {}
558
559string_param!(
560    EcucLinkerSymbolDef,
561    EcucLinkerSymbolDefVariants,
562    EcucLinkerSymbolDefConditional
563);
564
565impl EcucLinkerSymbolDef {
566    pub(crate) fn new(name: &str, parameters_elem: &Element, origin: &str) -> Result<Self, AutosarAbstractionError> {
567        let linker_symbol_def_elem =
568            parameters_elem.create_named_sub_element(ElementName::EcucLinkerSymbolDef, name)?;
569
570        let linker_symbol_def = Self(linker_symbol_def_elem);
571        linker_symbol_def.set_origin(origin)?;
572
573        Ok(linker_symbol_def)
574    }
575}
576
577//#########################################################
578
579/// `EcucMultilineStringParamDef` is used to specify a multiline string parameter in the ECU configuration
580#[derive(Debug, Clone, PartialEq, Eq, Hash)]
581pub struct EcucMultilineStringParamDef(Element);
582abstraction_element!(EcucMultilineStringParamDef, EcucMultilineStringParamDef);
583impl IdentifiableAbstractionElement for EcucMultilineStringParamDef {}
584impl EcucCommonAttributes for EcucMultilineStringParamDef {}
585impl EcucDefinitionElement for EcucMultilineStringParamDef {}
586impl EcucParamDef for EcucMultilineStringParamDef {}
587
588string_param!(
589    EcucMultilineStringParamDef,
590    EcucMultilineStringParamDefVariants,
591    EcucMultilineStringParamDefConditional
592);
593
594impl EcucMultilineStringParamDef {
595    pub(crate) fn new(name: &str, parameters_elem: &Element, origin: &str) -> Result<Self, AutosarAbstractionError> {
596        let multiline_string_def_elem =
597            parameters_elem.create_named_sub_element(ElementName::EcucMultilineStringParamDef, name)?;
598
599        let multiline_string_def = Self(multiline_string_def_elem);
600        multiline_string_def.set_origin(origin)?;
601
602        Ok(multiline_string_def)
603    }
604}
605
606//#########################################################
607
608/// `EcucStringParamDef` is used to specify a string parameter in the ECU configuration
609#[derive(Debug, Clone, PartialEq, Eq, Hash)]
610pub struct EcucStringParamDef(Element);
611abstraction_element!(EcucStringParamDef, EcucStringParamDef);
612impl IdentifiableAbstractionElement for EcucStringParamDef {}
613impl EcucCommonAttributes for EcucStringParamDef {}
614impl EcucDefinitionElement for EcucStringParamDef {}
615impl EcucParamDef for EcucStringParamDef {}
616
617string_param!(
618    EcucStringParamDef,
619    EcucStringParamDefVariants,
620    EcucStringParamDefConditional
621);
622
623impl EcucStringParamDef {
624    pub(crate) fn new(name: &str, parameters_elem: &Element, origin: &str) -> Result<Self, AutosarAbstractionError> {
625        let string_def_elem = parameters_elem.create_named_sub_element(ElementName::EcucStringParamDef, name)?;
626
627        let string_def = Self(string_def_elem);
628        string_def.set_origin(origin)?;
629
630        Ok(string_def)
631    }
632}
633
634//#########################################################
635
636/// `EcucParameterDef` encapsulates all possible parameter types in the ECU configuration, and is used as a return type for the iterator
637#[derive(Debug, Clone, PartialEq, Eq, Hash)]
638pub enum EcucParameterDef {
639    /// AddInfo parameter
640    AddInfo(EcucAddInfoParamDef),
641    /// Boolean parameter
642    Boolean(EcucBooleanParamDef),
643    /// Enumeration parameter
644    Enumeration(EcucEnumerationParamDef),
645    /// Float parameter
646    Float(EcucFloatParamDef),
647    /// Integer parameter
648    Integer(EcucIntegerParamDef),
649    /// FunctionName parameter
650    FunctionName(EcucFunctionNameDef),
651    /// LinkerSymbol parameter
652    LinkerSymbol(EcucLinkerSymbolDef),
653    /// MultilineString parameter
654    MultilineString(EcucMultilineStringParamDef),
655    /// String parameter
656    String(EcucStringParamDef),
657}
658
659impl AbstractionElement for EcucParameterDef {
660    fn element(&self) -> &Element {
661        match self {
662            EcucParameterDef::AddInfo(elem) => elem.element(),
663            EcucParameterDef::Boolean(elem) => elem.element(),
664            EcucParameterDef::Enumeration(elem) => elem.element(),
665            EcucParameterDef::Float(elem) => elem.element(),
666            EcucParameterDef::Integer(elem) => elem.element(),
667            EcucParameterDef::FunctionName(elem) => elem.element(),
668            EcucParameterDef::LinkerSymbol(elem) => elem.element(),
669            EcucParameterDef::MultilineString(elem) => elem.element(),
670            EcucParameterDef::String(elem) => elem.element(),
671        }
672    }
673}
674
675impl TryFrom<Element> for EcucParameterDef {
676    type Error = AutosarAbstractionError;
677
678    fn try_from(element: Element) -> Result<Self, Self::Error> {
679        match element.element_name() {
680            ElementName::EcucAddInfoParamDef => Ok(EcucParameterDef::AddInfo(element.try_into()?)),
681            ElementName::EcucBooleanParamDef => Ok(EcucParameterDef::Boolean(element.try_into()?)),
682            ElementName::EcucEnumerationParamDef => Ok(EcucParameterDef::Enumeration(element.try_into()?)),
683            ElementName::EcucFloatParamDef => Ok(EcucParameterDef::Float(element.try_into()?)),
684            ElementName::EcucIntegerParamDef => Ok(EcucParameterDef::Integer(element.try_into()?)),
685            ElementName::EcucFunctionNameDef => Ok(EcucParameterDef::FunctionName(element.try_into()?)),
686            ElementName::EcucLinkerSymbolDef => Ok(EcucParameterDef::LinkerSymbol(element.try_into()?)),
687            ElementName::EcucMultilineStringParamDef => Ok(EcucParameterDef::MultilineString(element.try_into()?)),
688            ElementName::EcucStringParamDef => Ok(EcucParameterDef::String(EcucStringParamDef(element))),
689            _ => Err(AutosarAbstractionError::ConversionError {
690                element,
691                dest: "EcucParameterDef".to_string(),
692            }),
693        }
694    }
695}
696
697impl IdentifiableAbstractionElement for EcucParameterDef {}
698impl EcucDefinitionElement for EcucParameterDef {}
699impl EcucCommonAttributes for EcucParameterDef {}
700impl EcucParamDef for EcucParameterDef {}
701
702//#########################################################
703
704#[cfg(test)]
705mod test {
706    use super::*;
707    use crate::{
708        AutosarModelAbstraction,
709        ecu_configuration::{EcucConfigurationClass, EcucConfigurationVariant},
710    };
711    use autosar_data::AutosarVersion;
712
713    #[test]
714    fn parameter() {
715        let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::Autosar_00048);
716        let pkg = model.get_or_create_package("/test").unwrap();
717        let ecuc_module = pkg.create_ecuc_module_def("EcucModule").unwrap();
718        let container = ecuc_module.create_param_conf_container_def("Container").unwrap();
719
720        let addinfo = container.create_add_info_param_def("AddInfo", "origin").unwrap();
721        let boolean = container.create_boolean_param_def("Boolean", "origin").unwrap();
722        let enumeration = container.create_enumeration_param_def("Enumeration", "origin").unwrap();
723        let float = container.create_float_param_def("Float", "origin").unwrap();
724        let integer = container.create_integer_param_def("Integer", "origin").unwrap();
725        let function_name = container
726            .create_function_name_param_def("FunctionName", "origin")
727            .unwrap();
728        let linker_symbol = container
729            .create_linker_symbol_param_def("LinkerSymbol", "origin")
730            .unwrap();
731        let multiline_string = container
732            .create_multiline_string_param_def("MultilineString", "origin")
733            .unwrap();
734        let string = container.create_string_param_def("String", "origin").unwrap();
735
736        let addinfo2 = EcucParameterDef::AddInfo(addinfo);
737        let boolean2 = EcucParameterDef::Boolean(boolean);
738        let enumeration2 = EcucParameterDef::Enumeration(enumeration);
739        let float2 = EcucParameterDef::Float(float);
740        let integer2 = EcucParameterDef::Integer(integer);
741        let function_name2 = EcucParameterDef::FunctionName(function_name);
742        let linker_symbol2 = EcucParameterDef::LinkerSymbol(linker_symbol);
743        let multiline_string2 = EcucParameterDef::MultilineString(multiline_string);
744        let string2 = EcucParameterDef::String(string);
745
746        assert_eq!(addinfo2.name(), Some("AddInfo".to_string()));
747        assert_eq!(boolean2.name(), Some("Boolean".to_string()));
748        assert_eq!(enumeration2.name(), Some("Enumeration".to_string()));
749        assert_eq!(float2.name(), Some("Float".to_string()));
750        assert_eq!(integer2.name(), Some("Integer".to_string()));
751        assert_eq!(function_name2.name(), Some("FunctionName".to_string()));
752        assert_eq!(linker_symbol2.name(), Some("LinkerSymbol".to_string()));
753        assert_eq!(multiline_string2.name(), Some("MultilineString".to_string()));
754        assert_eq!(string2.name(), Some("String".to_string()));
755    }
756
757    #[test]
758    fn string_parameters() {
759        let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::Autosar_00048);
760        let pkg = model.get_or_create_package("/test").unwrap();
761        let ecuc_module = pkg.create_ecuc_module_def("EcucModule").unwrap();
762        let container = ecuc_module.create_param_conf_container_def("Container").unwrap();
763
764        let function_name = container
765            .create_function_name_param_def("FunctionName", "origin")
766            .unwrap();
767        function_name.set_max_length(Some(10)).unwrap();
768        assert_eq!(function_name.max_length(), Some(10));
769        function_name.set_max_length(None).unwrap();
770        assert_eq!(function_name.max_length(), None);
771        function_name.set_min_length(Some(5)).unwrap();
772        assert_eq!(function_name.min_length(), Some(5));
773        function_name.set_min_length(None).unwrap();
774        assert_eq!(function_name.min_length(), None);
775        function_name.set_regular_expression(Some(r"^\d{5}$")).unwrap();
776        assert_eq!(function_name.regular_expression(), Some(r"^\d{5}$".to_string()));
777        function_name.set_regular_expression(None).unwrap();
778        assert_eq!(function_name.regular_expression(), None);
779        function_name.set_default_value(Some("12345")).unwrap();
780        assert_eq!(function_name.default_value(), Some("12345".to_string()));
781        function_name.set_default_value(None).unwrap();
782        assert_eq!(function_name.default_value(), None);
783
784        let linker_symbol = container
785            .create_linker_symbol_param_def("LinkerSymbol", "origin")
786            .unwrap();
787        linker_symbol.set_max_length(Some(10)).unwrap();
788        assert_eq!(linker_symbol.max_length(), Some(10));
789        linker_symbol.set_max_length(None).unwrap();
790        assert_eq!(linker_symbol.max_length(), None);
791        linker_symbol.set_min_length(Some(5)).unwrap();
792        assert_eq!(linker_symbol.min_length(), Some(5));
793        linker_symbol.set_min_length(None).unwrap();
794        assert_eq!(linker_symbol.min_length(), None);
795        linker_symbol.set_regular_expression(Some(r"^\d{5}$")).unwrap();
796        assert_eq!(linker_symbol.regular_expression(), Some(r"^\d{5}$".to_string()));
797        linker_symbol.set_regular_expression(None).unwrap();
798        assert_eq!(linker_symbol.regular_expression(), None);
799        linker_symbol.set_default_value(Some("12345")).unwrap();
800        assert_eq!(linker_symbol.default_value(), Some("12345".to_string()));
801        linker_symbol.set_default_value(None).unwrap();
802        assert_eq!(linker_symbol.default_value(), None);
803
804        let multiline_string = container
805            .create_multiline_string_param_def("MultilineString", "origin")
806            .unwrap();
807        multiline_string.set_max_length(Some(10)).unwrap();
808        assert_eq!(multiline_string.max_length(), Some(10));
809        multiline_string.set_max_length(None).unwrap();
810        assert_eq!(multiline_string.max_length(), None);
811        multiline_string.set_min_length(Some(5)).unwrap();
812        assert_eq!(multiline_string.min_length(), Some(5));
813        multiline_string.set_min_length(None).unwrap();
814        assert_eq!(multiline_string.min_length(), None);
815        multiline_string.set_regular_expression(Some(r"^\d{5}$")).unwrap();
816        assert_eq!(multiline_string.regular_expression(), Some(r"^\d{5}$".to_string()));
817        multiline_string.set_regular_expression(None).unwrap();
818        assert_eq!(multiline_string.regular_expression(), None);
819        multiline_string.set_default_value(Some("12345")).unwrap();
820        assert_eq!(multiline_string.default_value(), Some("12345".to_string()));
821        multiline_string.set_default_value(None).unwrap();
822        assert_eq!(multiline_string.default_value(), None);
823
824        let string = container.create_string_param_def("String", "origin").unwrap();
825        string.set_max_length(Some(10)).unwrap();
826        assert_eq!(string.max_length(), Some(10));
827        string.set_max_length(None).unwrap();
828        assert_eq!(string.max_length(), None);
829        string.set_min_length(Some(5)).unwrap();
830        assert_eq!(string.min_length(), Some(5));
831        string.set_min_length(None).unwrap();
832        assert_eq!(string.min_length(), None);
833        string.set_regular_expression(Some(r"^\d{5}$")).unwrap();
834        assert_eq!(string.regular_expression(), Some(r"^\d{5}$".to_string()));
835        string.set_regular_expression(None).unwrap();
836        assert_eq!(string.regular_expression(), None);
837        string.set_default_value(Some("12345")).unwrap();
838        assert_eq!(string.default_value(), Some("12345".to_string()));
839        string.set_default_value(None).unwrap();
840        assert_eq!(string.default_value(), None);
841
842        // trait functions
843        let mcc = [(
844            EcucConfigurationClass::PreCompile,
845            EcucConfigurationVariant::VariantPreCompile,
846        )];
847        string.set_multiplicity_config_classes(&mcc).unwrap();
848        assert_eq!(string.multiplicity_config_classes(), mcc);
849        string.set_origin("AUTOSAR_ECUC").unwrap();
850        assert_eq!(string.origin().as_deref(), Some("AUTOSAR_ECUC"));
851        string.set_post_build_variant_multiplicity(Some(true)).unwrap();
852        assert_eq!(string.post_build_variant_multiplicity(), Some(true));
853        string.set_post_build_variant_value(Some(true)).unwrap();
854        assert_eq!(string.post_build_variant_value(), Some(true));
855        string.set_requires_index(Some(false)).unwrap();
856        assert_eq!(string.requires_index(), Some(false));
857        let vcc = [(
858            EcucConfigurationClass::PostBuild,
859            EcucConfigurationVariant::VariantPostBuild,
860        )];
861        string.set_value_config_classes(&vcc).unwrap();
862        assert_eq!(string.value_config_classes(), vcc);
863        string.set_with_auto(Some(true)).unwrap();
864        assert_eq!(string.with_auto(), Some(true));
865    }
866
867    #[test]
868    fn boolean_parameters() {
869        let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::Autosar_00048);
870        let pkg = model.get_or_create_package("/test").unwrap();
871        let ecuc_module = pkg.create_ecuc_module_def("EcucModule").unwrap();
872        let container = ecuc_module.create_param_conf_container_def("Container").unwrap();
873
874        let boolean = container.create_boolean_param_def("Boolean", "origin").unwrap();
875        boolean.set_default_value(Some(true)).unwrap();
876        assert_eq!(boolean.default_value(), Some(true));
877        boolean.set_default_value(None).unwrap();
878        assert_eq!(boolean.default_value(), None);
879    }
880
881    #[test]
882    fn enumeration_parameters() {
883        let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::Autosar_00048);
884        let pkg = model.get_or_create_package("/test").unwrap();
885        let ecuc_module = pkg.create_ecuc_module_def("EcucModule").unwrap();
886        let container = ecuc_module.create_param_conf_container_def("Container").unwrap();
887
888        let enumeration = container.create_enumeration_param_def("Enumeration", "origin").unwrap();
889        // setting a default value before creating literals should fail
890        let result = enumeration.set_default_value(Some("Literal1"));
891        assert!(result.is_err());
892        // create literals
893        let _literal1 = enumeration.create_enumeration_literal("Literal1").unwrap();
894        let _literal2 = enumeration.create_enumeration_literal("Literal2").unwrap();
895
896        enumeration.set_default_value(Some("Literal1")).unwrap();
897        assert_eq!(enumeration.default_value(), Some("Literal1".to_string()));
898    }
899
900    #[test]
901    fn float_parameters() {
902        let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::Autosar_00048);
903        let pkg = model.get_or_create_package("/test").unwrap();
904        let ecuc_module = pkg.create_ecuc_module_def("EcucModule").unwrap();
905        let container = ecuc_module.create_param_conf_container_def("Container").unwrap();
906
907        let float = container.create_float_param_def("Float", "origin").unwrap();
908        float.set_default_value(Some(1.23)).unwrap();
909        assert_eq!(float.default_value(), Some(1.23));
910        float.set_min(Some(0.0)).unwrap();
911        assert_eq!(float.min(), Some(0.0));
912        float.set_max(Some(2.0)).unwrap();
913        assert_eq!(float.max(), Some(2.0));
914    }
915
916    #[test]
917    fn integer_parameters() {
918        let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::Autosar_00048);
919        let pkg = model.get_or_create_package("/test").unwrap();
920        let ecuc_module = pkg.create_ecuc_module_def("EcucModule").unwrap();
921        let container = ecuc_module.create_param_conf_container_def("Container").unwrap();
922
923        let integer = container.create_integer_param_def("Integer", "origin").unwrap();
924        integer.set_default_value(Some(123)).unwrap();
925        assert_eq!(integer.default_value(), Some(123));
926        integer.set_min(Some(0)).unwrap();
927        assert_eq!(integer.min(), Some(0));
928        integer.set_max(Some(200)).unwrap();
929        assert_eq!(integer.max(), Some(200));
930    }
931}