svd_rs/
enumeratedvalues.rs

1use super::{EmptyToNone, EnumeratedValue, SvdError, Usage, ValidateLevel};
2
3/// A map describing unsigned integers and their description and name.
4#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
5#[derive(Clone, Debug, PartialEq, Eq)]
6#[non_exhaustive]
7pub struct EnumeratedValues {
8    /// Identifier for the whole enumeration section
9    #[cfg_attr(
10        feature = "serde",
11        serde(default, skip_serializing_if = "Option::is_none")
12    )]
13    pub name: Option<String>,
14
15    /// Usage of the values
16    #[cfg_attr(
17        feature = "serde",
18        serde(default, skip_serializing_if = "Option::is_none")
19    )]
20    pub usage: Option<Usage>,
21
22    /// Makes a copy from a previously defined enumeratedValues section.
23    /// No modifications are allowed
24    #[cfg_attr(
25        feature = "serde",
26        serde(default, skip_serializing_if = "Option::is_none")
27    )]
28    pub derived_from: Option<String>,
29
30    /// List of variants. The number of required items depends on the bit-width of the associated field.
31    #[cfg_attr(
32        feature = "serde",
33        serde(default, skip_serializing_if = "Vec::is_empty")
34    )]
35    pub values: Vec<EnumeratedValue>,
36}
37
38/// Errors for [`EnumeratedValues::validate`]
39#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
40pub enum Error {
41    /// Enum is empty
42    #[error("EnumeratedValues is empty")]
43    Empty,
44}
45
46/// Builder for [`EnumeratedValues`]
47#[derive(Clone, Debug, Default, PartialEq, Eq)]
48pub struct EnumeratedValuesBuilder {
49    name: Option<String>,
50    usage: Option<Usage>,
51    derived_from: Option<String>,
52    values: Option<Vec<EnumeratedValue>>,
53}
54
55impl From<EnumeratedValues> for EnumeratedValuesBuilder {
56    fn from(e: EnumeratedValues) -> Self {
57        Self {
58            name: e.name,
59            usage: e.usage,
60            derived_from: e.derived_from,
61            values: Some(e.values),
62        }
63    }
64}
65
66impl EnumeratedValuesBuilder {
67    /// Set the name of the enumerated values
68    pub fn name(mut self, value: Option<String>) -> Self {
69        self.name = value;
70        self
71    }
72    /// Set the usage of the enumerated values
73    pub fn usage(mut self, value: Option<Usage>) -> Self {
74        self.usage = value;
75        self
76    }
77    /// Set the derived_from attribute for the enumerated values
78    pub fn derived_from(mut self, value: Option<String>) -> Self {
79        self.derived_from = value;
80        self
81    }
82    /// Set the values
83    pub fn values(mut self, value: Vec<EnumeratedValue>) -> Self {
84        self.values = Some(value);
85        self
86    }
87    /// Validate and build a [`EnumeratedValues`].
88    pub fn build(self, lvl: ValidateLevel) -> Result<EnumeratedValues, SvdError> {
89        let evs = EnumeratedValues {
90            name: self.name.empty_to_none(),
91            usage: self.usage,
92            derived_from: self.derived_from,
93            values: self.values.unwrap_or_default(),
94        };
95        evs.validate(lvl)?;
96        Ok(evs)
97    }
98}
99
100impl EnumeratedValues {
101    /// Return default value if present
102    pub fn default_value(&self) -> Option<&EnumeratedValue> {
103        self.values.iter().find(|&v| v.is_default())
104    }
105
106    /// Make a builder for [`EnumeratedValues`]
107    pub fn builder() -> EnumeratedValuesBuilder {
108        EnumeratedValuesBuilder::default()
109    }
110    /// Modify an existing [`EnumeratedValues`] based on a [builder](EnumeratedValuesBuilder).
111    pub fn modify_from(
112        &mut self,
113        builder: EnumeratedValuesBuilder,
114        lvl: ValidateLevel,
115    ) -> Result<(), SvdError> {
116        if builder.derived_from.is_some() {
117            self.name = None;
118            self.usage = None;
119            self.values = Vec::new();
120        } else {
121            if builder.name.is_some() {
122                self.name = builder.name.empty_to_none();
123            }
124            if builder.usage.is_some() {
125                self.usage = builder.usage;
126            }
127            if let Some(values) = builder.values {
128                self.values = values;
129            }
130        }
131        self.validate(lvl)
132    }
133    /// Validate the [`EnumeratedValues`]
134    pub fn validate(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
135        if !lvl.is_disabled() {
136            if lvl.is_strict() {
137                if let Some(name) = self.name.as_ref() {
138                    super::check_name(name, "name")?;
139                }
140            }
141            if let Some(_dname) = self.derived_from.as_ref() {
142                if lvl.is_strict() {
143                    super::check_derived_name(_dname, "derivedFrom")?;
144                }
145                Ok(())
146            } else if self.values.is_empty() {
147                Err(Error::Empty.into())
148            } else {
149                Ok(())
150            }
151        } else {
152            Ok(())
153        }
154    }
155    /// Validate the [`EnumeratedValues`] recursively.
156    pub fn validate_all(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
157        for ev in &self.values {
158            ev.validate(lvl)?;
159        }
160        self.validate(lvl)
161    }
162    pub(crate) fn check_range(&self, range: core::ops::Range<u64>) -> Result<(), SvdError> {
163        for v in self.values.iter() {
164            v.check_range(&range)?;
165        }
166        Ok(())
167    }
168    /// Get the usage of these enumerated values.
169    pub fn usage(&self) -> Option<Usage> {
170        if self.derived_from.is_some() {
171            None
172        } else {
173            Some(self.usage.unwrap_or_default())
174        }
175    }
176
177    /// Get `enumeratedValue` by name
178    pub fn get_value(&self, name: &str) -> Option<&EnumeratedValue> {
179        self.values.iter().find(|e| e.name == name)
180    }
181
182    /// Get mutable `enumeratedValue` by name
183    pub fn get_mut_value(&mut self, name: &str) -> Option<&mut EnumeratedValue> {
184        self.values.iter_mut().find(|e| e.name == name)
185    }
186}