1use super::{
2    array::{descriptions, names},
3    registercluster::{
4        AllRegistersIter, AllRegistersIterMut, ClusterIter, ClusterIterMut, RegisterIter,
5        RegisterIterMut,
6    },
7    AddressBlock, BuildError, Cluster, Description, DimElement, EmptyToNone, Interrupt, MaybeArray,
8    Name, Register, RegisterCluster, RegisterProperties, SvdError, ValidateLevel,
9};
10use std::ops::Deref;
11
12pub type Peripheral = MaybeArray<PeripheralInfo>;
14
15#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
17pub enum Error {
18    #[error("Peripheral have `registers` tag, but it is empty")]
20    EmptyRegisters,
21}
22
23#[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 PeripheralInfo {
32    pub name: String,
34
35    #[cfg_attr(
37        feature = "serde",
38        serde(default, skip_serializing_if = "Option::is_none")
39    )]
40    pub display_name: Option<String>,
41
42    #[cfg_attr(
44        feature = "serde",
45        serde(default, skip_serializing_if = "Option::is_none")
46    )]
47    pub version: Option<String>,
48
49    #[cfg_attr(
51        feature = "serde",
52        serde(default, skip_serializing_if = "Option::is_none")
53    )]
54    pub description: Option<String>,
55
56    #[cfg_attr(
58        feature = "serde",
59        serde(default, skip_serializing_if = "Option::is_none")
60    )]
61    pub alternate_peripheral: Option<String>,
62
63    #[cfg_attr(
65        feature = "serde",
66        serde(default, skip_serializing_if = "Option::is_none")
67    )]
68    pub group_name: Option<String>,
69
70    #[cfg_attr(
72        feature = "serde",
73        serde(default, skip_serializing_if = "Option::is_none")
74    )]
75    pub prepend_to_name: Option<String>,
76
77    #[cfg_attr(
79        feature = "serde",
80        serde(default, skip_serializing_if = "Option::is_none")
81    )]
82    pub append_to_name: Option<String>,
83
84    #[cfg_attr(
86        feature = "serde",
87        serde(default, skip_serializing_if = "Option::is_none")
88    )]
89    pub header_struct_name: Option<String>,
90
91    pub base_address: u64,
93
94    #[cfg_attr(feature = "serde", serde(flatten))]
96    pub default_register_properties: RegisterProperties,
97
98    #[cfg_attr(
100        feature = "serde",
101        serde(default, skip_serializing_if = "Option::is_none")
102    )]
103    pub address_block: Option<Vec<AddressBlock>>,
104
105    #[cfg_attr(
107        feature = "serde",
108        serde(default, skip_serializing_if = "Vec::is_empty")
109    )]
110    pub interrupt: Vec<Interrupt>,
111
112    #[cfg_attr(
115        feature = "serde",
116        serde(default, skip_serializing_if = "Option::is_none")
117    )]
118    pub registers: Option<Vec<RegisterCluster>>,
119
120    #[cfg_attr(
122        feature = "serde",
123        serde(default, skip_serializing_if = "Option::is_none")
124    )]
125    pub derived_from: Option<String>,
126}
127
128pub fn base_addresses<'a>(
130    info: &'a PeripheralInfo,
131    dim: &'a DimElement,
132) -> impl Iterator<Item = u64> + 'a {
133    (0..dim.dim as u64).map(|i| info.base_address + i * dim.dim_increment as u64)
134}
135
136pub fn expand<'a>(
138    info: &'a PeripheralInfo,
139    dim: &'a DimElement,
140) -> impl Iterator<Item = PeripheralInfo> + 'a {
141    dim.indexes()
142        .zip(names(info, dim))
143        .zip(descriptions(info, dim))
144        .zip(base_addresses(info, dim))
145        .map(|(((idx, name), description), base_address)| {
146            let mut info = info.clone();
147            info.name = name;
148            info.description = description;
149            info.base_address = base_address;
150            info.display_name = info
151                .display_name
152                .map(|d| d.replace("[%s]", &idx).replace("%s", &idx));
153            info
154        })
155}
156
157#[derive(Clone, Debug, Default, PartialEq)]
159pub struct PeripheralInfoBuilder {
160    name: Option<String>,
161    display_name: Option<String>,
162    version: Option<String>,
163    description: Option<String>,
164    alternate_peripheral: Option<String>,
165    group_name: Option<String>,
166    prepend_to_name: Option<String>,
167    append_to_name: Option<String>,
168    header_struct_name: Option<String>,
169    base_address: Option<u64>,
170    default_register_properties: RegisterProperties,
171    address_block: Option<Vec<AddressBlock>>,
172    interrupt: Option<Vec<Interrupt>>,
173    registers: Option<Vec<RegisterCluster>>,
174    derived_from: Option<String>,
175}
176
177impl From<PeripheralInfo> for PeripheralInfoBuilder {
178    fn from(p: PeripheralInfo) -> Self {
179        Self {
180            name: Some(p.name),
181            display_name: p.display_name,
182            version: p.version,
183            description: p.description,
184            alternate_peripheral: p.alternate_peripheral,
185            group_name: p.group_name,
186            prepend_to_name: p.prepend_to_name,
187            append_to_name: p.append_to_name,
188            header_struct_name: p.header_struct_name,
189            base_address: Some(p.base_address),
190            default_register_properties: p.default_register_properties,
191            address_block: p.address_block,
192            interrupt: Some(p.interrupt),
193            registers: p.registers,
194            derived_from: p.derived_from,
195        }
196    }
197}
198
199impl PeripheralInfoBuilder {
200    pub fn name(mut self, value: String) -> Self {
202        self.name = Some(value);
203        self
204    }
205    pub fn display_name(mut self, value: Option<String>) -> Self {
207        self.display_name = value;
208        self
209    }
210    pub fn version(mut self, value: Option<String>) -> Self {
212        self.version = value;
213        self
214    }
215    pub fn description(mut self, value: Option<String>) -> Self {
217        self.description = value;
218        self
219    }
220    pub fn alternate_peripheral(mut self, value: Option<String>) -> Self {
222        self.alternate_peripheral = value;
223        self
224    }
225    pub fn group_name(mut self, value: Option<String>) -> Self {
227        self.group_name = value;
228        self
229    }
230    pub fn prepend_to_name(mut self, value: Option<String>) -> Self {
232        self.prepend_to_name = value;
233        self
234    }
235    pub fn append_to_name(mut self, value: Option<String>) -> Self {
237        self.append_to_name = value;
238        self
239    }
240    pub fn header_struct_name(mut self, value: Option<String>) -> Self {
242        self.header_struct_name = value;
243        self
244    }
245    pub fn base_address(mut self, value: u64) -> Self {
247        self.base_address = Some(value);
248        self
249    }
250    pub fn default_register_properties(mut self, value: RegisterProperties) -> Self {
252        self.default_register_properties = value;
253        self
254    }
255    pub fn address_block(mut self, value: Option<Vec<AddressBlock>>) -> Self {
257        self.address_block = value;
258        self
259    }
260    pub fn interrupt(mut self, value: Option<Vec<Interrupt>>) -> Self {
262        self.interrupt = value;
263        self
264    }
265    pub fn registers(mut self, value: Option<Vec<RegisterCluster>>) -> Self {
267        self.registers = value;
268        self
269    }
270    pub fn derived_from(mut self, value: Option<String>) -> Self {
272        self.derived_from = value;
273        self
274    }
275    pub fn build(self, lvl: ValidateLevel) -> Result<PeripheralInfo, SvdError> {
277        let per = PeripheralInfo {
278            name: self
279                .name
280                .ok_or_else(|| BuildError::Uninitialized("name".to_string()))?,
281            display_name: self.display_name.empty_to_none(),
282            version: self.version.empty_to_none(),
283            description: self.description.empty_to_none(),
284            alternate_peripheral: self.alternate_peripheral.empty_to_none(),
285            group_name: self.group_name.empty_to_none(),
286            prepend_to_name: self.prepend_to_name.empty_to_none(),
287            append_to_name: self.append_to_name.empty_to_none(),
288            header_struct_name: self.header_struct_name.empty_to_none(),
289            base_address: self
290                .base_address
291                .ok_or_else(|| BuildError::Uninitialized("base_address".to_string()))?,
292            default_register_properties: self.default_register_properties.build(lvl)?,
293            address_block: self.address_block,
294            interrupt: self.interrupt.unwrap_or_default(),
295            registers: self.registers,
296            derived_from: self.derived_from,
297        };
298        per.validate(lvl)?;
299        Ok(per)
300    }
301}
302
303impl PeripheralInfo {
304    pub fn builder() -> PeripheralInfoBuilder {
306        PeripheralInfoBuilder::default()
307    }
308    pub const fn single(self) -> Peripheral {
310        Peripheral::Single(self)
311    }
312    pub const fn array(self, dim: DimElement) -> Peripheral {
314        Peripheral::Array(self, dim)
315    }
316    pub fn maybe_array(self, dim: Option<DimElement>) -> Peripheral {
318        if let Some(dim) = dim {
319            self.array(dim)
320        } else {
321            self.single()
322        }
323    }
324    pub fn modify_from(
326        &mut self,
327        builder: PeripheralInfoBuilder,
328        lvl: ValidateLevel,
329    ) -> Result<(), SvdError> {
330        if let Some(name) = builder.name {
331            self.name = name;
332        }
333        if builder.display_name.is_some() {
334            self.display_name = builder.display_name.empty_to_none();
335        }
336        if builder.version.is_some() {
337            self.version = builder.version.empty_to_none();
338        }
339        if builder.description.is_some() {
340            self.description = builder.description.empty_to_none();
341        }
342        if builder.alternate_peripheral.is_some() {
343            self.alternate_peripheral = builder.alternate_peripheral.empty_to_none();
344        }
345        if builder.group_name.is_some() {
346            self.group_name = builder.group_name.empty_to_none();
347        }
348        if builder.prepend_to_name.is_some() {
349            self.prepend_to_name = builder.prepend_to_name.empty_to_none();
350        }
351        if builder.append_to_name.is_some() {
352            self.append_to_name = builder.append_to_name.empty_to_none();
353        }
354        if builder.header_struct_name.is_some() {
355            self.header_struct_name = builder.header_struct_name.empty_to_none();
356        }
357        if let Some(base_address) = builder.base_address {
358            self.base_address = base_address;
359        }
360        if let Some(interrupt) = builder.interrupt {
361            self.interrupt = interrupt;
362        }
363        if builder.derived_from.is_some() {
364            self.derived_from = builder.derived_from;
365            self.registers = None;
366            self.address_block = None;
367            self.default_register_properties = RegisterProperties::default();
368        } else {
369            if builder.address_block.is_some() {
370                self.address_block = builder.address_block;
371            }
372            self.default_register_properties
373                .modify_from(builder.default_register_properties, lvl)?;
374            if builder.registers.is_some() {
375                self.registers = builder.registers.empty_to_none();
376            }
377        }
378        self.validate(lvl)
379    }
380
381    pub fn validate(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
383        if !lvl.is_disabled() {
384            if lvl.is_strict() {
386                super::check_dimable_name(&self.name, "name")?;
387            }
388            if let Some(name) = self.derived_from.as_ref() {
389                if lvl.is_strict() {
390                    super::check_dimable_name(name, "derivedFrom")?;
391                }
392            } else if let Some(registers) = self.registers.as_ref() {
393                if registers.is_empty() && lvl.is_strict() {
394                    return Err(Error::EmptyRegisters.into());
395                }
396            }
397        }
398        Ok(())
399    }
400    pub fn validate_all(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
402        if let Some(abs) = self.address_block.as_ref() {
403            for ab in abs {
404                ab.validate(lvl)?;
405            }
406        }
407        for i in &self.interrupt {
408            i.validate(lvl)?;
409        }
410        self.default_register_properties.validate(lvl)?;
411        for r in self.registers() {
412            r.validate_all(lvl)?;
413        }
414        for c in self.clusters() {
415            c.validate_all(lvl)?;
416        }
417        self.validate(lvl)
418    }
419
420    pub fn registers(&self) -> RegisterIter {
422        RegisterIter {
423            all: match &self.registers {
424                Some(regs) => regs.iter(),
425                None => [].iter(),
426            },
427        }
428    }
429
430    pub fn registers_mut(&mut self) -> RegisterIterMut {
432        RegisterIterMut {
433            all: match &mut self.registers {
434                Some(regs) => regs.iter_mut(),
435                None => [].iter_mut(),
436            },
437        }
438    }
439
440    pub fn clusters(&self) -> ClusterIter {
442        ClusterIter {
443            all: match &self.registers {
444                Some(regs) => regs.iter(),
445                None => [].iter(),
446            },
447        }
448    }
449
450    pub fn clusters_mut(&mut self) -> ClusterIterMut {
452        ClusterIterMut {
453            all: match &mut self.registers {
454                Some(regs) => regs.iter_mut(),
455                None => [].iter_mut(),
456            },
457        }
458    }
459
460    #[deprecated(since = "0.12.1", note = "Please use `all_registers` instead")]
462    pub fn reg_iter(&self) -> AllRegistersIter {
463        self.all_registers()
464    }
465
466    pub fn all_registers(&self) -> AllRegistersIter {
468        AllRegistersIter {
469            rem: match &self.registers {
470                Some(regs) => regs.iter().rev().collect(),
471                None => Vec::new(),
472            },
473        }
474    }
475
476    #[deprecated(since = "0.12.1", note = "Please use `all_registers_mut` instead")]
478    pub fn reg_iter_mut(&mut self) -> AllRegistersIterMut {
479        self.all_registers_mut()
480    }
481
482    pub fn all_registers_mut(&mut self) -> AllRegistersIterMut {
484        AllRegistersIterMut {
485            rem: match &mut self.registers {
486                Some(regs) => regs.iter_mut().rev().collect(),
487                None => Vec::new(),
488            },
489        }
490    }
491
492    pub fn get_register(&self, name: &str) -> Option<&Register> {
494        self.registers().find(|f| f.name == name)
495    }
496
497    pub fn get_mut_register(&mut self, name: &str) -> Option<&mut Register> {
499        self.registers_mut().find(|f| f.name == name)
500    }
501
502    pub fn get_cluster(&self, name: &str) -> Option<&Cluster> {
504        self.clusters().find(|f| f.name == name)
505    }
506
507    pub fn get_mut_cluster(&mut self, name: &str) -> Option<&mut Cluster> {
509        self.clusters_mut().find(|f| f.name == name)
510    }
511
512    pub fn get_interrupt(&self, name: &str) -> Option<&Interrupt> {
514        self.interrupt.iter().find(|e| e.name == name)
515    }
516
517    pub fn get_mut_interrupt(&mut self, name: &str) -> Option<&mut Interrupt> {
519        self.interrupt.iter_mut().find(|e| e.name == name)
520    }
521}
522
523impl Peripheral {
524    pub fn validate_all(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
526        if let Self::Array(_, dim) = self {
527            dim.validate(lvl)?;
528        }
529        self.deref().validate_all(lvl)
530    }
531}
532
533impl Name for PeripheralInfo {
534    fn name(&self) -> &str {
535        &self.name
536    }
537}
538
539impl Description for PeripheralInfo {
540    fn description(&self) -> Option<&str> {
541        self.description.as_deref()
542    }
543}