Skip to content

Commit

Permalink
builder for AddressBlock
Browse files Browse the repository at this point in the history
  • Loading branch information
burrbull committed Nov 9, 2021
1 parent 3ac31f0 commit b858a79
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 14 deletions.
16 changes: 10 additions & 6 deletions svd-parser/src/addressblock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ impl Parse for AddressBlock {
type Config = Config;

fn parse(tree: &Node, config: &Self::Config) -> Result<Self, Self::Error> {
Ok(Self {
offset: tree.get_child_u32("offset")?,
size: tree.get_child_u32("size")?,
usage: AddressBlockUsage::parse(&tree.get_child_elem("usage")?, config)?,
protection: optional::<Protection>("protection", tree, config)?,
})
Self::builder()
.offset(tree.get_child_u32("offset")?)
.size(tree.get_child_u32("size")?)
.usage(AddressBlockUsage::parse(
&tree.get_child_elem("usage")?,
config,
)?)
.protection(optional::<Protection>("protection", tree, config)?)
.build(config.validate_level)
.map_err(|e| SVDError::from(e).at(tree.id()))
}
}

Expand Down
1 change: 1 addition & 0 deletions svd-rs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased

- `AddressBlock` now uses builder
- Add `dim_name` and `dim_array_index` to `DimElement`
- Add `alternate_peripheral`, `prepend_to_name`, `append_to_name`,
`header_struct_name` to `PeripheralInfo`, `alternate_cluster` to `ClusterInfo`
Expand Down
104 changes: 103 additions & 1 deletion svd-rs/src/addressblock.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use super::Protection;
use super::{BuildError, Protection, SvdError, ValidateLevel};

/// An uniquely mapped address block to a peripheral
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct AddressBlock {
/// Specifies the start address of an address block relative to the peripheral [`baseAddress`](crate::Peripheral::base_address).
pub offset: u32,
Expand Down Expand Up @@ -60,3 +61,104 @@ impl AddressBlockUsage {
}
}
}

/// Builder for [`AddressBlock`]
#[derive(Clone, Debug, Default, PartialEq)]
pub struct AddressBlockBuilder {
offset: Option<u32>,
size: Option<u32>,
usage: Option<AddressBlockUsage>,
protection: Option<Protection>,
}

impl From<AddressBlock> for AddressBlockBuilder {
fn from(d: AddressBlock) -> Self {
Self {
offset: Some(d.offset),
size: Some(d.size),
usage: Some(d.usage),
protection: d.protection,
}
}
}

impl AddressBlockBuilder {
/// Set the offset of the block
pub fn offset(mut self, value: u32) -> Self {
self.offset = Some(value);
self
}
/// Set the size of the block
pub fn size(mut self, value: u32) -> Self {
self.size = Some(value);
self
}
/// Set the usage of the block
pub fn usage(mut self, value: AddressBlockUsage) -> Self {
self.usage = Some(value);
self
}
/// Set the protection of the block
pub fn protection(mut self, value: Option<Protection>) -> Self {
self.protection = value;
self
}
/// Validate and build a [`AddressBlock`].
pub fn build(self, lvl: ValidateLevel) -> Result<AddressBlock, SvdError> {
let mut de = AddressBlock {
offset: self
.offset
.ok_or_else(|| BuildError::Uninitialized("offset".to_string()))?,
size: self
.size
.ok_or_else(|| BuildError::Uninitialized("size".to_string()))?,
usage: self
.usage
.ok_or_else(|| BuildError::Uninitialized("usage".to_string()))?,
protection: self.protection,
};
if !lvl.is_disabled() {
de.validate(lvl)?;
}
Ok(de)
}
}

impl AddressBlock {
/// Make a builder for [`AddressBlock`]
pub fn builder() -> AddressBlockBuilder {
AddressBlockBuilder::default()
}
/// Modify an existing [`AddressBlock`] based on a [builder](AddressBlockBuilder).
pub fn modify_from(
&mut self,
builder: AddressBlockBuilder,
lvl: ValidateLevel,
) -> Result<(), SvdError> {
if let Some(offset) = builder.offset {
self.offset = offset;
}
if let Some(size) = builder.size {
self.size = size;
}
if let Some(usage) = builder.usage {
self.usage = usage;
}
if builder.protection.is_some() {
self.protection = builder.protection;
}
if !lvl.is_disabled() {
self.validate(lvl)
} else {
Ok(())
}
}
/// Validate the [`AddressBlock`].
///
/// # Notes
///
/// This doesn't do anything.
pub fn validate(&mut self, _lvl: ValidateLevel) -> Result<(), SvdError> {
Ok(())
}
}
15 changes: 8 additions & 7 deletions tests/src/addressblock.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use super::run_test;
use crate::svd::{AddressBlock, AddressBlockUsage};
use crate::svd::{AddressBlock, AddressBlockUsage, ValidateLevel};

#[test]
fn decode_encode() {
let tests = vec![(
AddressBlock {
offset: 0,
size: 0x00000800,
usage: AddressBlockUsage::Registers,
protection: None,
},
AddressBlock::builder()
.offset(0)
.size(0x00000800)
.usage(AddressBlockUsage::Registers)
.protection(None)
.build(ValidateLevel::Strict)
.unwrap(),
"<addressBlock>
<offset>0x0</offset>
<size>0x800</size>
Expand Down

0 comments on commit b858a79

Please sign in to comment.