svd_rs/
addressblock.rs

1use super::{BuildError, Protection, SvdError, ValidateLevel};
2
3///  An uniquely mapped address block to a peripheral
4#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
5#[derive(Clone, Debug, PartialEq, Eq)]
6#[non_exhaustive]
7pub struct AddressBlock {
8    /// Specifies the start address of an address block relative to the peripheral [`baseAddress`](crate::Peripheral::base_address).
9    pub offset: u32,
10    /// Specifies the number of [`addressUnitBits`](crate::Device::address_unit_bits) being covered by this address block.
11    pub size: u32,
12    /// Usage of the address block.
13    pub usage: AddressBlockUsage,
14    /// Specify the security privilege to access an address region
15    #[cfg_attr(
16        feature = "serde",
17        serde(default, skip_serializing_if = "Option::is_none")
18    )]
19    pub protection: Option<Protection>,
20}
21
22/// Usage of the address block.
23#[cfg_attr(
24    feature = "serde",
25    derive(serde::Deserialize, serde::Serialize),
26    serde(rename_all = "kebab-case")
27)]
28#[derive(Clone, Copy, Debug, Eq, PartialEq)]
29pub enum AddressBlockUsage {
30    /// Registers
31    Registers,
32    /// Buffer / Memory
33    Buffer,
34    /// Reserved
35    Reserved,
36}
37
38impl Default for AddressBlockUsage {
39    fn default() -> Self {
40        Self::Registers
41    }
42}
43
44impl AddressBlockUsage {
45    /// Parse a string into an [`AddressBlockUsage`] value, returning [`Option::None`] if the string is not valid.
46    pub fn parse_str(s: &str) -> Option<Self> {
47        match s {
48            "registers" => Some(Self::Registers),
49            "buffer" => Some(Self::Buffer),
50            "reserved" => Some(Self::Reserved),
51            _ => None,
52        }
53    }
54
55    /// Convert this [`AddressBlockUsage`] into a static string.
56    pub const fn as_str(self) -> &'static str {
57        match self {
58            Self::Registers => "registers",
59            Self::Buffer => "buffer",
60            Self::Reserved => "reserved",
61        }
62    }
63}
64
65/// Builder for [`AddressBlock`]
66#[derive(Clone, Debug, Default, PartialEq, Eq)]
67pub struct AddressBlockBuilder {
68    offset: Option<u32>,
69    size: Option<u32>,
70    usage: Option<AddressBlockUsage>,
71    protection: Option<Protection>,
72}
73
74impl From<AddressBlock> for AddressBlockBuilder {
75    fn from(d: AddressBlock) -> Self {
76        Self {
77            offset: Some(d.offset),
78            size: Some(d.size),
79            usage: Some(d.usage),
80            protection: d.protection,
81        }
82    }
83}
84
85impl AddressBlockBuilder {
86    /// Set the offset of the block
87    pub fn offset(mut self, value: u32) -> Self {
88        self.offset = Some(value);
89        self
90    }
91    /// Set the size of the block
92    pub fn size(mut self, value: u32) -> Self {
93        self.size = Some(value);
94        self
95    }
96    /// Set the usage of the block
97    pub fn usage(mut self, value: AddressBlockUsage) -> Self {
98        self.usage = Some(value);
99        self
100    }
101    /// Set the protection of the block
102    pub fn protection(mut self, value: Option<Protection>) -> Self {
103        self.protection = value;
104        self
105    }
106    /// Validate and build a [`AddressBlock`].
107    pub fn build(self, lvl: ValidateLevel) -> Result<AddressBlock, SvdError> {
108        let de = AddressBlock {
109            offset: self
110                .offset
111                .ok_or_else(|| BuildError::Uninitialized("offset".to_string()))?,
112            size: self
113                .size
114                .ok_or_else(|| BuildError::Uninitialized("size".to_string()))?,
115            usage: self
116                .usage
117                .ok_or_else(|| BuildError::Uninitialized("usage".to_string()))?,
118            protection: self.protection,
119        };
120        de.validate(lvl)?;
121        Ok(de)
122    }
123}
124
125impl AddressBlock {
126    /// Make a builder for [`AddressBlock`]
127    pub fn builder() -> AddressBlockBuilder {
128        AddressBlockBuilder::default()
129    }
130    /// Modify an existing [`AddressBlock`] based on a [builder](AddressBlockBuilder).
131    pub fn modify_from(
132        &mut self,
133        builder: AddressBlockBuilder,
134        lvl: ValidateLevel,
135    ) -> Result<(), SvdError> {
136        if let Some(offset) = builder.offset {
137            self.offset = offset;
138        }
139        if let Some(size) = builder.size {
140            self.size = size;
141        }
142        if let Some(usage) = builder.usage {
143            self.usage = usage;
144        }
145        if builder.protection.is_some() {
146            self.protection = builder.protection;
147        }
148        self.validate(lvl)
149    }
150    /// Validate the [`AddressBlock`].
151    ///
152    /// # Notes
153    ///
154    /// This doesn't do anything.
155    pub fn validate(&self, _lvl: ValidateLevel) -> Result<(), SvdError> {
156        Ok(())
157    }
158}