From b858a79d6eb193f8a7f59fbbd2d151b8132a05a2 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Tue, 9 Nov 2021 11:22:14 +0300 Subject: [PATCH] builder for AddressBlock --- svd-parser/src/addressblock.rs | 16 +++-- svd-rs/CHANGELOG.md | 1 + svd-rs/src/addressblock.rs | 104 ++++++++++++++++++++++++++++++++- tests/src/addressblock.rs | 15 ++--- 4 files changed, 122 insertions(+), 14 deletions(-) diff --git a/svd-parser/src/addressblock.rs b/svd-parser/src/addressblock.rs index 9f0f42e3..9a0585f0 100644 --- a/svd-parser/src/addressblock.rs +++ b/svd-parser/src/addressblock.rs @@ -7,12 +7,16 @@ impl Parse for AddressBlock { type Config = Config; fn parse(tree: &Node, config: &Self::Config) -> Result { - 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", 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", tree, config)?) + .build(config.validate_level) + .map_err(|e| SVDError::from(e).at(tree.id())) } } diff --git a/svd-rs/CHANGELOG.md b/svd-rs/CHANGELOG.md index 4361441e..5486d4cb 100644 --- a/svd-rs/CHANGELOG.md +++ b/svd-rs/CHANGELOG.md @@ -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` diff --git a/svd-rs/src/addressblock.rs b/svd-rs/src/addressblock.rs index 324ac804..945c8069 100644 --- a/svd-rs/src/addressblock.rs +++ b/svd-rs/src/addressblock.rs @@ -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, @@ -60,3 +61,104 @@ impl AddressBlockUsage { } } } + +/// Builder for [`AddressBlock`] +#[derive(Clone, Debug, Default, PartialEq)] +pub struct AddressBlockBuilder { + offset: Option, + size: Option, + usage: Option, + protection: Option, +} + +impl From 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) -> Self { + self.protection = value; + self + } + /// Validate and build a [`AddressBlock`]. + pub fn build(self, lvl: ValidateLevel) -> Result { + 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(()) + } +} diff --git a/tests/src/addressblock.rs b/tests/src/addressblock.rs index 2f02f2e9..3394a28e 100644 --- a/tests/src/addressblock.rs +++ b/tests/src/addressblock.rs @@ -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(), " 0x0 0x800