svd_rs/
cluster.rs

1use super::{
2    array::{descriptions, names},
3    registercluster::{
4        AllRegistersIter, AllRegistersIterMut, ClusterIter, ClusterIterMut, RegisterIter,
5        RegisterIterMut,
6    },
7    BuildError, Description, DimElement, EmptyToNone, MaybeArray, Name, Register, RegisterCluster,
8    RegisterProperties, SvdError, ValidateLevel,
9};
10use std::ops::Deref;
11
12/// Cluster describes a sequence of neighboring registers within a peripheral.
13pub type Cluster = MaybeArray<ClusterInfo>;
14
15/// Errors from [`ClusterInfo::validate`]
16#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
17pub enum Error {
18    /// The cluster can not be empty
19    #[error("Cluster must contain at least one Register or Cluster")]
20    EmptyCluster,
21}
22
23/// Description of a cluster
24#[cfg_attr(
25    feature = "serde",
26    derive(serde::Deserialize, serde::Serialize),
27    serde(rename_all = "camelCase")
28)]
29#[derive(Clone, Debug, PartialEq)]
30#[non_exhaustive]
31pub struct ClusterInfo {
32    /// String to identify the cluster.
33    /// Cluster names are required to be unique within the scope of a peripheral
34    pub name: String,
35
36    /// String describing the details of the register cluster
37    #[cfg_attr(
38        feature = "serde",
39        serde(default, skip_serializing_if = "Option::is_none")
40    )]
41    pub description: Option<String>,
42
43    /// Specify the name of the original cluster if this cluster provides an alternative description
44    #[cfg_attr(
45        feature = "serde",
46        serde(default, skip_serializing_if = "Option::is_none")
47    )]
48    pub alternate_cluster: Option<String>,
49
50    /// Specify the struct type name created in the device header file
51    #[cfg_attr(
52        feature = "serde",
53        serde(default, skip_serializing_if = "Option::is_none")
54    )]
55    pub header_struct_name: Option<String>,
56
57    /// Cluster address relative to the `baseAddress` of the peripheral
58    pub address_offset: u32,
59
60    /// Default properties for all registers
61    #[cfg_attr(feature = "serde", serde(flatten))]
62    pub default_register_properties: RegisterProperties,
63
64    /// Children/members of the cluster
65    pub children: Vec<RegisterCluster>,
66
67    /// Specify the cluster name from which to inherit data.
68    /// Elements specified subsequently override inherited values
69    #[cfg_attr(
70        feature = "serde",
71        serde(default, skip_serializing_if = "Option::is_none")
72    )]
73    pub derived_from: Option<String>,
74}
75
76/// Return iterator over address offsets of each cluster in array
77pub fn address_offsets<'a>(
78    info: &'a ClusterInfo,
79    dim: &'a DimElement,
80) -> impl Iterator<Item = u32> + 'a {
81    (0..dim.dim).map(move |i| info.address_offset + i * dim.dim_increment)
82}
83
84/// Extract `ClusterInfo` items from array
85pub fn expand<'a>(
86    info: &'a ClusterInfo,
87    dim: &'a DimElement,
88) -> impl Iterator<Item = ClusterInfo> + 'a {
89    names(info, dim)
90        .zip(descriptions(info, dim))
91        .zip(address_offsets(info, dim))
92        .map(|((name, description), address_offset)| {
93            let mut info = info.clone();
94            info.name = name;
95            info.description = description;
96            info.address_offset = address_offset;
97            info
98        })
99}
100
101/// Builder for [`ClusterInfo`]
102#[derive(Clone, Debug, Default, PartialEq)]
103pub struct ClusterInfoBuilder {
104    name: Option<String>,
105    description: Option<String>,
106    alternate_cluster: Option<String>,
107    header_struct_name: Option<String>,
108    address_offset: Option<u32>,
109    default_register_properties: RegisterProperties,
110    children: Option<Vec<RegisterCluster>>,
111    derived_from: Option<String>,
112}
113
114impl From<ClusterInfo> for ClusterInfoBuilder {
115    fn from(c: ClusterInfo) -> Self {
116        Self {
117            name: Some(c.name),
118            description: c.description,
119            alternate_cluster: c.alternate_cluster,
120            header_struct_name: c.header_struct_name,
121            address_offset: Some(c.address_offset),
122            default_register_properties: c.default_register_properties,
123            children: Some(c.children),
124            derived_from: c.derived_from,
125        }
126    }
127}
128
129impl ClusterInfoBuilder {
130    /// Set the name of the cluster.
131    pub fn name(mut self, value: String) -> Self {
132        self.name = Some(value);
133        self
134    }
135    /// Set the description of the cluster.
136    pub fn description(mut self, value: Option<String>) -> Self {
137        self.description = value;
138        self
139    }
140    /// Set the alternate cluster.
141    pub fn alternate_cluster(mut self, value: Option<String>) -> Self {
142        self.alternate_cluster = value;
143        self
144    }
145    /// Set the struct type name of the cluster. If not specified, the name of the cluster should be used.
146    pub fn header_struct_name(mut self, value: Option<String>) -> Self {
147        self.header_struct_name = value;
148        self
149    }
150    /// Set the address_offset of the cluster, relative to the [`baseAddress`](crate::Peripheral::base_address) of the peripheral.
151    pub fn address_offset(mut self, value: u32) -> Self {
152        self.address_offset = Some(value);
153        self
154    }
155    /// Set the default_register_properties of the cluster.
156    pub fn default_register_properties(mut self, value: RegisterProperties) -> Self {
157        self.default_register_properties = value;
158        self
159    }
160    /// Set the children of the cluster.
161    pub fn children(mut self, value: Vec<RegisterCluster>) -> Self {
162        self.children = Some(value);
163        self
164    }
165    /// Set the derived_from of the cluster.
166    pub fn derived_from(mut self, value: Option<String>) -> Self {
167        self.derived_from = value;
168        self
169    }
170    /// Validate and build a [`ClusterInfo`].
171    pub fn build(self, lvl: ValidateLevel) -> Result<ClusterInfo, SvdError> {
172        let cluster = ClusterInfo {
173            name: self
174                .name
175                .ok_or_else(|| BuildError::Uninitialized("name".to_string()))?,
176            description: self.description.empty_to_none(),
177            alternate_cluster: self.alternate_cluster.empty_to_none(),
178            header_struct_name: self.header_struct_name.empty_to_none(),
179            address_offset: self
180                .address_offset
181                .ok_or_else(|| BuildError::Uninitialized("address_offset".to_string()))?,
182            default_register_properties: self.default_register_properties.build(lvl)?,
183            children: self
184                .children
185                .ok_or_else(|| BuildError::Uninitialized("children".to_string()))?,
186            derived_from: self.derived_from,
187        };
188        cluster.validate(lvl)?;
189        Ok(cluster)
190    }
191}
192
193impl ClusterInfo {
194    /// Make a builder for [`ClusterInfo`]
195    pub fn builder() -> ClusterInfoBuilder {
196        ClusterInfoBuilder::default()
197    }
198    /// Construct single [`Cluster`]
199    pub const fn single(self) -> Cluster {
200        Cluster::Single(self)
201    }
202    /// Construct [`Cluster`] array
203    pub const fn array(self, dim: DimElement) -> Cluster {
204        Cluster::Array(self, dim)
205    }
206    /// Construct single [`Cluster`] or array
207    pub fn maybe_array(self, dim: Option<DimElement>) -> Cluster {
208        if let Some(dim) = dim {
209            self.array(dim)
210        } else {
211            self.single()
212        }
213    }
214    /// Modify an existing [`ClusterInfo`] based on a [builder](ClusterInfoBuilder).
215    pub fn modify_from(
216        &mut self,
217        builder: ClusterInfoBuilder,
218        lvl: ValidateLevel,
219    ) -> Result<(), SvdError> {
220        if let Some(name) = builder.name {
221            self.name = name;
222        }
223        if builder.description.is_some() {
224            self.description = builder.description.empty_to_none();
225        }
226        if builder.alternate_cluster.is_some() {
227            self.alternate_cluster = builder.alternate_cluster.empty_to_none();
228        }
229        if builder.header_struct_name.is_some() {
230            self.header_struct_name = builder.header_struct_name.empty_to_none();
231        }
232        if let Some(address_offset) = builder.address_offset {
233            self.address_offset = address_offset;
234        }
235        if builder.derived_from.is_some() {
236            self.derived_from = builder.derived_from;
237            self.children = Vec::new();
238            self.default_register_properties = RegisterProperties::default();
239        } else {
240            self.default_register_properties
241                .modify_from(builder.default_register_properties, lvl)?;
242            if let Some(children) = builder.children {
243                self.children = children;
244            }
245        }
246        self.validate(lvl)
247    }
248
249    /// Validate the [`ClusterInfo`]
250    pub fn validate(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
251        if !lvl.is_disabled() {
252            if lvl.is_strict() {
253                super::check_dimable_name(&self.name, "name")?;
254            }
255            if let Some(name) = self.derived_from.as_ref() {
256                if lvl.is_strict() {
257                    super::check_derived_name(name, "derivedFrom")?;
258                }
259            } else if self.children.is_empty() && lvl.is_strict() {
260                return Err(Error::EmptyCluster.into());
261            }
262        }
263        Ok(())
264    }
265    /// Validate the [`ClusterInfo`] recursively
266    pub fn validate_all(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
267        self.default_register_properties.validate(lvl)?;
268        for r in self.registers() {
269            r.validate_all(lvl)?;
270        }
271        for c in self.clusters() {
272            c.validate_all(lvl)?;
273        }
274        self.validate(lvl)
275    }
276
277    /// Returns iterator over all descendant registers
278    #[deprecated(since = "0.12.1", note = "Please use `all_registers` instead")]
279    pub fn reg_iter(&self) -> AllRegistersIter {
280        self.all_registers()
281    }
282
283    /// Returns iterator over all descendant registers
284    pub fn all_registers(&self) -> AllRegistersIter {
285        AllRegistersIter {
286            rem: self.children.iter().rev().collect(),
287        }
288    }
289
290    /// Returns mutable iterator over all descendant registers
291    #[deprecated(since = "0.12.1", note = "Please use `all_registers_mut` instead")]
292    pub fn reg_iter_mut(&mut self) -> AllRegistersIterMut {
293        self.all_registers_mut()
294    }
295
296    /// Returns mutable iterator over all descendant registers
297    pub fn all_registers_mut(&mut self) -> AllRegistersIterMut {
298        AllRegistersIterMut {
299            rem: self.children.iter_mut().rev().collect(),
300        }
301    }
302
303    /// Returns iterator over child registers
304    pub fn registers(&self) -> RegisterIter {
305        RegisterIter {
306            all: self.children.iter(),
307        }
308    }
309
310    /// Returns mutable iterator over child registers
311    pub fn registers_mut(&mut self) -> RegisterIterMut {
312        RegisterIterMut {
313            all: self.children.iter_mut(),
314        }
315    }
316
317    /// Returns iterator over child clusters
318    pub fn clusters(&self) -> ClusterIter {
319        ClusterIter {
320            all: self.children.iter(),
321        }
322    }
323
324    /// Returns mutable iterator over child clusters
325    pub fn clusters_mut(&mut self) -> ClusterIterMut {
326        ClusterIterMut {
327            all: self.children.iter_mut(),
328        }
329    }
330
331    /// Get register by name
332    pub fn get_register(&self, name: &str) -> Option<&Register> {
333        self.registers().find(|f| f.name == name)
334    }
335
336    /// Get mutable register by name
337    pub fn get_mut_register(&mut self, name: &str) -> Option<&mut Register> {
338        self.registers_mut().find(|f| f.name == name)
339    }
340
341    /// Get cluster by name
342    pub fn get_cluster(&self, name: &str) -> Option<&Cluster> {
343        self.clusters().find(|f| f.name == name)
344    }
345
346    /// Get mutable cluster by name
347    pub fn get_mut_cluster(&mut self, name: &str) -> Option<&mut Cluster> {
348        self.clusters_mut().find(|f| f.name == name)
349    }
350}
351
352impl Cluster {
353    /// Validate the [`Cluster`] recursively
354    pub fn validate_all(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
355        if let Self::Array(_, dim) = self {
356            dim.validate(lvl)?;
357        }
358        self.deref().validate_all(lvl)
359    }
360}
361
362impl Name for ClusterInfo {
363    fn name(&self) -> &str {
364        &self.name
365    }
366}
367
368impl Description for ClusterInfo {
369    fn description(&self) -> Option<&str> {
370        self.description.as_deref()
371    }
372}