svd_rs/
field.rs

1use super::{
2    array::{descriptions, names},
3    bitrange, Access, BitRange, BuildError, Description, DimElement, EmptyToNone, EnumeratedValues,
4    MaybeArray, ModifiedWriteValues, Name, ReadAction, SvdError, Usage, ValidateLevel,
5    WriteConstraint,
6};
7use std::ops::Deref;
8
9/// Describes a field or fields of a [register](crate::RegisterInfo).
10pub type Field = MaybeArray<FieldInfo>;
11
12/// Errors for [`FieldInfo::validate`]
13#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
14pub enum Error {
15    /// The enumerated value is not recognized by svd-rs.
16    #[error("You can have 0, 1 or 2 enumeratedValues with different usage")]
17    IncompatibleEnumeratedValues,
18}
19
20/// A partition of a [register](crate::RegisterInfo)
21#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
22#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
23#[derive(Clone, Debug, PartialEq, Eq)]
24#[non_exhaustive]
25pub struct FieldInfo {
26    /// Name string used to identify the field.
27    /// Field names must be unique within a register
28    pub name: String,
29
30    /// String describing the details of the register
31    #[cfg_attr(
32        feature = "serde",
33        serde(default, skip_serializing_if = "Option::is_none")
34    )]
35    pub description: Option<String>,
36
37    /// Bit position of the field within the register
38    #[cfg_attr(feature = "serde", serde(flatten))]
39    pub bit_range: BitRange,
40
41    /// Predefined strings set the access type.
42    /// The element can be omitted if access rights get inherited from parent elements
43    #[cfg_attr(
44        feature = "serde",
45        serde(default, skip_serializing_if = "Option::is_none")
46    )]
47    pub access: Option<Access>,
48
49    /// Describe the manipulation of data written to a field.
50    #[cfg_attr(
51        feature = "serde",
52        serde(default, skip_serializing_if = "Option::is_none")
53    )]
54    pub modified_write_values: Option<ModifiedWriteValues>,
55
56    /// Specifies the subset of allowed write values
57    #[cfg_attr(
58        feature = "serde",
59        serde(default, skip_serializing_if = "Option::is_none")
60    )]
61    pub write_constraint: Option<WriteConstraint>,
62
63    /// If set, it specifies the side effect following a read operation.
64    /// If not set, the field is not modified
65    #[cfg_attr(
66        feature = "serde",
67        serde(default, skip_serializing_if = "Option::is_none")
68    )]
69    pub read_action: Option<ReadAction>,
70
71    /// Describes the field
72    #[cfg_attr(
73        feature = "serde",
74        serde(default, skip_serializing_if = "Vec::is_empty")
75    )]
76    pub enumerated_values: Vec<EnumeratedValues>,
77
78    /// Specify the field name from which to inherit data.
79    /// Elements specified subsequently override inherited values
80    #[cfg_attr(
81        feature = "serde",
82        serde(default, skip_serializing_if = "Option::is_none")
83    )]
84    pub derived_from: Option<String>,
85}
86
87/// Return iterator over bit offsets of each field in array
88pub fn bit_offsets<'a>(info: &'a FieldInfo, dim: &'a DimElement) -> impl Iterator<Item = u32> + 'a {
89    (0..dim.dim).map(|i| info.bit_offset() + i * dim.dim_increment)
90}
91
92/// Extract `FieldInfo` items from array
93pub fn expand<'a>(
94    info: &'a FieldInfo,
95    dim: &'a DimElement,
96) -> impl Iterator<Item = FieldInfo> + 'a {
97    names(info, dim)
98        .zip(descriptions(info, dim))
99        .zip(bit_offsets(info, dim))
100        .map(|((name, description), bit_offset)| {
101            let mut info = info.clone();
102            info.name = name;
103            info.description = description;
104            info.bit_range = BitRange::from_offset_width(bit_offset, info.bit_width());
105            info
106        })
107}
108
109/// Builder for [`FieldInfo`]
110
111#[derive(Clone, Debug, Default, PartialEq, Eq)]
112pub struct FieldInfoBuilder {
113    name: Option<String>,
114    description: Option<String>,
115    bit_range: Option<BitRange>,
116    bit_offset: Option<u32>,
117    bit_width: Option<u32>,
118    access: Option<Access>,
119    modified_write_values: Option<ModifiedWriteValues>,
120    write_constraint: Option<WriteConstraint>,
121    read_action: Option<ReadAction>,
122    enumerated_values: Option<Vec<EnumeratedValues>>,
123    derived_from: Option<String>,
124}
125
126impl From<FieldInfo> for FieldInfoBuilder {
127    fn from(f: FieldInfo) -> Self {
128        Self {
129            name: Some(f.name),
130            description: f.description,
131            bit_range: Some(f.bit_range),
132            bit_offset: None,
133            bit_width: None,
134            access: f.access,
135            modified_write_values: f.modified_write_values,
136            write_constraint: f.write_constraint,
137            read_action: f.read_action,
138            enumerated_values: Some(f.enumerated_values),
139            derived_from: f.derived_from,
140        }
141    }
142}
143
144impl FieldInfoBuilder {
145    /// Set the name of the field
146    pub fn name(mut self, value: String) -> Self {
147        self.name = Some(value);
148        self
149    }
150    /// Set the description of the field
151    pub fn description(mut self, value: Option<String>) -> Self {
152        self.description = value;
153        self
154    }
155    /// Set the bit range of the field
156    pub fn bit_range(mut self, value: BitRange) -> Self {
157        self.bit_range = Some(value);
158        self.bit_offset = None;
159        self.bit_width = None;
160        self
161    }
162    /// Set the bit offset of the field
163    pub fn bit_offset(mut self, value: u32) -> Self {
164        if let Some(bit_range) = self.bit_range.as_mut() {
165            bit_range.offset = value;
166        } else if let Some(width) = self.bit_offset {
167            self.bit_range = Some(BitRange::from_offset_width(value, width));
168            self.bit_width = None;
169        } else {
170            self.bit_offset = Some(value);
171        }
172        self
173    }
174    /// Set the bit width of the field
175    pub fn bit_width(mut self, value: u32) -> Self {
176        if let Some(bit_range) = self.bit_range.as_mut() {
177            bit_range.width = value;
178        } else if let Some(offset) = self.bit_offset {
179            self.bit_range = Some(BitRange::from_offset_width(offset, value));
180            self.bit_offset = None;
181        } else {
182            self.bit_width = Some(value);
183        }
184        self
185    }
186    /// Set the access of the field
187    pub fn access(mut self, value: Option<Access>) -> Self {
188        self.access = value;
189        self
190    }
191    /// Set the modified write values of the field
192    pub fn modified_write_values(mut self, value: Option<ModifiedWriteValues>) -> Self {
193        self.modified_write_values = value;
194        self
195    }
196    /// Set the write constraint of the field
197    pub fn write_constraint(mut self, value: Option<WriteConstraint>) -> Self {
198        self.write_constraint = value;
199        self
200    }
201    /// Set the read action of the register.
202    pub fn read_action(mut self, value: Option<ReadAction>) -> Self {
203        self.read_action = value;
204        self
205    }
206    /// Set the enumerated values of the field
207    pub fn enumerated_values(mut self, value: Vec<EnumeratedValues>) -> Self {
208        self.enumerated_values = Some(value);
209        self
210    }
211    /// Set the derived_from attribute of the field
212    pub fn derived_from(mut self, value: Option<String>) -> Self {
213        self.derived_from = value;
214        self
215    }
216    /// Validate and build a [`FieldInfo`].
217    pub fn build(self, lvl: ValidateLevel) -> Result<FieldInfo, SvdError> {
218        let field = FieldInfo {
219            name: self
220                .name
221                .ok_or_else(|| BuildError::Uninitialized("name".to_string()))?,
222            description: self.description.empty_to_none(),
223            bit_range: self
224                .bit_range
225                .ok_or_else(|| BuildError::Uninitialized("bit_range".to_string()))?,
226            access: self.access,
227            modified_write_values: self.modified_write_values,
228            write_constraint: self.write_constraint,
229            read_action: self.read_action,
230            enumerated_values: self.enumerated_values.unwrap_or_default(),
231            derived_from: self.derived_from,
232        };
233        field.validate(lvl)?;
234        Ok(field)
235    }
236}
237
238impl FieldInfo {
239    /// Make a builder for [`FieldInfo`]
240    pub fn builder() -> FieldInfoBuilder {
241        FieldInfoBuilder::default()
242    }
243    /// Construct single [`Field`]
244    pub const fn single(self) -> Field {
245        Field::Single(self)
246    }
247    /// Construct [`Field`] array
248    pub const fn array(self, dim: DimElement) -> Field {
249        Field::Array(self, dim)
250    }
251    /// Construct single [`Field`] or array
252    pub fn maybe_array(self, dim: Option<DimElement>) -> Field {
253        if let Some(dim) = dim {
254            self.array(dim)
255        } else {
256            self.single()
257        }
258    }
259    /// Modify an existing [`FieldInfo`] based on a [builder](FieldInfoBuilder).
260    pub fn modify_from(
261        &mut self,
262        builder: FieldInfoBuilder,
263        lvl: ValidateLevel,
264    ) -> Result<(), SvdError> {
265        if let Some(name) = builder.name {
266            self.name = name;
267        }
268        if builder.description.is_some() {
269            self.description = builder.description.empty_to_none();
270        }
271        if let Some(bit_range) = builder.bit_range {
272            self.bit_range = bit_range;
273        }
274        if let Some(offset) = builder.bit_offset {
275            self.bit_range.offset = offset;
276        }
277        if let Some(width) = builder.bit_width {
278            self.bit_range.width = width;
279        }
280        if builder.access.is_some() {
281            self.access = builder.access;
282        }
283        if builder.derived_from.is_some() {
284            self.derived_from = builder.derived_from;
285            self.modified_write_values = None;
286            self.write_constraint = None;
287            self.enumerated_values = Vec::new();
288        } else {
289            if builder.modified_write_values.is_some() {
290                self.modified_write_values = builder.modified_write_values;
291            }
292            if builder.write_constraint.is_some() {
293                self.write_constraint = builder.write_constraint;
294            }
295            if builder.read_action.is_some() {
296                self.read_action = builder.read_action;
297            }
298            if let Some(enumerated_values) = builder.enumerated_values {
299                self.enumerated_values = enumerated_values;
300            }
301        }
302        self.validate(lvl)
303    }
304    /// Validate the [`FieldInfo`].
305    pub fn validate(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
306        if !lvl.is_disabled() {
307            if lvl.is_strict() {
308                super::check_dimable_name(&self.name, "name")?;
309                if let Some(name) = self.derived_from.as_ref() {
310                    super::check_derived_name(name, "derivedFrom")?;
311                }
312            }
313
314            if self.bit_range.width == 0 {
315                return Err(bitrange::Error::ZeroWidth.into());
316            }
317
318            // If the bit_range has its maximum width, all enumerated values will of
319            // course fit in so we can skip validation.
320            if self.bit_range.width < 64 {
321                for ev in &self.enumerated_values {
322                    ev.check_range(0..2_u64.pow(self.bit_range.width))?;
323                }
324            }
325
326            if lvl.is_strict() {
327                match self.enumerated_values.as_slice() {
328                    [] | [_] => {}
329                    [ev1, ev2]
330                        if matches!(ev1.usage(), None | Some(Usage::Read))
331                            && matches!(ev2.usage(), None | Some(Usage::Write)) => {}
332                    [ev1, ev2]
333                        if matches!(ev2.usage(), None | Some(Usage::Read))
334                            && matches!(ev1.usage(), None | Some(Usage::Write)) => {}
335                    _ => return Err(Error::IncompatibleEnumeratedValues.into()),
336                }
337            }
338
339            match self.write_constraint {
340                // If the bit_range has its maximum width, all values will of
341                // course fit in so we can skip validation.
342                Some(WriteConstraint::Range(constraint)) if self.bit_range.width < 64 => {
343                    constraint.check_range(0..2_u64.pow(self.bit_range.width))?;
344                }
345                _ => (),
346            }
347        }
348
349        Ok(())
350    }
351    /// Validate the [`FieldInfo`] recursively
352    pub fn validate_all(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
353        for evs in &self.enumerated_values {
354            evs.validate_all(lvl)?;
355        }
356        self.validate(lvl)
357    }
358
359    /// Get bit offset
360    pub fn bit_offset(&self) -> u32 {
361        self.bit_range.offset
362    }
363
364    /// Get bit width
365    pub fn bit_width(&self) -> u32 {
366        self.bit_range.width
367    }
368
369    /// Get the position of the least significant bit
370    pub fn lsb(&self) -> u32 {
371        self.bit_range.lsb()
372    }
373    /// Get the position of the most significant bit
374    pub fn msb(&self) -> u32 {
375        self.bit_range.msb()
376    }
377
378    /// Get bits which is affected by field
379    pub fn bitmask(&self) -> u64 {
380        let BitRange { offset, width, .. } = self.bit_range;
381        (!0u64 >> (64 - width)) << offset
382    }
383
384    /// Get enumeratedValues cluster by usage
385    pub fn get_enumerated_values(&self, usage: Usage) -> Option<&EnumeratedValues> {
386        match self.enumerated_values.len() {
387            1 | 2 => self
388                .enumerated_values
389                .iter()
390                .find(|ev| ev.usage() == Some(usage)),
391            _ => None,
392        }
393    }
394
395    /// Get mutable enumeratedValues by usage
396    pub fn get_mut_enumerated_values(&mut self, usage: Usage) -> Option<&mut EnumeratedValues> {
397        match self.enumerated_values.len() {
398            1 | 2 => self
399                .enumerated_values
400                .iter_mut()
401                .find(|ev| ev.usage() == Some(usage)),
402            _ => None,
403        }
404    }
405}
406
407impl Field {
408    /// Validate the [`Field`] recursively
409    pub fn validate_all(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
410        if let Self::Array(_, dim) = self {
411            dim.validate(lvl)?;
412        }
413        self.deref().validate_all(lvl)
414    }
415
416    /// Get bits which is affected by field or field array
417    pub fn bitmask(&self) -> u64 {
418        match self {
419            Field::Single(f) => f.bitmask(),
420            Field::Array(f, d) => {
421                let mask = f.bitmask();
422                let mut bits = 0;
423                for i in 0..d.dim {
424                    bits |= mask << (i * d.dim_increment);
425                }
426                bits
427            }
428        }
429    }
430}
431
432impl Name for FieldInfo {
433    fn name(&self) -> &str {
434        &self.name
435    }
436}
437
438impl Description for FieldInfo {
439    fn description(&self) -> Option<&str> {
440        self.description.as_deref()
441    }
442}