From 98fe606864228ee1b60e4336fbc93a7de02df0bf Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 20 Dec 2021 19:38:16 +0300 Subject: [PATCH] merge info files --- svd-encoder/src/cluster.rs | 45 ++- svd-encoder/src/clusterinfo.rs | 44 --- svd-encoder/src/field.rs | 52 +++- svd-encoder/src/fieldinfo.rs | 51 ---- svd-encoder/src/lib.rs | 4 - svd-encoder/src/peripheral.rs | 83 +++++- svd-encoder/src/peripheralinfo.rs | 82 ------ svd-encoder/src/register.rs | 69 ++++- svd-encoder/src/registerinfo.rs | 68 ----- svd-parser/src/cluster.rs | 31 +- svd-parser/src/clusterinfo.rs | 31 -- svd-parser/src/field.rs | 46 ++- svd-parser/src/fieldinfo.rs | 45 --- svd-parser/src/lib.rs | 4 - svd-parser/src/peripheral.rs | 63 +++- svd-parser/src/peripheralinfo.rs | 61 ---- svd-parser/src/register.rs | 48 ++- svd-parser/src/registerinfo.rs | 47 --- svd-rs/CHANGELOG.md | 1 + svd-rs/src/cluster.rs | 313 +++++++++++++++++++- svd-rs/src/clusterinfo.rs | 311 -------------------- svd-rs/src/field.rs | 358 +++++++++++++++++++++- svd-rs/src/fieldinfo.rs | 356 ---------------------- svd-rs/src/lib.rs | 32 +- svd-rs/src/peripheral.rs | 472 +++++++++++++++++++++++++++++- svd-rs/src/peripheralinfo.rs | 470 ----------------------------- svd-rs/src/register.rs | 366 ++++++++++++++++++++++- svd-rs/src/registerinfo.rs | 363 ----------------------- tests/src/field.rs | 79 ++++- tests/src/fieldinfo.rs | 72 ----- tests/src/lib.rs | 2 - tests/src/register.rs | 63 +++- tests/src/registerinfo.rs | 63 ---- 33 files changed, 2072 insertions(+), 2123 deletions(-) delete mode 100644 svd-encoder/src/clusterinfo.rs delete mode 100644 svd-encoder/src/fieldinfo.rs delete mode 100644 svd-encoder/src/peripheralinfo.rs delete mode 100644 svd-encoder/src/registerinfo.rs delete mode 100644 svd-parser/src/clusterinfo.rs delete mode 100644 svd-parser/src/fieldinfo.rs delete mode 100644 svd-parser/src/peripheralinfo.rs delete mode 100644 svd-parser/src/registerinfo.rs delete mode 100644 svd-rs/src/clusterinfo.rs delete mode 100644 svd-rs/src/fieldinfo.rs delete mode 100644 svd-rs/src/peripheralinfo.rs delete mode 100644 svd-rs/src/registerinfo.rs delete mode 100644 tests/src/fieldinfo.rs delete mode 100644 tests/src/registerinfo.rs diff --git a/svd-encoder/src/cluster.rs b/svd-encoder/src/cluster.rs index 6f26be00..104f69a1 100644 --- a/svd-encoder/src/cluster.rs +++ b/svd-encoder/src/cluster.rs @@ -1,6 +1,6 @@ -use super::{Element, ElementMerge, Encode, EncodeError}; +use super::{new_node, Element, ElementMerge, Encode, EncodeChildren, EncodeError, XMLNode}; -use crate::svd::Cluster; +use crate::svd::{Cluster, ClusterInfo}; impl Encode for Cluster { type Error = EncodeError; @@ -17,3 +17,44 @@ impl Encode for Cluster { } } } + +impl Encode for ClusterInfo { + type Error = EncodeError; + + fn encode(&self) -> Result { + let mut e = Element::new("cluster"); + + e.children.push(new_node("name", self.name.clone())); + + if let Some(v) = &self.description { + e.children.push(new_node("description", v.clone())); + } + + if let Some(v) = &self.alternate_cluster { + e.children.push(new_node("alternateCluster", v.clone())); + } + + if let Some(v) = &self.header_struct_name { + e.children.push(new_node("headerStructName", v.clone())); + } + + e.children.push(new_node( + "addressOffset", + format!("{}", self.address_offset), + )); + + e.children + .extend(self.default_register_properties.encode()?); + + for c in &self.children { + e.children.push(XMLNode::Element(c.encode()?)); + } + + if let Some(v) = &self.derived_from { + e.attributes + .insert(String::from("derivedFrom"), v.to_string()); + } + + Ok(e) + } +} diff --git a/svd-encoder/src/clusterinfo.rs b/svd-encoder/src/clusterinfo.rs deleted file mode 100644 index 71de2b43..00000000 --- a/svd-encoder/src/clusterinfo.rs +++ /dev/null @@ -1,44 +0,0 @@ -use super::{new_node, Element, Encode, EncodeChildren, EncodeError, XMLNode}; - -use crate::svd::ClusterInfo; - -impl Encode for ClusterInfo { - type Error = EncodeError; - - fn encode(&self) -> Result { - let mut e = Element::new("cluster"); - - e.children.push(new_node("name", self.name.clone())); - - if let Some(v) = &self.description { - e.children.push(new_node("description", v.clone())); - } - - if let Some(v) = &self.alternate_cluster { - e.children.push(new_node("alternateCluster", v.clone())); - } - - if let Some(v) = &self.header_struct_name { - e.children.push(new_node("headerStructName", v.clone())); - } - - e.children.push(new_node( - "addressOffset", - format!("{}", self.address_offset), - )); - - e.children - .extend(self.default_register_properties.encode()?); - - for c in &self.children { - e.children.push(XMLNode::Element(c.encode()?)); - } - - if let Some(v) = &self.derived_from { - e.attributes - .insert(String::from("derivedFrom"), v.to_string()); - } - - Ok(e) - } -} diff --git a/svd-encoder/src/field.rs b/svd-encoder/src/field.rs index a1fbf3b5..c3dabf20 100644 --- a/svd-encoder/src/field.rs +++ b/svd-encoder/src/field.rs @@ -1,6 +1,7 @@ -use super::{Element, ElementMerge, Encode, EncodeError}; +use super::{new_node, Element, ElementMerge, Encode, EncodeError, XMLNode}; +use crate::bitrange::encode_bitrange; -use crate::svd::Field; +use crate::svd::{Field, FieldInfo}; impl Encode for Field { type Error = EncodeError; @@ -17,3 +18,50 @@ impl Encode for Field { } } } + +impl Encode for FieldInfo { + type Error = EncodeError; + + fn encode(&self) -> Result { + let mut elem = Element::new("field"); + elem.children.push(new_node("name", self.name.clone())); + + if let Some(description) = &self.description { + elem.children + .push(new_node("description", description.clone())) + } + + // Add bit range + elem.children.append(&mut encode_bitrange(&self.bit_range)?); + + if let Some(v) = &self.access { + elem.children.push(v.encode_node()?); + } + + if let Some(v) = &self.modified_write_values { + elem.children.push(v.encode_node()?); + } + + if let Some(v) = &self.write_constraint { + elem.children.push(v.encode_node()?); + } + + if let Some(v) = &self.read_action { + elem.children.push(v.encode_node()?); + } + + let enumerated_values: Result, EncodeError> = self + .enumerated_values + .iter() + .map(|v| v.encode_node()) + .collect(); + elem.children.append(&mut enumerated_values?); + + if let Some(v) = &self.derived_from { + elem.attributes + .insert(String::from("derivedFrom"), v.to_string()); + } + + Ok(elem) + } +} diff --git a/svd-encoder/src/fieldinfo.rs b/svd-encoder/src/fieldinfo.rs deleted file mode 100644 index 7b44f5ac..00000000 --- a/svd-encoder/src/fieldinfo.rs +++ /dev/null @@ -1,51 +0,0 @@ -use super::{new_node, Element, Encode, EncodeError, XMLNode}; -use crate::bitrange::encode_bitrange; - -use crate::svd::FieldInfo; - -impl Encode for FieldInfo { - type Error = EncodeError; - - fn encode(&self) -> Result { - let mut elem = Element::new("field"); - elem.children.push(new_node("name", self.name.clone())); - - if let Some(description) = &self.description { - elem.children - .push(new_node("description", description.clone())) - } - - // Add bit range - elem.children.append(&mut encode_bitrange(&self.bit_range)?); - - if let Some(v) = &self.access { - elem.children.push(v.encode_node()?); - } - - if let Some(v) = &self.modified_write_values { - elem.children.push(v.encode_node()?); - } - - if let Some(v) = &self.write_constraint { - elem.children.push(v.encode_node()?); - } - - if let Some(v) = &self.read_action { - elem.children.push(v.encode_node()?); - } - - let enumerated_values: Result, EncodeError> = self - .enumerated_values - .iter() - .map(|v| v.encode_node()) - .collect(); - elem.children.append(&mut enumerated_values?); - - if let Some(v) = &self.derived_from { - elem.attributes - .insert(String::from("derivedFrom"), v.to_string()); - } - - Ok(elem) - } -} diff --git a/svd-encoder/src/lib.rs b/svd-encoder/src/lib.rs index 579c4881..e94afc8e 100644 --- a/svd-encoder/src/lib.rs +++ b/svd-encoder/src/lib.rs @@ -66,7 +66,6 @@ mod access; mod addressblock; mod bitrange; mod cluster; -mod clusterinfo; mod cpu; mod device; mod dimelement; @@ -74,16 +73,13 @@ mod endian; mod enumeratedvalue; mod enumeratedvalues; mod field; -mod fieldinfo; mod interrupt; mod modifiedwritevalues; mod peripheral; -mod peripheralinfo; mod protection; mod readaction; mod register; mod registercluster; -mod registerinfo; mod registerproperties; mod usage; mod writeconstraint; diff --git a/svd-encoder/src/peripheral.rs b/svd-encoder/src/peripheral.rs index 5a05b18b..bbaa00e4 100644 --- a/svd-encoder/src/peripheral.rs +++ b/svd-encoder/src/peripheral.rs @@ -1,6 +1,6 @@ -use super::{Element, ElementMerge, Encode, EncodeError}; +use super::{new_node, Element, ElementMerge, Encode, EncodeChildren, EncodeError, XMLNode}; -use crate::svd::Peripheral; +use crate::svd::{Interrupt, Peripheral, PeripheralInfo}; impl Encode for Peripheral { type Error = EncodeError; @@ -17,3 +17,82 @@ impl Encode for Peripheral { } } } + +impl Encode for PeripheralInfo { + type Error = EncodeError; + + fn encode(&self) -> Result { + let mut elem = Element::new("peripheral"); + elem.children.push(new_node("name", self.name.clone())); + + if let Some(v) = &self.display_name { + elem.children.push(new_node("displayName", v.to_string())); + } + + if let Some(v) = &self.version { + elem.children.push(new_node("version", v.to_string())); + } + + if let Some(v) = &self.description { + elem.children.push(new_node("description", v.to_string())); + } + + if let Some(v) = &self.alternate_peripheral { + elem.children + .push(new_node("alternatePeripheral", v.to_string())); + } + + if let Some(v) = &self.group_name { + elem.children.push(new_node("groupName", v.to_string())); + } + + if let Some(v) = &self.prepend_to_name { + elem.children.push(new_node("prependToName", v.to_string())); + } + + if let Some(v) = &self.append_to_name { + elem.children.push(new_node("appendToName", v.to_string())); + } + + if let Some(v) = &self.header_struct_name { + elem.children + .push(new_node("headerStructName", v.to_string())); + } + + elem.children.push(new_node( + "baseAddress", + format!("0x{:.08X}", self.base_address), + )); + + elem.children + .extend(self.default_register_properties.encode()?); + + if let Some(v) = &self.address_block { + for ab in v { + elem.children.push(ab.encode_node()?); + } + } + + let interrupts: Result, _> = + self.interrupt.iter().map(Interrupt::encode_node).collect(); + + elem.children.append(&mut interrupts?); + + if let Some(v) = &self.registers { + let children: Result, _> = v.iter().map(|e| e.encode_node()).collect(); + + elem.children.push({ + let mut e = Element::new("registers"); + e.children = children?; + XMLNode::Element(e) + }); + } + + if let Some(v) = &self.derived_from { + elem.attributes + .insert(String::from("derivedFrom"), v.to_string()); + } + + Ok(elem) + } +} diff --git a/svd-encoder/src/peripheralinfo.rs b/svd-encoder/src/peripheralinfo.rs deleted file mode 100644 index 59b86dca..00000000 --- a/svd-encoder/src/peripheralinfo.rs +++ /dev/null @@ -1,82 +0,0 @@ -use super::{new_node, Element, Encode, EncodeChildren, EncodeError, XMLNode}; - -use crate::svd::{Interrupt, PeripheralInfo}; - -impl Encode for PeripheralInfo { - type Error = EncodeError; - - fn encode(&self) -> Result { - let mut elem = Element::new("peripheral"); - elem.children.push(new_node("name", self.name.clone())); - - if let Some(v) = &self.display_name { - elem.children.push(new_node("displayName", v.to_string())); - } - - if let Some(v) = &self.version { - elem.children.push(new_node("version", v.to_string())); - } - - if let Some(v) = &self.description { - elem.children.push(new_node("description", v.to_string())); - } - - if let Some(v) = &self.alternate_peripheral { - elem.children - .push(new_node("alternatePeripheral", v.to_string())); - } - - if let Some(v) = &self.group_name { - elem.children.push(new_node("groupName", v.to_string())); - } - - if let Some(v) = &self.prepend_to_name { - elem.children.push(new_node("prependToName", v.to_string())); - } - - if let Some(v) = &self.append_to_name { - elem.children.push(new_node("appendToName", v.to_string())); - } - - if let Some(v) = &self.header_struct_name { - elem.children - .push(new_node("headerStructName", v.to_string())); - } - - elem.children.push(new_node( - "baseAddress", - format!("0x{:.08X}", self.base_address), - )); - - elem.children - .extend(self.default_register_properties.encode()?); - - if let Some(v) = &self.address_block { - for ab in v { - elem.children.push(ab.encode_node()?); - } - } - - let interrupts: Result, _> = - self.interrupt.iter().map(Interrupt::encode_node).collect(); - - elem.children.append(&mut interrupts?); - - if let Some(v) = &self.registers { - let children: Result, _> = v.iter().map(|e| e.encode_node()).collect(); - - elem.children.push({ - let mut e = Element::new("registers"); - e.children = children?; - XMLNode::Element(e) - }); - } - - if let Some(v) = &self.derived_from { - elem.attributes - .insert(String::from("derivedFrom"), v.to_string()); - } - - Ok(elem) - } -} diff --git a/svd-encoder/src/register.rs b/svd-encoder/src/register.rs index 86c48d48..fc68f9c3 100644 --- a/svd-encoder/src/register.rs +++ b/svd-encoder/src/register.rs @@ -1,6 +1,6 @@ -use super::{Element, ElementMerge, Encode, EncodeError}; +use super::{new_node, Element, ElementMerge, Encode, EncodeChildren, EncodeError, XMLNode}; -use crate::svd::Register; +use crate::svd::{Field, Register, RegisterInfo}; impl Encode for Register { type Error = EncodeError; @@ -17,3 +17,68 @@ impl Encode for Register { } } } + +impl Encode for RegisterInfo { + type Error = EncodeError; + + fn encode(&self) -> Result { + let mut elem = Element::new("register"); + elem.children.push(new_node("name", self.name.clone())); + + if let Some(v) = &self.display_name { + elem.children.push(new_node("displayName", v.clone())); + } + + if let Some(v) = &self.description { + elem.children.push(new_node("description", v.clone())); + } + + if let Some(v) = &self.alternate_group { + elem.children + .push(new_node("alternateGroup", v.to_string())); + } + + if let Some(v) = &self.alternate_register { + elem.children + .push(new_node("alternateRegister", v.to_string())); + } + + elem.children.push(new_node( + "addressOffset", + format!("0x{:X}", self.address_offset), + )); + + elem.children.extend(self.properties.encode()?); + + if let Some(v) = &self.modified_write_values { + elem.children.push(v.encode_node()?); + } + + if let Some(v) = &self.write_constraint { + elem.children.push(v.encode_node()?); + } + + if let Some(v) = &self.read_action { + elem.children.push(v.encode_node()?); + } + + if let Some(v) = &self.fields { + let children = v + .iter() + .map(Field::encode_node) + .collect::, EncodeError>>()?; + if !children.is_empty() { + let mut fields = Element::new("fields"); + fields.children = children; + elem.children.push(XMLNode::Element(fields)); + } + } + + if let Some(v) = &self.derived_from { + elem.attributes + .insert(String::from("derivedFrom"), v.to_string()); + } + + Ok(elem) + } +} diff --git a/svd-encoder/src/registerinfo.rs b/svd-encoder/src/registerinfo.rs deleted file mode 100644 index 2e9d8be3..00000000 --- a/svd-encoder/src/registerinfo.rs +++ /dev/null @@ -1,68 +0,0 @@ -use super::{new_node, Element, Encode, EncodeChildren, EncodeError, XMLNode}; - -use crate::svd::{Field, RegisterInfo}; - -impl Encode for RegisterInfo { - type Error = EncodeError; - - fn encode(&self) -> Result { - let mut elem = Element::new("register"); - elem.children.push(new_node("name", self.name.clone())); - - if let Some(v) = &self.display_name { - elem.children.push(new_node("displayName", v.clone())); - } - - if let Some(v) = &self.description { - elem.children.push(new_node("description", v.clone())); - } - - if let Some(v) = &self.alternate_group { - elem.children - .push(new_node("alternateGroup", v.to_string())); - } - - if let Some(v) = &self.alternate_register { - elem.children - .push(new_node("alternateRegister", v.to_string())); - } - - elem.children.push(new_node( - "addressOffset", - format!("0x{:X}", self.address_offset), - )); - - elem.children.extend(self.properties.encode()?); - - if let Some(v) = &self.modified_write_values { - elem.children.push(v.encode_node()?); - } - - if let Some(v) = &self.write_constraint { - elem.children.push(v.encode_node()?); - } - - if let Some(v) = &self.read_action { - elem.children.push(v.encode_node()?); - } - - if let Some(v) = &self.fields { - let children = v - .iter() - .map(Field::encode_node) - .collect::, EncodeError>>()?; - if !children.is_empty() { - let mut fields = Element::new("fields"); - fields.children = children; - elem.children.push(XMLNode::Element(fields)); - } - } - - if let Some(v) = &self.derived_from { - elem.attributes - .insert(String::from("derivedFrom"), v.to_string()); - } - - Ok(elem) - } -} diff --git a/svd-parser/src/cluster.rs b/svd-parser/src/cluster.rs index 6fbf4d15..2fe8b729 100644 --- a/svd-parser/src/cluster.rs +++ b/svd-parser/src/cluster.rs @@ -1,5 +1,5 @@ use super::*; -use crate::svd::Cluster; +use crate::svd::{Cluster, ClusterInfo, RegisterCluster, RegisterProperties}; impl Parse for Cluster { type Object = Self; @@ -10,3 +10,32 @@ impl Parse for Cluster { parse_array("cluster", tree, config) } } + +impl Parse for ClusterInfo { + type Object = Self; + type Error = SVDErrorAt; + type Config = Config; + + fn parse(tree: &Node, config: &Self::Config) -> Result { + ClusterInfo::builder() + .name(tree.get_child_text("name")?) + .description(tree.get_child_text_opt("description")?) + .alternate_cluster(tree.get_child_text_opt("alternateCluster")?) + .header_struct_name(tree.get_child_text_opt("headerStructName")?) + .address_offset(tree.get_child_u32("addressOffset")?) + .default_register_properties(RegisterProperties::parse(tree, config)?) + .children({ + let children: Result, _> = tree + .children() + .filter(|t| { + t.is_element() && (t.has_tag_name("register") || t.has_tag_name("cluster")) + }) + .map(|t| RegisterCluster::parse(&t, config)) + .collect(); + children? + }) + .derived_from(tree.attribute("derivedFrom").map(|s| s.to_owned())) + .build(config.validate_level) + .map_err(|e| SVDError::from(e).at(tree.id())) + } +} diff --git a/svd-parser/src/clusterinfo.rs b/svd-parser/src/clusterinfo.rs deleted file mode 100644 index 1cba272d..00000000 --- a/svd-parser/src/clusterinfo.rs +++ /dev/null @@ -1,31 +0,0 @@ -use super::*; -use crate::svd::{ClusterInfo, RegisterCluster, RegisterProperties}; - -impl Parse for ClusterInfo { - type Object = Self; - type Error = SVDErrorAt; - type Config = Config; - - fn parse(tree: &Node, config: &Self::Config) -> Result { - ClusterInfo::builder() - .name(tree.get_child_text("name")?) - .description(tree.get_child_text_opt("description")?) - .alternate_cluster(tree.get_child_text_opt("alternateCluster")?) - .header_struct_name(tree.get_child_text_opt("headerStructName")?) - .address_offset(tree.get_child_u32("addressOffset")?) - .default_register_properties(RegisterProperties::parse(tree, config)?) - .children({ - let children: Result, _> = tree - .children() - .filter(|t| { - t.is_element() && (t.has_tag_name("register") || t.has_tag_name("cluster")) - }) - .map(|t| RegisterCluster::parse(&t, config)) - .collect(); - children? - }) - .derived_from(tree.attribute("derivedFrom").map(|s| s.to_owned())) - .build(config.validate_level) - .map_err(|e| SVDError::from(e).at(tree.id())) - } -} diff --git a/svd-parser/src/field.rs b/svd-parser/src/field.rs index 87b80bbc..67bbb464 100644 --- a/svd-parser/src/field.rs +++ b/svd-parser/src/field.rs @@ -1,5 +1,8 @@ use super::*; -use crate::svd::Field; +use crate::svd::{ + Access, BitRange, EnumeratedValues, Field, FieldInfo, ModifiedWriteValues, ReadAction, + WriteConstraint, +}; impl Parse for Field { type Object = Self; @@ -10,3 +13,44 @@ impl Parse for Field { parse_array("field", tree, config) } } + +impl Parse for FieldInfo { + type Object = Self; + type Error = SVDErrorAt; + type Config = Config; + + fn parse(tree: &Node, config: &Self::Config) -> Result { + if !tree.has_tag_name("field") { + return Err(SVDError::NotExpectedTag("field".to_string()).at(tree.id())); + } + + let bit_range = BitRange::parse(tree, config)?; + FieldInfo::builder() + .name(tree.get_child_text("name")?) + .description(tree.get_child_text_opt("description")?) + .bit_range(bit_range) + .access(optional::("access", tree, config)?) + .modified_write_values(optional::( + "modifiedWriteValues", + tree, + config, + )?) + .write_constraint(optional::( + "writeConstraint", + tree, + config, + )?) + .read_action(optional::("readAction", tree, config)?) + .enumerated_values({ + let values: Result, _> = tree + .children() + .filter(|t| t.is_element() && t.has_tag_name("enumeratedValues")) + .map(|t| EnumeratedValues::parse(&t, config)) + .collect(); + values? + }) + .derived_from(tree.attribute("derivedFrom").map(|s| s.to_owned())) + .build(config.validate_level) + .map_err(|e| SVDError::from(e).at(tree.id())) + } +} diff --git a/svd-parser/src/fieldinfo.rs b/svd-parser/src/fieldinfo.rs deleted file mode 100644 index a33059ca..00000000 --- a/svd-parser/src/fieldinfo.rs +++ /dev/null @@ -1,45 +0,0 @@ -use super::*; -use crate::svd::{ - Access, BitRange, EnumeratedValues, FieldInfo, ModifiedWriteValues, ReadAction, WriteConstraint, -}; - -impl Parse for FieldInfo { - type Object = Self; - type Error = SVDErrorAt; - type Config = Config; - - fn parse(tree: &Node, config: &Self::Config) -> Result { - if !tree.has_tag_name("field") { - return Err(SVDError::NotExpectedTag("field".to_string()).at(tree.id())); - } - - let bit_range = BitRange::parse(tree, config)?; - FieldInfo::builder() - .name(tree.get_child_text("name")?) - .description(tree.get_child_text_opt("description")?) - .bit_range(bit_range) - .access(optional::("access", tree, config)?) - .modified_write_values(optional::( - "modifiedWriteValues", - tree, - config, - )?) - .write_constraint(optional::( - "writeConstraint", - tree, - config, - )?) - .read_action(optional::("readAction", tree, config)?) - .enumerated_values({ - let values: Result, _> = tree - .children() - .filter(|t| t.is_element() && t.has_tag_name("enumeratedValues")) - .map(|t| EnumeratedValues::parse(&t, config)) - .collect(); - values? - }) - .derived_from(tree.attribute("derivedFrom").map(|s| s.to_owned())) - .build(config.validate_level) - .map_err(|e| SVDError::from(e).at(tree.id())) - } -} diff --git a/svd-parser/src/lib.rs b/svd-parser/src/lib.rs index 8d3ba84e..05657111 100644 --- a/svd-parser/src/lib.rs +++ b/svd-parser/src/lib.rs @@ -153,7 +153,6 @@ mod access; mod addressblock; mod bitrange; mod cluster; -mod clusterinfo; mod cpu; mod device; mod dimelement; @@ -161,16 +160,13 @@ mod endian; mod enumeratedvalue; mod enumeratedvalues; mod field; -mod fieldinfo; mod interrupt; mod modifiedwritevalues; mod peripheral; -mod peripheralinfo; mod protection; mod readaction; mod register; mod registercluster; -mod registerinfo; mod registerproperties; mod usage; mod writeconstraint; diff --git a/svd-parser/src/peripheral.rs b/svd-parser/src/peripheral.rs index af72d902..964ed097 100644 --- a/svd-parser/src/peripheral.rs +++ b/svd-parser/src/peripheral.rs @@ -1,5 +1,7 @@ use super::*; -use crate::svd::Peripheral; +use crate::svd::{ + AddressBlock, Interrupt, Peripheral, PeripheralInfo, RegisterCluster, RegisterProperties, +}; impl Parse for Peripheral { type Object = Self; @@ -10,3 +12,62 @@ impl Parse for Peripheral { parse_array("peripheral", tree, config) } } + +impl Parse for PeripheralInfo { + type Object = Self; + type Error = SVDErrorAt; + type Config = Config; + + fn parse(tree: &Node, config: &Self::Config) -> Result { + if !tree.has_tag_name("peripheral") { + return Err(SVDError::NotExpectedTag("peripheral".to_string()).at(tree.id())); + } + + PeripheralInfo::builder() + .name(tree.get_child_text("name")?) + .display_name(tree.get_child_text_opt("displayName")?) + .version(tree.get_child_text_opt("version")?) + .description(tree.get_child_text_opt("description")?) + .alternate_peripheral(tree.get_child_text_opt("alternatePeripheral")?) + .group_name(tree.get_child_text_opt("groupName")?) + .prepend_to_name(tree.get_child_text_opt("prependToName")?) + .append_to_name(tree.get_child_text_opt("appendToName")?) + .header_struct_name(tree.get_child_text_opt("headerStructName")?) + .base_address(tree.get_child_u64("baseAddress")?) + .default_register_properties(RegisterProperties::parse(tree, config)?) + .address_block({ + let ab: Result, _> = tree + .children() + .filter(|t| t.is_element() && t.has_tag_name("addressBlock")) + .map(|i| AddressBlock::parse(&i, config)) + .collect(); + let ab = ab?; + if ab.is_empty() { + None + } else { + Some(ab) + } + }) + .interrupt({ + let interrupt: Result, _> = tree + .children() + .filter(|t| t.is_element() && t.has_tag_name("interrupt")) + .map(|i| Interrupt::parse(&i, config)) + .collect(); + Some(interrupt?) + }) + .registers(if let Some(registers) = tree.get_child("registers") { + let rs: Result, _> = registers + .children() + .filter(Node::is_element) + .map(|t| RegisterCluster::parse(&t, config)) + .collect(); + Some(rs?) + } else { + None + }) + .derived_from(tree.attribute("derivedFrom").map(|s| s.to_owned())) + .build(config.validate_level) + .map_err(|e| SVDError::from(e).at(tree.id())) + } +} diff --git a/svd-parser/src/peripheralinfo.rs b/svd-parser/src/peripheralinfo.rs deleted file mode 100644 index 3c1bad32..00000000 --- a/svd-parser/src/peripheralinfo.rs +++ /dev/null @@ -1,61 +0,0 @@ -use super::*; -use crate::svd::{AddressBlock, Interrupt, PeripheralInfo, RegisterCluster, RegisterProperties}; - -impl Parse for PeripheralInfo { - type Object = Self; - type Error = SVDErrorAt; - type Config = Config; - - fn parse(tree: &Node, config: &Self::Config) -> Result { - if !tree.has_tag_name("peripheral") { - return Err(SVDError::NotExpectedTag("peripheral".to_string()).at(tree.id())); - } - - PeripheralInfo::builder() - .name(tree.get_child_text("name")?) - .display_name(tree.get_child_text_opt("displayName")?) - .version(tree.get_child_text_opt("version")?) - .description(tree.get_child_text_opt("description")?) - .alternate_peripheral(tree.get_child_text_opt("alternatePeripheral")?) - .group_name(tree.get_child_text_opt("groupName")?) - .prepend_to_name(tree.get_child_text_opt("prependToName")?) - .append_to_name(tree.get_child_text_opt("appendToName")?) - .header_struct_name(tree.get_child_text_opt("headerStructName")?) - .base_address(tree.get_child_u64("baseAddress")?) - .default_register_properties(RegisterProperties::parse(tree, config)?) - .address_block({ - let ab: Result, _> = tree - .children() - .filter(|t| t.is_element() && t.has_tag_name("addressBlock")) - .map(|i| AddressBlock::parse(&i, config)) - .collect(); - let ab = ab?; - if ab.is_empty() { - None - } else { - Some(ab) - } - }) - .interrupt({ - let interrupt: Result, _> = tree - .children() - .filter(|t| t.is_element() && t.has_tag_name("interrupt")) - .map(|i| Interrupt::parse(&i, config)) - .collect(); - Some(interrupt?) - }) - .registers(if let Some(registers) = tree.get_child("registers") { - let rs: Result, _> = registers - .children() - .filter(Node::is_element) - .map(|t| RegisterCluster::parse(&t, config)) - .collect(); - Some(rs?) - } else { - None - }) - .derived_from(tree.attribute("derivedFrom").map(|s| s.to_owned())) - .build(config.validate_level) - .map_err(|e| SVDError::from(e).at(tree.id())) - } -} diff --git a/svd-parser/src/register.rs b/svd-parser/src/register.rs index 65cd1d52..ef5340a2 100644 --- a/svd-parser/src/register.rs +++ b/svd-parser/src/register.rs @@ -1,5 +1,8 @@ use super::*; -use crate::svd::Register; +use crate::svd::{ + Field, ModifiedWriteValues, ReadAction, Register, RegisterInfo, RegisterProperties, + WriteConstraint, +}; impl Parse for Register { type Object = Self; @@ -10,3 +13,46 @@ impl Parse for Register { parse_array("register", tree, config) } } + +impl Parse for RegisterInfo { + type Object = Self; + type Error = SVDErrorAt; + type Config = Config; + + fn parse(tree: &Node, config: &Self::Config) -> Result { + RegisterInfo::builder() + .name(tree.get_child_text("name")?) + .display_name(tree.get_child_text_opt("displayName")?) + .description(tree.get_child_text_opt("description")?) + .alternate_group(tree.get_child_text_opt("alternateGroup")?) + .alternate_register(tree.get_child_text_opt("alternateRegister")?) + .address_offset(tree.get_child_u32("addressOffset")?) + .properties(RegisterProperties::parse(tree, config)?) + .modified_write_values(optional::( + "modifiedWriteValues", + tree, + config, + )?) + .write_constraint(optional::( + "writeConstraint", + tree, + config, + )?) + .read_action(optional::("readAction", tree, config)?) + .fields({ + if let Some(fields) = tree.get_child("fields") { + let fs: Result, _> = fields + .children() + .filter(Node::is_element) + .map(|t| Field::parse(&t, config)) + .collect(); + Some(fs?) + } else { + None + } + }) + .derived_from(tree.attribute("derivedFrom").map(|s| s.to_owned())) + .build(config.validate_level) + .map_err(|e| SVDError::from(e).at(tree.id())) + } +} diff --git a/svd-parser/src/registerinfo.rs b/svd-parser/src/registerinfo.rs deleted file mode 100644 index 89b1a8de..00000000 --- a/svd-parser/src/registerinfo.rs +++ /dev/null @@ -1,47 +0,0 @@ -use super::*; -use crate::svd::{ - Field, ModifiedWriteValues, ReadAction, RegisterInfo, RegisterProperties, WriteConstraint, -}; - -impl Parse for RegisterInfo { - type Object = Self; - type Error = SVDErrorAt; - type Config = Config; - - fn parse(tree: &Node, config: &Self::Config) -> Result { - RegisterInfo::builder() - .name(tree.get_child_text("name")?) - .display_name(tree.get_child_text_opt("displayName")?) - .description(tree.get_child_text_opt("description")?) - .alternate_group(tree.get_child_text_opt("alternateGroup")?) - .alternate_register(tree.get_child_text_opt("alternateRegister")?) - .address_offset(tree.get_child_u32("addressOffset")?) - .properties(RegisterProperties::parse(tree, config)?) - .modified_write_values(optional::( - "modifiedWriteValues", - tree, - config, - )?) - .write_constraint(optional::( - "writeConstraint", - tree, - config, - )?) - .read_action(optional::("readAction", tree, config)?) - .fields({ - if let Some(fields) = tree.get_child("fields") { - let fs: Result, _> = fields - .children() - .filter(Node::is_element) - .map(|t| Field::parse(&t, config)) - .collect(); - Some(fs?) - } else { - None - } - }) - .derived_from(tree.attribute("derivedFrom").map(|s| s.to_owned())) - .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 f5a01686..1d4eb61e 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 +- merge `register` with `registerinfo` modules same as other `info`s - `EnumeratedValues.usage()` now return `None` if it is derived, fix bug in usage check - Use generic `SingleArray` enum for types which can be either collected into SVD arrays or have only one instance - `Name` trait for structures that has `name` field diff --git a/svd-rs/src/cluster.rs b/svd-rs/src/cluster.rs index 5ebf0825..b611eee3 100644 --- a/svd-rs/src/cluster.rs +++ b/svd-rs/src/cluster.rs @@ -1,4 +1,315 @@ -use super::{array::SingleArray, ClusterInfo}; +use super::{ + array::SingleArray, + registercluster::{ + AllRegistersIter, AllRegistersIterMut, ClusterIter, ClusterIterMut, RegisterIter, + RegisterIterMut, + }, + BuildError, DimElement, EmptyToNone, Name, Register, RegisterCluster, RegisterProperties, + SvdError, ValidateLevel, +}; /// Cluster describes a sequence of neighboring registers within a peripheral. pub type Cluster = SingleArray; + +/// Errors from [`ClusterInfo::validate`] +#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)] +pub enum Error { + /// The cluster can not be empty + #[error("Cluster must contain at least one Register or Cluster")] + EmptyCluster, +} + +/// Description of a cluster +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(rename_all = "camelCase") +)] +#[derive(Clone, Debug, PartialEq)] +#[non_exhaustive] +pub struct ClusterInfo { + /// String to identify the cluster. + /// Cluster names are required to be unique within the scope of a peripheral + pub name: String, + + /// String describing the details of the register cluster + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub description: Option, + + /// Specify the name of the original cluster if this cluster provides an alternative description + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub alternate_cluster: Option, + + /// Specify the struct type name created in the device header file + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub header_struct_name: Option, + + /// Cluster address relative to the `baseAddress` of the peripheral + pub address_offset: u32, + + /// Default properties for all registers + #[cfg_attr(feature = "serde", serde(flatten))] + pub default_register_properties: RegisterProperties, + + /// Children/members of the cluster + pub children: Vec, + + /// Specify the cluster name from which to inherit data. + /// Elements specified subsequently override inherited values + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub derived_from: Option, +} + +/// Builder for [`ClusterInfo`] +#[derive(Clone, Debug, Default, PartialEq)] +pub struct ClusterInfoBuilder { + name: Option, + description: Option, + alternate_cluster: Option, + header_struct_name: Option, + address_offset: Option, + default_register_properties: RegisterProperties, + children: Option>, + derived_from: Option, +} + +impl From for ClusterInfoBuilder { + fn from(c: ClusterInfo) -> Self { + Self { + name: Some(c.name), + description: c.description, + alternate_cluster: c.alternate_cluster, + header_struct_name: c.header_struct_name, + address_offset: Some(c.address_offset), + default_register_properties: c.default_register_properties, + children: Some(c.children), + derived_from: c.derived_from, + } + } +} + +impl ClusterInfoBuilder { + /// Set the name of the cluster. + pub fn name(mut self, value: String) -> Self { + self.name = Some(value); + self + } + /// Set the description of the cluster. + pub fn description(mut self, value: Option) -> Self { + self.description = value; + self + } + /// Set the alternate cluster. + pub fn alternate_cluster(mut self, value: Option) -> Self { + self.alternate_cluster = value; + self + } + /// Set the struct type name of the cluster. If not specified, the name of the cluster should be used. + pub fn header_struct_name(mut self, value: Option) -> Self { + self.header_struct_name = value; + self + } + /// Set the address_offset of the cluster, relative to the [`baseAddress`](crate::Peripheral::base_address) of the peripheral. + pub fn address_offset(mut self, value: u32) -> Self { + self.address_offset = Some(value); + self + } + /// Set the default_register_properties of the cluster. + pub fn default_register_properties(mut self, value: RegisterProperties) -> Self { + self.default_register_properties = value; + self + } + /// Set the children of the cluster. + pub fn children(mut self, value: Vec) -> Self { + self.children = Some(value); + self + } + /// Set the derived_from of the cluster. + pub fn derived_from(mut self, value: Option) -> Self { + self.derived_from = value; + self + } + /// Validate and build a [`ClusterInfo`]. + pub fn build(self, lvl: ValidateLevel) -> Result { + let mut cluster = ClusterInfo { + name: self + .name + .ok_or_else(|| BuildError::Uninitialized("name".to_string()))?, + description: self.description.empty_to_none(), + alternate_cluster: self.alternate_cluster.empty_to_none(), + header_struct_name: self.header_struct_name.empty_to_none(), + address_offset: self + .address_offset + .ok_or_else(|| BuildError::Uninitialized("address_offset".to_string()))?, + default_register_properties: self.default_register_properties.build(lvl)?, + children: self + .children + .ok_or_else(|| BuildError::Uninitialized("children".to_string()))?, + derived_from: self.derived_from, + }; + if !lvl.is_disabled() { + cluster.validate(lvl)?; + } + Ok(cluster) + } +} + +impl ClusterInfo { + /// Make a builder for [`ClusterInfo`] + pub fn builder() -> ClusterInfoBuilder { + ClusterInfoBuilder::default() + } + /// Construct single [`Cluster`] + pub const fn single(self) -> Cluster { + Cluster::Single(self) + } + /// Construct [`Cluster`] array + pub const fn array(self, dim: DimElement) -> Cluster { + Cluster::Array(self, dim) + } + /// Modify an existing [`ClusterInfo`] based on a [builder](ClusterInfoBuilder). + pub fn modify_from( + &mut self, + builder: ClusterInfoBuilder, + lvl: ValidateLevel, + ) -> Result<(), SvdError> { + if let Some(name) = builder.name { + self.name = name; + } + if builder.description.is_some() { + self.description = builder.description.empty_to_none(); + } + if builder.alternate_cluster.is_some() { + self.alternate_cluster = builder.alternate_cluster.empty_to_none(); + } + if builder.header_struct_name.is_some() { + self.header_struct_name = builder.header_struct_name.empty_to_none(); + } + if let Some(address_offset) = builder.address_offset { + self.address_offset = address_offset; + } + if builder.derived_from.is_some() { + self.derived_from = builder.derived_from; + self.children = Vec::new(); + self.default_register_properties = RegisterProperties::default(); + } else { + self.default_register_properties + .modify_from(builder.default_register_properties, lvl)?; + if let Some(children) = builder.children { + self.children = children; + } + } + if !lvl.is_disabled() { + self.validate(lvl) + } else { + Ok(()) + } + } + + /// Validate the [`ClusterInfo`] + pub fn validate(&mut self, lvl: ValidateLevel) -> Result<(), SvdError> { + if lvl.is_strict() { + super::check_dimable_name(&self.name, "name")?; + } + if let Some(name) = self.derived_from.as_ref() { + if lvl.is_strict() { + super::check_derived_name(name, "derivedFrom")?; + } + } else if self.children.is_empty() && lvl.is_strict() { + return Err(Error::EmptyCluster.into()); + } + Ok(()) + } + + /// Returns iterator over all descendant registers + #[deprecated(since = "0.12.1", note = "Please use `all_registers` instead")] + pub fn reg_iter(&self) -> AllRegistersIter { + self.all_registers() + } + + /// Returns iterator over all descendant registers + pub fn all_registers(&self) -> AllRegistersIter { + AllRegistersIter { + rem: self.children.iter().rev().collect(), + } + } + + /// Returns mutable iterator over all descendant registers + #[deprecated(since = "0.12.1", note = "Please use `all_registers_mut` instead")] + pub fn reg_iter_mut(&mut self) -> AllRegistersIterMut { + self.all_registers_mut() + } + + /// Returns mutable iterator over all descendant registers + pub fn all_registers_mut(&mut self) -> AllRegistersIterMut { + AllRegistersIterMut { + rem: self.children.iter_mut().rev().collect(), + } + } + + /// Returns iterator over child registers + pub fn registers(&self) -> RegisterIter { + RegisterIter { + all: self.children.iter(), + } + } + + /// Returns mutable iterator over child registers + pub fn registers_mut(&mut self) -> RegisterIterMut { + RegisterIterMut { + all: self.children.iter_mut(), + } + } + + /// Returns iterator over child clusters + pub fn clusters(&self) -> ClusterIter { + ClusterIter { + all: self.children.iter(), + } + } + + /// Returns mutable iterator over child clusters + pub fn clusters_mut(&mut self) -> ClusterIterMut { + ClusterIterMut { + all: self.children.iter_mut(), + } + } + + /// Get register by name + pub fn get_register(&self, name: &str) -> Option<&Register> { + self.registers().find(|f| f.name == name) + } + + /// Get mutable register by name + pub fn get_mut_register(&mut self, name: &str) -> Option<&mut Register> { + self.registers_mut().find(|f| f.name == name) + } + + /// Get cluster by name + pub fn get_cluster(&self, name: &str) -> Option<&Cluster> { + self.clusters().find(|f| f.name == name) + } + + /// Get mutable cluster by name + pub fn get_mut_cluster(&mut self, name: &str) -> Option<&mut Cluster> { + self.clusters_mut().find(|f| f.name == name) + } +} + +impl Name for ClusterInfo { + fn name(&self) -> &str { + &self.name + } +} diff --git a/svd-rs/src/clusterinfo.rs b/svd-rs/src/clusterinfo.rs deleted file mode 100644 index 371f9410..00000000 --- a/svd-rs/src/clusterinfo.rs +++ /dev/null @@ -1,311 +0,0 @@ -use super::{ - registercluster::{ - AllRegistersIter, AllRegistersIterMut, ClusterIter, ClusterIterMut, RegisterIter, - RegisterIterMut, - }, - BuildError, Cluster, DimElement, EmptyToNone, Name, Register, RegisterCluster, - RegisterProperties, SvdError, ValidateLevel, -}; - -/// Errors from [`ClusterInfo::validate`] -#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)] -pub enum Error { - /// The cluster can not be empty - #[error("Cluster must contain at least one Register or Cluster")] - EmptyCluster, -} - -/// Description of a cluster -#[cfg_attr( - feature = "serde", - derive(serde::Deserialize, serde::Serialize), - serde(rename_all = "camelCase") -)] -#[derive(Clone, Debug, PartialEq)] -#[non_exhaustive] -pub struct ClusterInfo { - /// String to identify the cluster. - /// Cluster names are required to be unique within the scope of a peripheral - pub name: String, - - /// String describing the details of the register cluster - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub description: Option, - - /// Specify the name of the original cluster if this cluster provides an alternative description - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub alternate_cluster: Option, - - /// Specify the struct type name created in the device header file - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub header_struct_name: Option, - - /// Cluster address relative to the `baseAddress` of the peripheral - pub address_offset: u32, - - /// Default properties for all registers - #[cfg_attr(feature = "serde", serde(flatten))] - pub default_register_properties: RegisterProperties, - - /// Children/members of the cluster - pub children: Vec, - - /// Specify the cluster name from which to inherit data. - /// Elements specified subsequently override inherited values - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub derived_from: Option, -} - -/// Builder for [`ClusterInfo`] -#[derive(Clone, Debug, Default, PartialEq)] -pub struct ClusterInfoBuilder { - name: Option, - description: Option, - alternate_cluster: Option, - header_struct_name: Option, - address_offset: Option, - default_register_properties: RegisterProperties, - children: Option>, - derived_from: Option, -} - -impl From for ClusterInfoBuilder { - fn from(c: ClusterInfo) -> Self { - Self { - name: Some(c.name), - description: c.description, - alternate_cluster: c.alternate_cluster, - header_struct_name: c.header_struct_name, - address_offset: Some(c.address_offset), - default_register_properties: c.default_register_properties, - children: Some(c.children), - derived_from: c.derived_from, - } - } -} - -impl ClusterInfoBuilder { - /// Set the name of the cluster. - pub fn name(mut self, value: String) -> Self { - self.name = Some(value); - self - } - /// Set the description of the cluster. - pub fn description(mut self, value: Option) -> Self { - self.description = value; - self - } - /// Set the alternate cluster. - pub fn alternate_cluster(mut self, value: Option) -> Self { - self.alternate_cluster = value; - self - } - /// Set the struct type name of the cluster. If not specified, the name of the cluster should be used. - pub fn header_struct_name(mut self, value: Option) -> Self { - self.header_struct_name = value; - self - } - /// Set the address_offset of the cluster, relative to the [`baseAddress`](crate::Peripheral::base_address) of the peripheral. - pub fn address_offset(mut self, value: u32) -> Self { - self.address_offset = Some(value); - self - } - /// Set the default_register_properties of the cluster. - pub fn default_register_properties(mut self, value: RegisterProperties) -> Self { - self.default_register_properties = value; - self - } - /// Set the children of the cluster. - pub fn children(mut self, value: Vec) -> Self { - self.children = Some(value); - self - } - /// Set the derived_from of the cluster. - pub fn derived_from(mut self, value: Option) -> Self { - self.derived_from = value; - self - } - /// Validate and build a [`ClusterInfo`]. - pub fn build(self, lvl: ValidateLevel) -> Result { - let mut cluster = ClusterInfo { - name: self - .name - .ok_or_else(|| BuildError::Uninitialized("name".to_string()))?, - description: self.description.empty_to_none(), - alternate_cluster: self.alternate_cluster.empty_to_none(), - header_struct_name: self.header_struct_name.empty_to_none(), - address_offset: self - .address_offset - .ok_or_else(|| BuildError::Uninitialized("address_offset".to_string()))?, - default_register_properties: self.default_register_properties.build(lvl)?, - children: self - .children - .ok_or_else(|| BuildError::Uninitialized("children".to_string()))?, - derived_from: self.derived_from, - }; - if !lvl.is_disabled() { - cluster.validate(lvl)?; - } - Ok(cluster) - } -} - -impl ClusterInfo { - /// Make a builder for [`ClusterInfo`] - pub fn builder() -> ClusterInfoBuilder { - ClusterInfoBuilder::default() - } - /// Construct single [`Cluster`] - pub const fn single(self) -> Cluster { - Cluster::Single(self) - } - /// Construct [`Cluster`] array - pub const fn array(self, dim: DimElement) -> Cluster { - Cluster::Array(self, dim) - } - /// Modify an existing [`ClusterInfo`] based on a [builder](ClusterInfoBuilder). - pub fn modify_from( - &mut self, - builder: ClusterInfoBuilder, - lvl: ValidateLevel, - ) -> Result<(), SvdError> { - if let Some(name) = builder.name { - self.name = name; - } - if builder.description.is_some() { - self.description = builder.description.empty_to_none(); - } - if builder.alternate_cluster.is_some() { - self.alternate_cluster = builder.alternate_cluster.empty_to_none(); - } - if builder.header_struct_name.is_some() { - self.header_struct_name = builder.header_struct_name.empty_to_none(); - } - if let Some(address_offset) = builder.address_offset { - self.address_offset = address_offset; - } - if builder.derived_from.is_some() { - self.derived_from = builder.derived_from; - self.children = Vec::new(); - self.default_register_properties = RegisterProperties::default(); - } else { - self.default_register_properties - .modify_from(builder.default_register_properties, lvl)?; - if let Some(children) = builder.children { - self.children = children; - } - } - if !lvl.is_disabled() { - self.validate(lvl) - } else { - Ok(()) - } - } - - /// Validate the [`ClusterInfo`] - pub fn validate(&mut self, lvl: ValidateLevel) -> Result<(), SvdError> { - if lvl.is_strict() { - super::check_dimable_name(&self.name, "name")?; - } - if let Some(name) = self.derived_from.as_ref() { - if lvl.is_strict() { - super::check_derived_name(name, "derivedFrom")?; - } - } else if self.children.is_empty() && lvl.is_strict() { - return Err(Error::EmptyCluster.into()); - } - Ok(()) - } - - /// Returns iterator over all descendant registers - #[deprecated(since = "0.12.1", note = "Please use `all_registers` instead")] - pub fn reg_iter(&self) -> AllRegistersIter { - self.all_registers() - } - - /// Returns iterator over all descendant registers - pub fn all_registers(&self) -> AllRegistersIter { - AllRegistersIter { - rem: self.children.iter().rev().collect(), - } - } - - /// Returns mutable iterator over all descendant registers - #[deprecated(since = "0.12.1", note = "Please use `all_registers_mut` instead")] - pub fn reg_iter_mut(&mut self) -> AllRegistersIterMut { - self.all_registers_mut() - } - - /// Returns mutable iterator over all descendant registers - pub fn all_registers_mut(&mut self) -> AllRegistersIterMut { - AllRegistersIterMut { - rem: self.children.iter_mut().rev().collect(), - } - } - - /// Returns iterator over child registers - pub fn registers(&self) -> RegisterIter { - RegisterIter { - all: self.children.iter(), - } - } - - /// Returns mutable iterator over child registers - pub fn registers_mut(&mut self) -> RegisterIterMut { - RegisterIterMut { - all: self.children.iter_mut(), - } - } - - /// Returns iterator over child clusters - pub fn clusters(&self) -> ClusterIter { - ClusterIter { - all: self.children.iter(), - } - } - - /// Returns mutable iterator over child clusters - pub fn clusters_mut(&mut self) -> ClusterIterMut { - ClusterIterMut { - all: self.children.iter_mut(), - } - } - - /// Get register by name - pub fn get_register(&self, name: &str) -> Option<&Register> { - self.registers().find(|f| f.name == name) - } - - /// Get mutable register by name - pub fn get_mut_register(&mut self, name: &str) -> Option<&mut Register> { - self.registers_mut().find(|f| f.name == name) - } - - /// Get cluster by name - pub fn get_cluster(&self, name: &str) -> Option<&Cluster> { - self.clusters().find(|f| f.name == name) - } - - /// Get mutable cluster by name - pub fn get_mut_cluster(&mut self, name: &str) -> Option<&mut Cluster> { - self.clusters_mut().find(|f| f.name == name) - } -} - -impl Name for ClusterInfo { - fn name(&self) -> &str { - &self.name - } -} diff --git a/svd-rs/src/field.rs b/svd-rs/src/field.rs index 357d8f4a..b1507af4 100644 --- a/svd-rs/src/field.rs +++ b/svd-rs/src/field.rs @@ -1,4 +1,360 @@ -use super::{array::SingleArray, FieldInfo}; +use super::{ + array::SingleArray, bitrange, Access, BitRange, BuildError, DimElement, EmptyToNone, + EnumeratedValues, ModifiedWriteValues, Name, ReadAction, SvdError, Usage, ValidateLevel, + WriteConstraint, +}; /// Describes a field or fields of a [register](crate::RegisterInfo). pub type Field = SingleArray; + +/// Errors for [`FieldInfo::validate`] +#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)] +pub enum Error { + /// The enumerated value is not recognized by svd-rs. + #[error("You can have 0, 1 or 2 enumeratedValues with different usage")] + IncompatibleEnumeratedValues, +} + +/// A partition of a [register](crate::RegisterInfo) +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[derive(Clone, Debug, PartialEq)] +#[non_exhaustive] +pub struct FieldInfo { + /// Name string used to identify the field. + /// Field names must be unique within a register + pub name: String, + + /// String describing the details of the register + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub description: Option, + + /// Bit position of the field within the register + #[cfg_attr(feature = "serde", serde(flatten))] + pub bit_range: BitRange, + + /// Predefined strings set the access type. + /// The element can be omitted if access rights get inherited from parent elements + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub access: Option, + + /// Describe the manipulation of data written to a field. + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub modified_write_values: Option, + + /// Specifies the subset of allowed write values + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub write_constraint: Option, + + /// If set, it specifies the side effect following a read operation. + /// If not set, the field is not modified + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub read_action: Option, + + /// Describes the field + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] + pub enumerated_values: Vec, + + /// Specify the field name from which to inherit data. + /// Elements specified subsequently override inherited values + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub derived_from: Option, +} + +/// Builder for [`FieldInfo`] + +#[derive(Clone, Debug, Default, PartialEq)] +pub struct FieldInfoBuilder { + name: Option, + description: Option, + bit_range: Option, + bit_offset: Option, + bit_width: Option, + access: Option, + modified_write_values: Option, + write_constraint: Option, + read_action: Option, + enumerated_values: Option>, + derived_from: Option, +} + +impl From for FieldInfoBuilder { + fn from(f: FieldInfo) -> Self { + Self { + name: Some(f.name), + description: f.description, + bit_range: Some(f.bit_range), + bit_offset: None, + bit_width: None, + access: f.access, + modified_write_values: f.modified_write_values, + write_constraint: f.write_constraint, + read_action: f.read_action, + enumerated_values: Some(f.enumerated_values), + derived_from: f.derived_from, + } + } +} + +impl FieldInfoBuilder { + /// Set the name of the field + pub fn name(mut self, value: String) -> Self { + self.name = Some(value); + self + } + /// Set the description of the field + pub fn description(mut self, value: Option) -> Self { + self.description = value; + self + } + /// Set the bit range of the field + pub fn bit_range(mut self, value: BitRange) -> Self { + self.bit_range = Some(value); + self.bit_offset = None; + self.bit_width = None; + self + } + /// Set the bit offset of the field + pub fn bit_offset(mut self, value: u32) -> Self { + if let Some(bit_range) = self.bit_range.as_mut() { + bit_range.offset = value; + } else if let Some(width) = self.bit_offset { + self.bit_range = Some(BitRange::from_offset_width(value, width)); + self.bit_width = None; + } else { + self.bit_offset = Some(value); + } + self + } + /// Set the bit width of the field + pub fn bit_width(mut self, value: u32) -> Self { + if let Some(bit_range) = self.bit_range.as_mut() { + bit_range.width = value; + } else if let Some(offset) = self.bit_offset { + self.bit_range = Some(BitRange::from_offset_width(offset, value)); + self.bit_offset = None; + } else { + self.bit_width = Some(value); + } + self + } + /// Set the access of the field + pub fn access(mut self, value: Option) -> Self { + self.access = value; + self + } + /// Set the modified write values of the field + pub fn modified_write_values(mut self, value: Option) -> Self { + self.modified_write_values = value; + self + } + /// Set the write constraint of the field + pub fn write_constraint(mut self, value: Option) -> Self { + self.write_constraint = value; + self + } + /// Set the read action of the register. + pub fn read_action(mut self, value: Option) -> Self { + self.read_action = value; + self + } + /// Set the enumerated values of the field + pub fn enumerated_values(mut self, value: Vec) -> Self { + self.enumerated_values = Some(value); + self + } + /// Set the derived_from attribute of the field + pub fn derived_from(mut self, value: Option) -> Self { + self.derived_from = value; + self + } + /// Validate and build a [`FieldInfo`]. + pub fn build(self, lvl: ValidateLevel) -> Result { + let mut field = FieldInfo { + name: self + .name + .ok_or_else(|| BuildError::Uninitialized("name".to_string()))?, + description: self.description.empty_to_none(), + bit_range: self + .bit_range + .ok_or_else(|| BuildError::Uninitialized("bit_range".to_string()))?, + access: self.access, + modified_write_values: self.modified_write_values, + write_constraint: self.write_constraint, + read_action: self.read_action, + enumerated_values: self.enumerated_values.unwrap_or_default(), + derived_from: self.derived_from, + }; + if !lvl.is_disabled() { + field.validate(lvl)?; + } + Ok(field) + } +} + +impl FieldInfo { + /// Make a builder for [`FieldInfo`] + pub fn builder() -> FieldInfoBuilder { + FieldInfoBuilder::default() + } + /// Construct single [`Field`] + pub const fn single(self) -> Field { + Field::Single(self) + } + /// Construct [`Field`] array + pub const fn array(self, dim: DimElement) -> Field { + Field::Array(self, dim) + } + /// Modify an existing [`FieldInfo`] based on a [builder](FieldInfoBuilder). + pub fn modify_from( + &mut self, + builder: FieldInfoBuilder, + lvl: ValidateLevel, + ) -> Result<(), SvdError> { + if let Some(name) = builder.name { + self.name = name; + } + if builder.description.is_some() { + self.description = builder.description.empty_to_none(); + } + if let Some(bit_range) = builder.bit_range { + self.bit_range = bit_range; + } + if let Some(offset) = builder.bit_offset { + self.bit_range.offset = offset; + } + if let Some(width) = builder.bit_width { + self.bit_range.width = width; + } + if builder.access.is_some() { + self.access = builder.access; + } + if builder.derived_from.is_some() { + self.derived_from = builder.derived_from; + self.modified_write_values = None; + self.write_constraint = None; + self.enumerated_values = Vec::new(); + } else { + if builder.modified_write_values.is_some() { + self.modified_write_values = builder.modified_write_values; + } + if builder.write_constraint.is_some() { + self.write_constraint = builder.write_constraint; + } + if builder.read_action.is_some() { + self.read_action = builder.read_action; + } + if let Some(enumerated_values) = builder.enumerated_values { + self.enumerated_values = enumerated_values; + } + } + if !lvl.is_disabled() { + self.validate(lvl) + } else { + Ok(()) + } + } + /// Validate the [`FieldInfo`]. + pub fn validate(&mut self, lvl: ValidateLevel) -> Result<(), SvdError> { + if lvl.is_strict() { + super::check_dimable_name(&self.name, "name")?; + if let Some(name) = self.derived_from.as_ref() { + super::check_derived_name(name, "derivedFrom")?; + } + } + + if self.bit_range.width == 0 { + return Err(bitrange::Error::ZeroWidth.into()); + } + + // If the bit_range has its maximum width, all enumerated values will of + // course fit in so we can skip validation. + if self.bit_range.width < 64 { + for ev in &self.enumerated_values { + ev.check_range(0..2_u64.pow(self.bit_range.width))?; + } + } + + if lvl.is_strict() { + match self.enumerated_values.as_slice() { + [] | [_] => {} + [ev1, ev2] + if matches!(ev1.usage(), None | Some(Usage::Read)) + && matches!(ev2.usage(), None | Some(Usage::Write)) => {} + [ev1, ev2] + if matches!(ev2.usage(), None | Some(Usage::Read)) + && matches!(ev1.usage(), None | Some(Usage::Write)) => {} + _ => return Err(Error::IncompatibleEnumeratedValues.into()), + } + } + Ok(()) + } + + /// Get bit offset + pub fn bit_offset(&self) -> u32 { + self.bit_range.offset + } + + /// Get bit width + pub fn bit_width(&self) -> u32 { + self.bit_range.width + } + + /// Get the position of the least significant bit + pub fn lsb(&self) -> u32 { + self.bit_range.lsb() + } + /// Get the position of the most significant bit + pub fn msb(&self) -> u32 { + self.bit_range.msb() + } + + /// Get enumeratedValues cluster by usage + pub fn get_enumerated_values(&self, usage: Usage) -> Option<&EnumeratedValues> { + match self.enumerated_values.len() { + 1 | 2 => self + .enumerated_values + .iter() + .find(|ev| ev.usage() == Some(usage)), + _ => None, + } + } + + /// Get mutable enumeratedValues by usage + pub fn get_mut_enumerated_values(&mut self, usage: Usage) -> Option<&mut EnumeratedValues> { + match self.enumerated_values.len() { + 1 | 2 => self + .enumerated_values + .iter_mut() + .find(|ev| ev.usage() == Some(usage)), + _ => None, + } + } +} + +impl Name for FieldInfo { + fn name(&self) -> &str { + &self.name + } +} diff --git a/svd-rs/src/fieldinfo.rs b/svd-rs/src/fieldinfo.rs deleted file mode 100644 index e021919a..00000000 --- a/svd-rs/src/fieldinfo.rs +++ /dev/null @@ -1,356 +0,0 @@ -use super::{ - bitrange, Access, BitRange, BuildError, DimElement, EmptyToNone, EnumeratedValues, Field, - ModifiedWriteValues, Name, ReadAction, SvdError, Usage, ValidateLevel, WriteConstraint, -}; - -/// Errors for [`FieldInfo::validate`] -#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)] -pub enum Error { - /// The enumerated value is not recognized by svd-rs. - #[error("You can have 0, 1 or 2 enumeratedValues with different usage")] - IncompatibleEnumeratedValues, -} - -/// A partition of a [register](crate::RegisterInfo) -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] -#[derive(Clone, Debug, PartialEq)] -#[non_exhaustive] -pub struct FieldInfo { - /// Name string used to identify the field. - /// Field names must be unique within a register - pub name: String, - - /// String describing the details of the register - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub description: Option, - - /// Bit position of the field within the register - #[cfg_attr(feature = "serde", serde(flatten))] - pub bit_range: BitRange, - - /// Predefined strings set the access type. - /// The element can be omitted if access rights get inherited from parent elements - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub access: Option, - - /// Describe the manipulation of data written to a field. - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub modified_write_values: Option, - - /// Specifies the subset of allowed write values - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub write_constraint: Option, - - /// If set, it specifies the side effect following a read operation. - /// If not set, the field is not modified - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub read_action: Option, - - /// Describes the field - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Vec::is_empty") - )] - pub enumerated_values: Vec, - - /// Specify the field name from which to inherit data. - /// Elements specified subsequently override inherited values - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub derived_from: Option, -} - -/// Builder for [`FieldInfo`] - -#[derive(Clone, Debug, Default, PartialEq)] -pub struct FieldInfoBuilder { - name: Option, - description: Option, - bit_range: Option, - bit_offset: Option, - bit_width: Option, - access: Option, - modified_write_values: Option, - write_constraint: Option, - read_action: Option, - enumerated_values: Option>, - derived_from: Option, -} - -impl From for FieldInfoBuilder { - fn from(f: FieldInfo) -> Self { - Self { - name: Some(f.name), - description: f.description, - bit_range: Some(f.bit_range), - bit_offset: None, - bit_width: None, - access: f.access, - modified_write_values: f.modified_write_values, - write_constraint: f.write_constraint, - read_action: f.read_action, - enumerated_values: Some(f.enumerated_values), - derived_from: f.derived_from, - } - } -} - -impl FieldInfoBuilder { - /// Set the name of the field - pub fn name(mut self, value: String) -> Self { - self.name = Some(value); - self - } - /// Set the description of the field - pub fn description(mut self, value: Option) -> Self { - self.description = value; - self - } - /// Set the bit range of the field - pub fn bit_range(mut self, value: BitRange) -> Self { - self.bit_range = Some(value); - self.bit_offset = None; - self.bit_width = None; - self - } - /// Set the bit offset of the field - pub fn bit_offset(mut self, value: u32) -> Self { - if let Some(bit_range) = self.bit_range.as_mut() { - bit_range.offset = value; - } else if let Some(width) = self.bit_offset { - self.bit_range = Some(BitRange::from_offset_width(value, width)); - self.bit_width = None; - } else { - self.bit_offset = Some(value); - } - self - } - /// Set the bit width of the field - pub fn bit_width(mut self, value: u32) -> Self { - if let Some(bit_range) = self.bit_range.as_mut() { - bit_range.width = value; - } else if let Some(offset) = self.bit_offset { - self.bit_range = Some(BitRange::from_offset_width(offset, value)); - self.bit_offset = None; - } else { - self.bit_width = Some(value); - } - self - } - /// Set the access of the field - pub fn access(mut self, value: Option) -> Self { - self.access = value; - self - } - /// Set the modified write values of the field - pub fn modified_write_values(mut self, value: Option) -> Self { - self.modified_write_values = value; - self - } - /// Set the write constraint of the field - pub fn write_constraint(mut self, value: Option) -> Self { - self.write_constraint = value; - self - } - /// Set the read action of the register. - pub fn read_action(mut self, value: Option) -> Self { - self.read_action = value; - self - } - /// Set the enumerated values of the field - pub fn enumerated_values(mut self, value: Vec) -> Self { - self.enumerated_values = Some(value); - self - } - /// Set the derived_from attribute of the field - pub fn derived_from(mut self, value: Option) -> Self { - self.derived_from = value; - self - } - /// Validate and build a [`FieldInfo`]. - pub fn build(self, lvl: ValidateLevel) -> Result { - let mut field = FieldInfo { - name: self - .name - .ok_or_else(|| BuildError::Uninitialized("name".to_string()))?, - description: self.description.empty_to_none(), - bit_range: self - .bit_range - .ok_or_else(|| BuildError::Uninitialized("bit_range".to_string()))?, - access: self.access, - modified_write_values: self.modified_write_values, - write_constraint: self.write_constraint, - read_action: self.read_action, - enumerated_values: self.enumerated_values.unwrap_or_default(), - derived_from: self.derived_from, - }; - if !lvl.is_disabled() { - field.validate(lvl)?; - } - Ok(field) - } -} - -impl FieldInfo { - /// Make a builder for [`FieldInfo`] - pub fn builder() -> FieldInfoBuilder { - FieldInfoBuilder::default() - } - /// Construct single [`Field`] - pub const fn single(self) -> Field { - Field::Single(self) - } - /// Construct [`Field`] array - pub const fn array(self, dim: DimElement) -> Field { - Field::Array(self, dim) - } - /// Modify an existing [`FieldInfo`] based on a [builder](FieldInfoBuilder). - pub fn modify_from( - &mut self, - builder: FieldInfoBuilder, - lvl: ValidateLevel, - ) -> Result<(), SvdError> { - if let Some(name) = builder.name { - self.name = name; - } - if builder.description.is_some() { - self.description = builder.description.empty_to_none(); - } - if let Some(bit_range) = builder.bit_range { - self.bit_range = bit_range; - } - if let Some(offset) = builder.bit_offset { - self.bit_range.offset = offset; - } - if let Some(width) = builder.bit_width { - self.bit_range.width = width; - } - if builder.access.is_some() { - self.access = builder.access; - } - if builder.derived_from.is_some() { - self.derived_from = builder.derived_from; - self.modified_write_values = None; - self.write_constraint = None; - self.enumerated_values = Vec::new(); - } else { - if builder.modified_write_values.is_some() { - self.modified_write_values = builder.modified_write_values; - } - if builder.write_constraint.is_some() { - self.write_constraint = builder.write_constraint; - } - if builder.read_action.is_some() { - self.read_action = builder.read_action; - } - if let Some(enumerated_values) = builder.enumerated_values { - self.enumerated_values = enumerated_values; - } - } - if !lvl.is_disabled() { - self.validate(lvl) - } else { - Ok(()) - } - } - /// Validate the [`FieldInfo`]. - pub fn validate(&mut self, lvl: ValidateLevel) -> Result<(), SvdError> { - if lvl.is_strict() { - super::check_dimable_name(&self.name, "name")?; - if let Some(name) = self.derived_from.as_ref() { - super::check_derived_name(name, "derivedFrom")?; - } - } - - if self.bit_range.width == 0 { - return Err(bitrange::Error::ZeroWidth.into()); - } - - // If the bit_range has its maximum width, all enumerated values will of - // course fit in so we can skip validation. - if self.bit_range.width < 64 { - for ev in &self.enumerated_values { - ev.check_range(0..2_u64.pow(self.bit_range.width))?; - } - } - - if lvl.is_strict() { - match self.enumerated_values.as_slice() { - [] | [_] => {} - [ev1, ev2] - if matches!(ev1.usage(), None | Some(Usage::Read)) - && matches!(ev2.usage(), None | Some(Usage::Write)) => {} - [ev1, ev2] - if matches!(ev2.usage(), None | Some(Usage::Read)) - && matches!(ev1.usage(), None | Some(Usage::Write)) => {} - _ => return Err(Error::IncompatibleEnumeratedValues.into()), - } - } - Ok(()) - } - - /// Get bit offset - pub fn bit_offset(&self) -> u32 { - self.bit_range.offset - } - - /// Get bit width - pub fn bit_width(&self) -> u32 { - self.bit_range.width - } - - /// Get the position of the least significant bit - pub fn lsb(&self) -> u32 { - self.bit_range.lsb() - } - /// Get the position of the most significant bit - pub fn msb(&self) -> u32 { - self.bit_range.msb() - } - - /// Get enumeratedValues cluster by usage - pub fn get_enumerated_values(&self, usage: Usage) -> Option<&EnumeratedValues> { - match self.enumerated_values.len() { - 1 | 2 => self - .enumerated_values - .iter() - .find(|ev| ev.usage() == Some(usage)), - _ => None, - } - } - - /// Get mutable enumeratedValues by usage - pub fn get_mut_enumerated_values(&mut self, usage: Usage) -> Option<&mut EnumeratedValues> { - match self.enumerated_values.len() { - 1 | 2 => self - .enumerated_values - .iter_mut() - .find(|ev| ev.usage() == Some(usage)), - _ => None, - } - } -} - -impl Name for FieldInfo { - fn name(&self) -> &str { - &self.name - } -} diff --git a/svd-rs/src/lib.rs b/svd-rs/src/lib.rs index e51b9bf4..4f94c188 100644 --- a/svd-rs/src/lib.rs +++ b/svd-rs/src/lib.rs @@ -43,15 +43,7 @@ pub use self::enumeratedvalues::{EnumeratedValues, EnumeratedValuesBuilder}; /// Field objects pub mod field; -pub use self::field::Field; - -/// Field Info objects -pub mod fieldinfo; -pub use self::fieldinfo::{FieldInfo, FieldInfoBuilder}; - -/// Register Info objects -pub mod registerinfo; -pub use self::registerinfo::{RegisterInfo, RegisterInfoBuilder}; +pub use self::field::{Field, FieldInfo, FieldInfoBuilder}; /// Register Properties objects pub mod registerproperties; @@ -63,15 +55,11 @@ pub use self::addressblock::{AddressBlock, AddressBlockUsage}; /// Cluster objects pub mod cluster; -pub use self::cluster::Cluster; - -/// Cluster Info objects -pub mod clusterinfo; -pub use self::clusterinfo::{ClusterInfo, ClusterInfoBuilder}; +pub use self::cluster::{Cluster, ClusterInfo, ClusterInfoBuilder}; /// Register objects pub mod register; -pub use self::register::Register; +pub use self::register::{Register, RegisterInfo, RegisterInfoBuilder}; /// Register Cluster objects pub mod registercluster; @@ -83,11 +71,7 @@ pub use self::dimelement::{DimArrayIndex, DimElement, DimElementBuilder}; /// Peripheral objects pub mod peripheral; -pub use self::peripheral::Peripheral; - -/// Peripheral Info objects -pub mod peripheralinfo; -pub use self::peripheralinfo::{PeripheralInfo, PeripheralInfoBuilder}; +pub use self::peripheral::{Peripheral, PeripheralInfo, PeripheralInfoBuilder}; /// Device objects pub mod device; @@ -159,16 +143,16 @@ pub enum SvdError { Device(#[from] device::Error), /// Peripheral error #[error("`Peripheral error: {0}")] - Peripheral(#[from] peripheralinfo::Error), + Peripheral(#[from] peripheral::Error), /// Cluster error #[error("`Cluster error: {0}")] - Cluster(#[from] clusterinfo::Error), + Cluster(#[from] cluster::Error), /// Register error #[error("`Register error: {0}")] - Register(#[from] registerinfo::Error), + Register(#[from] register::Error), /// Field error #[error("`Field error: {0}")] - Field(#[from] fieldinfo::Error), + Field(#[from] field::Error), /// BitRange error #[error("`BitRange error: {0}")] BitRange(#[from] bitrange::Error), diff --git a/svd-rs/src/peripheral.rs b/svd-rs/src/peripheral.rs index 1c27f38d..6f3696ab 100644 --- a/svd-rs/src/peripheral.rs +++ b/svd-rs/src/peripheral.rs @@ -1,4 +1,474 @@ -use super::{array::SingleArray, PeripheralInfo}; +use super::{ + array::SingleArray, + registercluster::{ + AllRegistersIter, AllRegistersIterMut, ClusterIter, ClusterIterMut, RegisterIter, + RegisterIterMut, + }, + AddressBlock, BuildError, Cluster, DimElement, EmptyToNone, Interrupt, Name, Register, + RegisterCluster, RegisterProperties, SvdError, ValidateLevel, +}; /// A single peripheral or array of peripherals pub type Peripheral = SingleArray; + +/// Errors from [Peripheral::validate] +#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)] +pub enum Error { + /// The peripheral has no registers, but specified a `` tag. + #[error("Peripheral have `registers` tag, but it is empty")] + EmptyRegisters, +} + +/// A description of a peripheral in the [device](crate::Device), describing, for example, the [memory mappings](crate::RegisterInfo). +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(rename_all = "camelCase") +)] +#[derive(Clone, Debug, PartialEq)] +#[non_exhaustive] +pub struct PeripheralInfo { + /// The string identifies the peripheral. Peripheral names are required to be unique for a device + pub name: String, + + /// Specifies a register name without the restrictions of an ANSI C identifier. + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub display_name: Option, + + /// The string specifies the version of this peripheral description + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub version: Option, + + /// The string provides an overview of the purpose and functionality of the peripheral + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub description: Option, + + /// Specifies peripheral assigned to the same address blocks + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub alternate_peripheral: Option, + + /// Assigns this peripheral to a group of peripherals. This is only used bye the System View + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub group_name: Option, + + /// Define a string as prefix. All register names of this peripheral get this prefix + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub prepend_to_name: Option, + + /// Define a string as suffix. All register names of this peripheral get this suffix + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub append_to_name: Option, + + /// Specify the struct type name created in the device header file + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub header_struct_name: Option, + + /// Lowest address reserved or used by the peripheral + pub base_address: u64, + + /// Default properties for all registers + #[cfg_attr(feature = "serde", serde(flatten))] + pub default_register_properties: RegisterProperties, + + /// Specify an address range uniquely mapped to this peripheral + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub address_block: Option>, + + /// A peripheral can have multiple associated interrupts + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] + pub interrupt: Vec, + + /// Group to enclose register definitions. + /// `None` indicates that the `` node is not present + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub registers: Option>, + + /// Specify the peripheral name from which to inherit data. Elements specified subsequently override inherited values + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub derived_from: Option, +} + +/// Builder for [`Peripheral`] +#[derive(Clone, Debug, Default, PartialEq)] +pub struct PeripheralInfoBuilder { + name: Option, + display_name: Option, + version: Option, + description: Option, + alternate_peripheral: Option, + group_name: Option, + prepend_to_name: Option, + append_to_name: Option, + header_struct_name: Option, + base_address: Option, + default_register_properties: RegisterProperties, + address_block: Option>, + interrupt: Option>, + registers: Option>, + derived_from: Option, +} + +impl From for PeripheralInfoBuilder { + fn from(p: PeripheralInfo) -> Self { + Self { + name: Some(p.name), + display_name: p.display_name, + version: p.version, + description: p.description, + alternate_peripheral: p.alternate_peripheral, + group_name: p.group_name, + prepend_to_name: p.prepend_to_name, + append_to_name: p.append_to_name, + header_struct_name: p.header_struct_name, + base_address: Some(p.base_address), + default_register_properties: p.default_register_properties, + address_block: p.address_block, + interrupt: Some(p.interrupt), + registers: p.registers, + derived_from: p.derived_from, + } + } +} + +impl PeripheralInfoBuilder { + /// Set the name of the peripheral + pub fn name(mut self, value: String) -> Self { + self.name = Some(value); + self + } + /// Set the display name of the peripheral + pub fn display_name(mut self, value: Option) -> Self { + self.display_name = value; + self + } + /// Set the version of the peripheral + pub fn version(mut self, value: Option) -> Self { + self.version = value; + self + } + /// Set the description of the peripheral + pub fn description(mut self, value: Option) -> Self { + self.description = value; + self + } + /// Set the alternate peripheral + pub fn alternate_peripheral(mut self, value: Option) -> Self { + self.alternate_peripheral = value; + self + } + /// Set the group name of the peripheral + pub fn group_name(mut self, value: Option) -> Self { + self.group_name = value; + self + } + /// Set the prefix for names of all registers of the peripheral + pub fn prepend_to_name(mut self, value: Option) -> Self { + self.prepend_to_name = value; + self + } + /// Set the suffix for names of all registers of the peripheral + pub fn append_to_name(mut self, value: Option) -> Self { + self.append_to_name = value; + self + } + /// Set the header struct name of the peripheral + pub fn header_struct_name(mut self, value: Option) -> Self { + self.header_struct_name = value; + self + } + /// Set the base address of the peripheral + pub fn base_address(mut self, value: u64) -> Self { + self.base_address = Some(value); + self + } + /// Set the default register properties of the peripheral + pub fn default_register_properties(mut self, value: RegisterProperties) -> Self { + self.default_register_properties = value; + self + } + /// Set the address block of the peripheral + pub fn address_block(mut self, value: Option>) -> Self { + self.address_block = value; + self + } + /// Set the interrupts of the peripheral + pub fn interrupt(mut self, value: Option>) -> Self { + self.interrupt = value; + self + } + /// Set the registers of the peripheral + pub fn registers(mut self, value: Option>) -> Self { + self.registers = value; + self + } + /// Set the derived_from attribute of the peripheral + pub fn derived_from(mut self, value: Option) -> Self { + self.derived_from = value; + self + } + /// Validate and build a [`PeripheralInfo`]. + pub fn build(self, lvl: ValidateLevel) -> Result { + let mut per = PeripheralInfo { + name: self + .name + .ok_or_else(|| BuildError::Uninitialized("name".to_string()))?, + display_name: self.display_name.empty_to_none(), + version: self.version.empty_to_none(), + description: self.description.empty_to_none(), + alternate_peripheral: self.alternate_peripheral.empty_to_none(), + group_name: self.group_name.empty_to_none(), + prepend_to_name: self.prepend_to_name.empty_to_none(), + append_to_name: self.append_to_name.empty_to_none(), + header_struct_name: self.header_struct_name.empty_to_none(), + base_address: self + .base_address + .ok_or_else(|| BuildError::Uninitialized("base_address".to_string()))?, + default_register_properties: self.default_register_properties.build(lvl)?, + address_block: self.address_block, + interrupt: self.interrupt.unwrap_or_default(), + registers: self.registers, + derived_from: self.derived_from, + }; + if !lvl.is_disabled() { + per.validate(lvl)?; + } + Ok(per) + } +} + +impl PeripheralInfo { + /// Make a builder for [`PeripheralInfo`] + pub fn builder() -> PeripheralInfoBuilder { + PeripheralInfoBuilder::default() + } + /// Construct single [`Peripheral`] + pub const fn single(self) -> Peripheral { + Peripheral::Single(self) + } + /// Construct [`Peripheral`] array + pub const fn array(self, dim: DimElement) -> Peripheral { + Peripheral::Array(self, dim) + } + /// Modify an existing [`Peripheral`] based on a [builder](PeripheralInfoBuilder). + pub fn modify_from( + &mut self, + builder: PeripheralInfoBuilder, + lvl: ValidateLevel, + ) -> Result<(), SvdError> { + if let Some(name) = builder.name { + self.name = name; + } + if builder.display_name.is_some() { + self.display_name = builder.display_name.empty_to_none(); + } + if builder.version.is_some() { + self.version = builder.version.empty_to_none(); + } + if builder.description.is_some() { + self.description = builder.description.empty_to_none(); + } + if builder.alternate_peripheral.is_some() { + self.alternate_peripheral = builder.alternate_peripheral.empty_to_none(); + } + if builder.group_name.is_some() { + self.group_name = builder.group_name.empty_to_none(); + } + if builder.prepend_to_name.is_some() { + self.prepend_to_name = builder.prepend_to_name.empty_to_none(); + } + if builder.append_to_name.is_some() { + self.append_to_name = builder.append_to_name.empty_to_none(); + } + if builder.header_struct_name.is_some() { + self.header_struct_name = builder.header_struct_name.empty_to_none(); + } + if let Some(base_address) = builder.base_address { + self.base_address = base_address; + } + if let Some(interrupt) = builder.interrupt { + self.interrupt = interrupt; + } + if builder.derived_from.is_some() { + self.derived_from = builder.derived_from; + self.registers = None; + self.address_block = None; + self.default_register_properties = RegisterProperties::default(); + } else { + if builder.address_block.is_some() { + self.address_block = builder.address_block; + } + self.default_register_properties + .modify_from(builder.default_register_properties, lvl)?; + if builder.registers.is_some() { + self.registers = builder.registers.empty_to_none(); + } + } + if !lvl.is_disabled() { + self.validate(lvl) + } else { + Ok(()) + } + } + + /// Validate the [`Peripheral`] + pub fn validate(&mut self, lvl: ValidateLevel) -> Result<(), SvdError> { + // TODO + if lvl.is_strict() { + super::check_dimable_name(&self.name, "name")?; + } + if let Some(name) = self.derived_from.as_ref() { + if lvl.is_strict() { + super::check_dimable_name(name, "derivedFrom")?; + } + } else if let Some(registers) = self.registers.as_ref() { + if registers.is_empty() && lvl.is_strict() { + return Err(Error::EmptyRegisters.into()); + } + } + Ok(()) + } + + /// Returns iterator over child registers + pub fn registers(&self) -> RegisterIter { + RegisterIter { + all: match &self.registers { + Some(regs) => regs.iter(), + None => [].iter(), + }, + } + } + + /// Returns mutable iterator over child registers + pub fn registers_mut(&mut self) -> RegisterIterMut { + RegisterIterMut { + all: match &mut self.registers { + Some(regs) => regs.iter_mut(), + None => [].iter_mut(), + }, + } + } + + /// Returns iterator over child clusters + pub fn clusters(&self) -> ClusterIter { + ClusterIter { + all: match &self.registers { + Some(regs) => regs.iter(), + None => [].iter(), + }, + } + } + + /// Returns mutable iterator over child clusters + pub fn clusters_mut(&mut self) -> ClusterIterMut { + ClusterIterMut { + all: match &mut self.registers { + Some(regs) => regs.iter_mut(), + None => [].iter_mut(), + }, + } + } + + /// Returns iterator over all descendant registers + #[deprecated(since = "0.12.1", note = "Please use `all_registers` instead")] + pub fn reg_iter(&self) -> AllRegistersIter { + self.all_registers() + } + + /// Returns iterator over all descendant registers + pub fn all_registers(&self) -> AllRegistersIter { + AllRegistersIter { + rem: match &self.registers { + Some(regs) => regs.iter().rev().collect(), + None => Vec::new(), + }, + } + } + + /// Returns mutable iterator over all descendant registers + #[deprecated(since = "0.12.1", note = "Please use `all_registers_mut` instead")] + pub fn reg_iter_mut(&mut self) -> AllRegistersIterMut { + self.all_registers_mut() + } + + /// Returns mutable iterator over all descendant registers + pub fn all_registers_mut(&mut self) -> AllRegistersIterMut { + AllRegistersIterMut { + rem: match &mut self.registers { + Some(regs) => regs.iter_mut().rev().collect(), + None => Vec::new(), + }, + } + } + + /// Get register by name + pub fn get_register(&self, name: &str) -> Option<&Register> { + self.registers().find(|f| f.name == name) + } + + /// Get mutable register by name + pub fn get_mut_register(&mut self, name: &str) -> Option<&mut Register> { + self.registers_mut().find(|f| f.name == name) + } + + /// Get cluster by name + pub fn get_cluster(&self, name: &str) -> Option<&Cluster> { + self.clusters().find(|f| f.name == name) + } + + /// Get mutable cluster by name + pub fn get_mut_cluster(&mut self, name: &str) -> Option<&mut Cluster> { + self.clusters_mut().find(|f| f.name == name) + } + + /// Get interrupt by name + pub fn get_interrupt(&self, name: &str) -> Option<&Interrupt> { + self.interrupt.iter().find(|e| e.name == name) + } + + /// Get mutable enumeratedValue by name + pub fn get_mut_interrupt(&mut self, name: &str) -> Option<&mut Interrupt> { + self.interrupt.iter_mut().find(|e| e.name == name) + } +} + +impl Name for PeripheralInfo { + fn name(&self) -> &str { + &self.name + } +} diff --git a/svd-rs/src/peripheralinfo.rs b/svd-rs/src/peripheralinfo.rs deleted file mode 100644 index 80be73c2..00000000 --- a/svd-rs/src/peripheralinfo.rs +++ /dev/null @@ -1,470 +0,0 @@ -use super::{ - registercluster::{ - AllRegistersIter, AllRegistersIterMut, ClusterIter, ClusterIterMut, RegisterIter, - RegisterIterMut, - }, - AddressBlock, BuildError, Cluster, DimElement, EmptyToNone, Interrupt, Name, Peripheral, - Register, RegisterCluster, RegisterProperties, SvdError, ValidateLevel, -}; - -/// Errors from [Peripheral::validate] -#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)] -pub enum Error { - /// The peripheral has no registers, but specified a `` tag. - #[error("Peripheral have `registers` tag, but it is empty")] - EmptyRegisters, -} - -/// A description of a peripheral in the [device](crate::Device), describing, for example, the [memory mappings](crate::RegisterInfo). -#[cfg_attr( - feature = "serde", - derive(serde::Deserialize, serde::Serialize), - serde(rename_all = "camelCase") -)] -#[derive(Clone, Debug, PartialEq)] -#[non_exhaustive] -pub struct PeripheralInfo { - /// The string identifies the peripheral. Peripheral names are required to be unique for a device - pub name: String, - - /// Specifies a register name without the restrictions of an ANSI C identifier. - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub display_name: Option, - - /// The string specifies the version of this peripheral description - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub version: Option, - - /// The string provides an overview of the purpose and functionality of the peripheral - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub description: Option, - - /// Specifies peripheral assigned to the same address blocks - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub alternate_peripheral: Option, - - /// Assigns this peripheral to a group of peripherals. This is only used bye the System View - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub group_name: Option, - - /// Define a string as prefix. All register names of this peripheral get this prefix - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub prepend_to_name: Option, - - /// Define a string as suffix. All register names of this peripheral get this suffix - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub append_to_name: Option, - - /// Specify the struct type name created in the device header file - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub header_struct_name: Option, - - /// Lowest address reserved or used by the peripheral - pub base_address: u64, - - /// Default properties for all registers - #[cfg_attr(feature = "serde", serde(flatten))] - pub default_register_properties: RegisterProperties, - - /// Specify an address range uniquely mapped to this peripheral - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub address_block: Option>, - - /// A peripheral can have multiple associated interrupts - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Vec::is_empty") - )] - pub interrupt: Vec, - - /// Group to enclose register definitions. - /// `None` indicates that the `` node is not present - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub registers: Option>, - - /// Specify the peripheral name from which to inherit data. Elements specified subsequently override inherited values - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub derived_from: Option, -} - -/// Builder for [`Peripheral`] -#[derive(Clone, Debug, Default, PartialEq)] -pub struct PeripheralInfoBuilder { - name: Option, - display_name: Option, - version: Option, - description: Option, - alternate_peripheral: Option, - group_name: Option, - prepend_to_name: Option, - append_to_name: Option, - header_struct_name: Option, - base_address: Option, - default_register_properties: RegisterProperties, - address_block: Option>, - interrupt: Option>, - registers: Option>, - derived_from: Option, -} - -impl From for PeripheralInfoBuilder { - fn from(p: PeripheralInfo) -> Self { - Self { - name: Some(p.name), - display_name: p.display_name, - version: p.version, - description: p.description, - alternate_peripheral: p.alternate_peripheral, - group_name: p.group_name, - prepend_to_name: p.prepend_to_name, - append_to_name: p.append_to_name, - header_struct_name: p.header_struct_name, - base_address: Some(p.base_address), - default_register_properties: p.default_register_properties, - address_block: p.address_block, - interrupt: Some(p.interrupt), - registers: p.registers, - derived_from: p.derived_from, - } - } -} - -impl PeripheralInfoBuilder { - /// Set the name of the peripheral - pub fn name(mut self, value: String) -> Self { - self.name = Some(value); - self - } - /// Set the display name of the peripheral - pub fn display_name(mut self, value: Option) -> Self { - self.display_name = value; - self - } - /// Set the version of the peripheral - pub fn version(mut self, value: Option) -> Self { - self.version = value; - self - } - /// Set the description of the peripheral - pub fn description(mut self, value: Option) -> Self { - self.description = value; - self - } - /// Set the alternate peripheral - pub fn alternate_peripheral(mut self, value: Option) -> Self { - self.alternate_peripheral = value; - self - } - /// Set the group name of the peripheral - pub fn group_name(mut self, value: Option) -> Self { - self.group_name = value; - self - } - /// Set the prefix for names of all registers of the peripheral - pub fn prepend_to_name(mut self, value: Option) -> Self { - self.prepend_to_name = value; - self - } - /// Set the suffix for names of all registers of the peripheral - pub fn append_to_name(mut self, value: Option) -> Self { - self.append_to_name = value; - self - } - /// Set the header struct name of the peripheral - pub fn header_struct_name(mut self, value: Option) -> Self { - self.header_struct_name = value; - self - } - /// Set the base address of the peripheral - pub fn base_address(mut self, value: u64) -> Self { - self.base_address = Some(value); - self - } - /// Set the default register properties of the peripheral - pub fn default_register_properties(mut self, value: RegisterProperties) -> Self { - self.default_register_properties = value; - self - } - /// Set the address block of the peripheral - pub fn address_block(mut self, value: Option>) -> Self { - self.address_block = value; - self - } - /// Set the interrupts of the peripheral - pub fn interrupt(mut self, value: Option>) -> Self { - self.interrupt = value; - self - } - /// Set the registers of the peripheral - pub fn registers(mut self, value: Option>) -> Self { - self.registers = value; - self - } - /// Set the derived_from attribute of the peripheral - pub fn derived_from(mut self, value: Option) -> Self { - self.derived_from = value; - self - } - /// Validate and build a [`PeripheralInfo`]. - pub fn build(self, lvl: ValidateLevel) -> Result { - let mut per = PeripheralInfo { - name: self - .name - .ok_or_else(|| BuildError::Uninitialized("name".to_string()))?, - display_name: self.display_name.empty_to_none(), - version: self.version.empty_to_none(), - description: self.description.empty_to_none(), - alternate_peripheral: self.alternate_peripheral.empty_to_none(), - group_name: self.group_name.empty_to_none(), - prepend_to_name: self.prepend_to_name.empty_to_none(), - append_to_name: self.append_to_name.empty_to_none(), - header_struct_name: self.header_struct_name.empty_to_none(), - base_address: self - .base_address - .ok_or_else(|| BuildError::Uninitialized("base_address".to_string()))?, - default_register_properties: self.default_register_properties.build(lvl)?, - address_block: self.address_block, - interrupt: self.interrupt.unwrap_or_default(), - registers: self.registers, - derived_from: self.derived_from, - }; - if !lvl.is_disabled() { - per.validate(lvl)?; - } - Ok(per) - } -} - -impl PeripheralInfo { - /// Make a builder for [`PeripheralInfo`] - pub fn builder() -> PeripheralInfoBuilder { - PeripheralInfoBuilder::default() - } - /// Construct single [`Peripheral`] - pub const fn single(self) -> Peripheral { - Peripheral::Single(self) - } - /// Construct [`Peripheral`] array - pub const fn array(self, dim: DimElement) -> Peripheral { - Peripheral::Array(self, dim) - } - /// Modify an existing [`Peripheral`] based on a [builder](PeripheralInfoBuilder). - pub fn modify_from( - &mut self, - builder: PeripheralInfoBuilder, - lvl: ValidateLevel, - ) -> Result<(), SvdError> { - if let Some(name) = builder.name { - self.name = name; - } - if builder.display_name.is_some() { - self.display_name = builder.display_name.empty_to_none(); - } - if builder.version.is_some() { - self.version = builder.version.empty_to_none(); - } - if builder.description.is_some() { - self.description = builder.description.empty_to_none(); - } - if builder.alternate_peripheral.is_some() { - self.alternate_peripheral = builder.alternate_peripheral.empty_to_none(); - } - if builder.group_name.is_some() { - self.group_name = builder.group_name.empty_to_none(); - } - if builder.prepend_to_name.is_some() { - self.prepend_to_name = builder.prepend_to_name.empty_to_none(); - } - if builder.append_to_name.is_some() { - self.append_to_name = builder.append_to_name.empty_to_none(); - } - if builder.header_struct_name.is_some() { - self.header_struct_name = builder.header_struct_name.empty_to_none(); - } - if let Some(base_address) = builder.base_address { - self.base_address = base_address; - } - if let Some(interrupt) = builder.interrupt { - self.interrupt = interrupt; - } - if builder.derived_from.is_some() { - self.derived_from = builder.derived_from; - self.registers = None; - self.address_block = None; - self.default_register_properties = RegisterProperties::default(); - } else { - if builder.address_block.is_some() { - self.address_block = builder.address_block; - } - self.default_register_properties - .modify_from(builder.default_register_properties, lvl)?; - if builder.registers.is_some() { - self.registers = builder.registers.empty_to_none(); - } - } - if !lvl.is_disabled() { - self.validate(lvl) - } else { - Ok(()) - } - } - - /// Validate the [`Peripheral`] - pub fn validate(&mut self, lvl: ValidateLevel) -> Result<(), SvdError> { - // TODO - if lvl.is_strict() { - super::check_dimable_name(&self.name, "name")?; - } - if let Some(name) = self.derived_from.as_ref() { - if lvl.is_strict() { - super::check_dimable_name(name, "derivedFrom")?; - } - } else if let Some(registers) = self.registers.as_ref() { - if registers.is_empty() && lvl.is_strict() { - return Err(Error::EmptyRegisters.into()); - } - } - Ok(()) - } - - /// Returns iterator over child registers - pub fn registers(&self) -> RegisterIter { - RegisterIter { - all: match &self.registers { - Some(regs) => regs.iter(), - None => [].iter(), - }, - } - } - - /// Returns mutable iterator over child registers - pub fn registers_mut(&mut self) -> RegisterIterMut { - RegisterIterMut { - all: match &mut self.registers { - Some(regs) => regs.iter_mut(), - None => [].iter_mut(), - }, - } - } - - /// Returns iterator over child clusters - pub fn clusters(&self) -> ClusterIter { - ClusterIter { - all: match &self.registers { - Some(regs) => regs.iter(), - None => [].iter(), - }, - } - } - - /// Returns mutable iterator over child clusters - pub fn clusters_mut(&mut self) -> ClusterIterMut { - ClusterIterMut { - all: match &mut self.registers { - Some(regs) => regs.iter_mut(), - None => [].iter_mut(), - }, - } - } - - /// Returns iterator over all descendant registers - #[deprecated(since = "0.12.1", note = "Please use `all_registers` instead")] - pub fn reg_iter(&self) -> AllRegistersIter { - self.all_registers() - } - - /// Returns iterator over all descendant registers - pub fn all_registers(&self) -> AllRegistersIter { - AllRegistersIter { - rem: match &self.registers { - Some(regs) => regs.iter().rev().collect(), - None => Vec::new(), - }, - } - } - - /// Returns mutable iterator over all descendant registers - #[deprecated(since = "0.12.1", note = "Please use `all_registers_mut` instead")] - pub fn reg_iter_mut(&mut self) -> AllRegistersIterMut { - self.all_registers_mut() - } - - /// Returns mutable iterator over all descendant registers - pub fn all_registers_mut(&mut self) -> AllRegistersIterMut { - AllRegistersIterMut { - rem: match &mut self.registers { - Some(regs) => regs.iter_mut().rev().collect(), - None => Vec::new(), - }, - } - } - - /// Get register by name - pub fn get_register(&self, name: &str) -> Option<&Register> { - self.registers().find(|f| f.name == name) - } - - /// Get mutable register by name - pub fn get_mut_register(&mut self, name: &str) -> Option<&mut Register> { - self.registers_mut().find(|f| f.name == name) - } - - /// Get cluster by name - pub fn get_cluster(&self, name: &str) -> Option<&Cluster> { - self.clusters().find(|f| f.name == name) - } - - /// Get mutable cluster by name - pub fn get_mut_cluster(&mut self, name: &str) -> Option<&mut Cluster> { - self.clusters_mut().find(|f| f.name == name) - } - - /// Get interrupt by name - pub fn get_interrupt(&self, name: &str) -> Option<&Interrupt> { - self.interrupt.iter().find(|e| e.name == name) - } - - /// Get mutable enumeratedValue by name - pub fn get_mut_interrupt(&mut self, name: &str) -> Option<&mut Interrupt> { - self.interrupt.iter_mut().find(|e| e.name == name) - } -} - -impl Name for PeripheralInfo { - fn name(&self) -> &str { - &self.name - } -} diff --git a/svd-rs/src/register.rs b/svd-rs/src/register.rs index 0094c5d6..8fc89b2e 100644 --- a/svd-rs/src/register.rs +++ b/svd-rs/src/register.rs @@ -1,6 +1,366 @@ -#[doc(hidden)] -pub use super::registercluster::{AllRegistersIter as RegIter, AllRegistersIterMut as RegIterMut}; -use super::{array::SingleArray, RegisterInfo}; +use super::{ + array::SingleArray, Access, BuildError, DimElement, EmptyToNone, Field, ModifiedWriteValues, + Name, ReadAction, RegisterProperties, SvdError, ValidateLevel, WriteConstraint, +}; /// A single register or array of registers. A register is a named, programmable resource that belongs to a [peripheral](crate::Peripheral). pub type Register = SingleArray; + +/// Errors from [`RegisterInfo::validate`] +#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)] +pub enum Error { + /// Register had no fields, but specified a `` tag. + #[error("Register have `fields` tag, but it is empty")] + EmptyFields, +} + +/// A register is a named, programmable resource that belongs to a [peripheral](crate::Peripheral). +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(rename_all = "camelCase") +)] +#[derive(Clone, Debug, PartialEq)] +#[non_exhaustive] +pub struct RegisterInfo { + /// String to identify the register. + /// Register names are required to be unique within the scope of a peripheral + pub name: String, + + /// Specifies a register name without the restrictions of an ANSI C identifier. + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub display_name: Option, + + /// String describing the details of the register + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub description: Option, + + /// Specifies a group name associated with all alternate register that have the same name + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub alternate_group: Option, + + /// This tag can reference a register that has been defined above to + /// current location in the description and that describes the memory location already + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub alternate_register: Option, + + /// Define the address offset relative to the enclosing element + pub address_offset: u32, + + /// Specifies register size, access permission and reset value + #[cfg_attr(feature = "serde", serde(flatten))] + pub properties: RegisterProperties, + + /// Specifies the write side effects + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub modified_write_values: Option, + + /// Specifies the subset of allowed write values + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub write_constraint: Option, + + /// If set, it specifies the side effect following a read operation. + /// If not set, the register is not modified + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub read_action: Option, + + /// `None` indicates that the `` node is not present + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub fields: Option>, + + /// Specify the register name from which to inherit data. + /// Elements specified subsequently override inherited values + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Option::is_none") + )] + pub derived_from: Option, +} + +/// Builder for [`RegisterInfo`] +#[derive(Clone, Debug, Default, PartialEq)] +pub struct RegisterInfoBuilder { + name: Option, + display_name: Option, + description: Option, + alternate_group: Option, + alternate_register: Option, + address_offset: Option, + properties: RegisterProperties, + modified_write_values: Option, + write_constraint: Option, + read_action: Option, + fields: Option>, + derived_from: Option, +} + +impl From for RegisterInfoBuilder { + fn from(r: RegisterInfo) -> Self { + Self { + name: Some(r.name), + display_name: r.display_name, + description: r.description, + alternate_group: r.alternate_group, + alternate_register: r.alternate_register, + address_offset: Some(r.address_offset), + properties: r.properties, + modified_write_values: r.modified_write_values, + write_constraint: r.write_constraint, + read_action: r.read_action, + fields: r.fields, + derived_from: r.derived_from, + } + } +} + +impl RegisterInfoBuilder { + /// Set the name of the register. + pub fn name(mut self, value: String) -> Self { + self.name = Some(value); + self + } + /// Set the display name of the register. + pub fn display_name(mut self, value: Option) -> Self { + self.display_name = value; + self + } + /// Set the description of the register. + pub fn description(mut self, value: Option) -> Self { + self.description = value; + self + } + /// Set the alternate group of the register. + pub fn alternate_group(mut self, value: Option) -> Self { + self.alternate_group = value; + self + } + /// Set the alternate register of the register. + pub fn alternate_register(mut self, value: Option) -> Self { + self.alternate_register = value; + self + } + /// Set the address offset of the register. + pub fn address_offset(mut self, value: u32) -> Self { + self.address_offset = Some(value); + self + } + /// Set the properties of the register. + pub fn properties(mut self, value: RegisterProperties) -> Self { + self.properties = value; + self + } + /// Set the size of the register. + pub fn size(mut self, value: Option) -> Self { + self.properties.size = value; + self + } + /// Set the access of the register. + pub fn access(mut self, value: Option) -> Self { + self.properties.access = value; + self + } + /// Set the reset value of the register. + pub fn reset_value(mut self, value: Option) -> Self { + self.properties.reset_value = value; + self + } + /// Set the reset mask of the register. + pub fn reset_mask(mut self, value: Option) -> Self { + self.properties.reset_mask = value; + self + } + /// Set the modified write values of the register. + pub fn modified_write_values(mut self, value: Option) -> Self { + self.modified_write_values = value; + self + } + /// Set the write constraint of the register. + pub fn write_constraint(mut self, value: Option) -> Self { + self.write_constraint = value; + self + } + /// Set the read action of the register. + pub fn read_action(mut self, value: Option) -> Self { + self.read_action = value; + self + } + /// Set the fields of the register. + pub fn fields(mut self, value: Option>) -> Self { + self.fields = value; + self + } + /// Set the derived_from attribute of the register. + pub fn derived_from(mut self, value: Option) -> Self { + self.derived_from = value; + self + } + /// Validate and build a [`RegisterInfo`]. + pub fn build(self, lvl: ValidateLevel) -> Result { + let mut reg = RegisterInfo { + name: self + .name + .ok_or_else(|| BuildError::Uninitialized("name".to_string()))?, + display_name: self.display_name, + description: self.description, + alternate_group: self.alternate_group, + alternate_register: self.alternate_register, + address_offset: self + .address_offset + .ok_or_else(|| BuildError::Uninitialized("address_offset".to_string()))?, + properties: self.properties.build(lvl)?, + modified_write_values: self.modified_write_values, + write_constraint: self.write_constraint, + read_action: self.read_action, + fields: self.fields, + derived_from: self.derived_from, + }; + if !lvl.is_disabled() { + reg.validate(lvl)?; + } + Ok(reg) + } +} + +impl RegisterInfo { + /// Make a builder for [`RegisterInfo`] + pub fn builder() -> RegisterInfoBuilder { + RegisterInfoBuilder::default() + } + /// Construct single [`Register`] + pub const fn single(self) -> Register { + Register::Single(self) + } + /// Construct [`Register`] array + pub const fn array(self, dim: DimElement) -> Register { + Register::Array(self, dim) + } + /// Modify an existing [`RegisterInfo`] based on a [builder](RegisterInfoBuilder). + pub fn modify_from( + &mut self, + builder: RegisterInfoBuilder, + lvl: ValidateLevel, + ) -> Result<(), SvdError> { + if let Some(name) = builder.name { + self.name = name; + } + if builder.display_name.is_some() { + self.display_name = builder.display_name.empty_to_none(); + } + if builder.description.is_some() { + self.description = builder.description.empty_to_none(); + } + if builder.alternate_group.is_some() { + self.alternate_group = builder.alternate_group.empty_to_none(); + } + if builder.alternate_register.is_some() { + self.alternate_register = builder.alternate_register.empty_to_none(); + } + if let Some(address_offset) = builder.address_offset { + self.address_offset = address_offset; + } + if builder.derived_from.is_some() { + self.derived_from = builder.derived_from; + self.fields = None; + self.properties = RegisterProperties::default(); + self.modified_write_values = None; + self.write_constraint = None; + } else { + self.properties.modify_from(builder.properties, lvl)?; + if builder.modified_write_values.is_some() { + self.modified_write_values = builder.modified_write_values; + } + if builder.write_constraint.is_some() { + self.write_constraint = builder.write_constraint; + } + if builder.read_action.is_some() { + self.read_action = builder.read_action; + } + if builder.fields.is_some() { + self.fields = builder.fields.empty_to_none(); + } + } + if !lvl.is_disabled() { + self.validate(lvl) + } else { + Ok(()) + } + } + /// Validate the [`RegisterInfo`] + pub fn validate(&mut self, lvl: ValidateLevel) -> Result<(), SvdError> { + if lvl.is_strict() { + super::check_dimable_name(&self.name, "name")?; + if let Some(name) = self.alternate_group.as_ref() { + super::check_name(name, "alternateGroup")?; + } + if let Some(name) = self.alternate_register.as_ref() { + super::check_dimable_name(name, "alternateRegister")?; + } + } + if let Some(name) = self.derived_from.as_ref() { + if lvl.is_strict() { + super::check_derived_name(name, "derivedFrom")?; + } + } else if let Some(fields) = self.fields.as_ref() { + if fields.is_empty() && lvl.is_strict() { + return Err(Error::EmptyFields.into()); + } + } + Ok(()) + } + + /// Returns iterator over child fields + pub fn fields(&self) -> std::slice::Iter { + match &self.fields { + Some(fields) => fields.iter(), + None => [].iter(), + } + } + + /// Returns mutable iterator over child fields + pub fn fields_mut(&mut self) -> std::slice::IterMut { + match &mut self.fields { + Some(fields) => fields.iter_mut(), + None => [].iter_mut(), + } + } + + /// Get field by name + pub fn get_field(&self, name: &str) -> Option<&Field> { + self.fields().find(|f| f.name == name) + } + + /// Get mutable field by name + pub fn get_mut_field(&mut self, name: &str) -> Option<&mut Field> { + self.fields_mut().find(|f| f.name == name) + } +} + +impl Name for RegisterInfo { + fn name(&self) -> &str { + &self.name + } +} diff --git a/svd-rs/src/registerinfo.rs b/svd-rs/src/registerinfo.rs deleted file mode 100644 index 5af680f9..00000000 --- a/svd-rs/src/registerinfo.rs +++ /dev/null @@ -1,363 +0,0 @@ -use super::{ - Access, BuildError, DimElement, EmptyToNone, Field, ModifiedWriteValues, Name, ReadAction, - Register, RegisterProperties, SvdError, ValidateLevel, WriteConstraint, -}; - -/// Errors from [`RegisterInfo::validate`] -#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)] -pub enum Error { - /// Register had no fields, but specified a `` tag. - #[error("Register have `fields` tag, but it is empty")] - EmptyFields, -} - -/// A register is a named, programmable resource that belongs to a [peripheral](crate::Peripheral). -#[cfg_attr( - feature = "serde", - derive(serde::Deserialize, serde::Serialize), - serde(rename_all = "camelCase") -)] -#[derive(Clone, Debug, PartialEq)] -#[non_exhaustive] -pub struct RegisterInfo { - /// String to identify the register. - /// Register names are required to be unique within the scope of a peripheral - pub name: String, - - /// Specifies a register name without the restrictions of an ANSI C identifier. - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub display_name: Option, - - /// String describing the details of the register - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub description: Option, - - /// Specifies a group name associated with all alternate register that have the same name - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub alternate_group: Option, - - /// This tag can reference a register that has been defined above to - /// current location in the description and that describes the memory location already - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub alternate_register: Option, - - /// Define the address offset relative to the enclosing element - pub address_offset: u32, - - /// Specifies register size, access permission and reset value - #[cfg_attr(feature = "serde", serde(flatten))] - pub properties: RegisterProperties, - - /// Specifies the write side effects - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub modified_write_values: Option, - - /// Specifies the subset of allowed write values - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub write_constraint: Option, - - /// If set, it specifies the side effect following a read operation. - /// If not set, the register is not modified - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub read_action: Option, - - /// `None` indicates that the `` node is not present - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub fields: Option>, - - /// Specify the register name from which to inherit data. - /// Elements specified subsequently override inherited values - #[cfg_attr( - feature = "serde", - serde(default, skip_serializing_if = "Option::is_none") - )] - pub derived_from: Option, -} - -/// Builder for [`RegisterInfo`] -#[derive(Clone, Debug, Default, PartialEq)] -pub struct RegisterInfoBuilder { - name: Option, - display_name: Option, - description: Option, - alternate_group: Option, - alternate_register: Option, - address_offset: Option, - properties: RegisterProperties, - modified_write_values: Option, - write_constraint: Option, - read_action: Option, - fields: Option>, - derived_from: Option, -} - -impl From for RegisterInfoBuilder { - fn from(r: RegisterInfo) -> Self { - Self { - name: Some(r.name), - display_name: r.display_name, - description: r.description, - alternate_group: r.alternate_group, - alternate_register: r.alternate_register, - address_offset: Some(r.address_offset), - properties: r.properties, - modified_write_values: r.modified_write_values, - write_constraint: r.write_constraint, - read_action: r.read_action, - fields: r.fields, - derived_from: r.derived_from, - } - } -} - -impl RegisterInfoBuilder { - /// Set the name of the register. - pub fn name(mut self, value: String) -> Self { - self.name = Some(value); - self - } - /// Set the display name of the register. - pub fn display_name(mut self, value: Option) -> Self { - self.display_name = value; - self - } - /// Set the description of the register. - pub fn description(mut self, value: Option) -> Self { - self.description = value; - self - } - /// Set the alternate group of the register. - pub fn alternate_group(mut self, value: Option) -> Self { - self.alternate_group = value; - self - } - /// Set the alternate register of the register. - pub fn alternate_register(mut self, value: Option) -> Self { - self.alternate_register = value; - self - } - /// Set the address offset of the register. - pub fn address_offset(mut self, value: u32) -> Self { - self.address_offset = Some(value); - self - } - /// Set the properties of the register. - pub fn properties(mut self, value: RegisterProperties) -> Self { - self.properties = value; - self - } - /// Set the size of the register. - pub fn size(mut self, value: Option) -> Self { - self.properties.size = value; - self - } - /// Set the access of the register. - pub fn access(mut self, value: Option) -> Self { - self.properties.access = value; - self - } - /// Set the reset value of the register. - pub fn reset_value(mut self, value: Option) -> Self { - self.properties.reset_value = value; - self - } - /// Set the reset mask of the register. - pub fn reset_mask(mut self, value: Option) -> Self { - self.properties.reset_mask = value; - self - } - /// Set the modified write values of the register. - pub fn modified_write_values(mut self, value: Option) -> Self { - self.modified_write_values = value; - self - } - /// Set the write constraint of the register. - pub fn write_constraint(mut self, value: Option) -> Self { - self.write_constraint = value; - self - } - /// Set the read action of the register. - pub fn read_action(mut self, value: Option) -> Self { - self.read_action = value; - self - } - /// Set the fields of the register. - pub fn fields(mut self, value: Option>) -> Self { - self.fields = value; - self - } - /// Set the derived_from attribute of the register. - pub fn derived_from(mut self, value: Option) -> Self { - self.derived_from = value; - self - } - /// Validate and build a [`RegisterInfo`]. - pub fn build(self, lvl: ValidateLevel) -> Result { - let mut reg = RegisterInfo { - name: self - .name - .ok_or_else(|| BuildError::Uninitialized("name".to_string()))?, - display_name: self.display_name, - description: self.description, - alternate_group: self.alternate_group, - alternate_register: self.alternate_register, - address_offset: self - .address_offset - .ok_or_else(|| BuildError::Uninitialized("address_offset".to_string()))?, - properties: self.properties.build(lvl)?, - modified_write_values: self.modified_write_values, - write_constraint: self.write_constraint, - read_action: self.read_action, - fields: self.fields, - derived_from: self.derived_from, - }; - if !lvl.is_disabled() { - reg.validate(lvl)?; - } - Ok(reg) - } -} - -impl RegisterInfo { - /// Make a builder for [`RegisterInfo`] - pub fn builder() -> RegisterInfoBuilder { - RegisterInfoBuilder::default() - } - /// Construct single [`Register`] - pub const fn single(self) -> Register { - Register::Single(self) - } - /// Construct [`Register`] array - pub const fn array(self, dim: DimElement) -> Register { - Register::Array(self, dim) - } - /// Modify an existing [`RegisterInfo`] based on a [builder](RegisterInfoBuilder). - pub fn modify_from( - &mut self, - builder: RegisterInfoBuilder, - lvl: ValidateLevel, - ) -> Result<(), SvdError> { - if let Some(name) = builder.name { - self.name = name; - } - if builder.display_name.is_some() { - self.display_name = builder.display_name.empty_to_none(); - } - if builder.description.is_some() { - self.description = builder.description.empty_to_none(); - } - if builder.alternate_group.is_some() { - self.alternate_group = builder.alternate_group.empty_to_none(); - } - if builder.alternate_register.is_some() { - self.alternate_register = builder.alternate_register.empty_to_none(); - } - if let Some(address_offset) = builder.address_offset { - self.address_offset = address_offset; - } - if builder.derived_from.is_some() { - self.derived_from = builder.derived_from; - self.fields = None; - self.properties = RegisterProperties::default(); - self.modified_write_values = None; - self.write_constraint = None; - } else { - self.properties.modify_from(builder.properties, lvl)?; - if builder.modified_write_values.is_some() { - self.modified_write_values = builder.modified_write_values; - } - if builder.write_constraint.is_some() { - self.write_constraint = builder.write_constraint; - } - if builder.read_action.is_some() { - self.read_action = builder.read_action; - } - if builder.fields.is_some() { - self.fields = builder.fields.empty_to_none(); - } - } - if !lvl.is_disabled() { - self.validate(lvl) - } else { - Ok(()) - } - } - /// Validate the [`RegisterInfo`] - pub fn validate(&mut self, lvl: ValidateLevel) -> Result<(), SvdError> { - if lvl.is_strict() { - super::check_dimable_name(&self.name, "name")?; - if let Some(name) = self.alternate_group.as_ref() { - super::check_name(name, "alternateGroup")?; - } - if let Some(name) = self.alternate_register.as_ref() { - super::check_dimable_name(name, "alternateRegister")?; - } - } - if let Some(name) = self.derived_from.as_ref() { - if lvl.is_strict() { - super::check_derived_name(name, "derivedFrom")?; - } - } else if let Some(fields) = self.fields.as_ref() { - if fields.is_empty() && lvl.is_strict() { - return Err(Error::EmptyFields.into()); - } - } - Ok(()) - } - - /// Returns iterator over child fields - pub fn fields(&self) -> std::slice::Iter { - match &self.fields { - Some(fields) => fields.iter(), - None => [].iter(), - } - } - - /// Returns mutable iterator over child fields - pub fn fields_mut(&mut self) -> std::slice::IterMut { - match &mut self.fields { - Some(fields) => fields.iter_mut(), - None => [].iter_mut(), - } - } - - /// Get field by name - pub fn get_field(&self, name: &str) -> Option<&Field> { - self.fields().find(|f| f.name == name) - } - - /// Get mutable field by name - pub fn get_mut_field(&mut self, name: &str) -> Option<&mut Field> { - self.fields_mut().find(|f| f.name == name) - } -} - -impl Name for RegisterInfo { - fn name(&self) -> &str { - &self.name - } -} diff --git a/tests/src/field.rs b/tests/src/field.rs index 1bde7e4f..b62d3aee 100644 --- a/tests/src/field.rs +++ b/tests/src/field.rs @@ -1,5 +1,8 @@ use super::run_test; -use crate::svd::{BitRange, BitRangeType, DimElement, Field, FieldInfo, ValidateLevel}; +use crate::svd::{ + Access, BitRange, BitRangeType, DimElement, EnumeratedValue, EnumeratedValues, Field, + FieldInfo, ValidateLevel, +}; #[test] fn decode_encode() { @@ -8,11 +11,7 @@ fn decode_encode() { FieldInfo::builder() .name("MODE%s".to_string()) .derived_from(Some("other_field".to_string())) - .bit_range(BitRange { - offset: 24, - width: 2, - range_type: BitRangeType::OffsetWidth, - }) + .bit_range(BitRange::from_offset_width(24, 2)) .build(ValidateLevel::Strict) .unwrap(), DimElement::builder() @@ -35,3 +34,71 @@ fn decode_encode() { )]; run_test::(&tests[..]); } + +#[test] +fn decode_encode_info() { + let tests = vec![ + ( + FieldInfo::builder() + .name("MODE".to_string()) + .description(Some("Read Mode".to_string())) + .bit_range(BitRange { + offset: 24, + width: 2, + range_type: BitRangeType::OffsetWidth, + }) + .access(Some(Access::ReadWrite)) + .enumerated_values(vec![EnumeratedValues::builder() + .values(vec![EnumeratedValue::builder() + .name("WS0".to_string()) + .description(Some( + "Zero wait-states inserted in fetch or read transfers".to_string(), + )) + .value(Some(0)) + .is_default(None) + .build(ValidateLevel::Strict) + .unwrap()]) + .build(ValidateLevel::Strict) + .unwrap()]) + .build(ValidateLevel::Strict) + .unwrap(), + " + + MODE + Read Mode + 24 + 2 + read-write + + + WS0 + Zero wait-states inserted in fetch or read transfers + 0 + + + + ", + ), + ( + FieldInfo::builder() + .name("MODE".to_string()) + .derived_from(Some("other_field".to_string())) + .bit_range(BitRange { + offset: 24, + width: 2, + range_type: BitRangeType::OffsetWidth, + }) + .build(ValidateLevel::Strict) + .unwrap(), + " + + MODE + 24 + 2 + + ", + ), + ]; + + run_test::(&tests[..]); +} diff --git a/tests/src/fieldinfo.rs b/tests/src/fieldinfo.rs deleted file mode 100644 index da85f000..00000000 --- a/tests/src/fieldinfo.rs +++ /dev/null @@ -1,72 +0,0 @@ -use super::run_test; -use crate::svd::{ - Access, BitRange, BitRangeType, EnumeratedValue, EnumeratedValues, FieldInfo, ValidateLevel, -}; - -#[test] -fn decode_encode() { - let tests = vec![ - ( - FieldInfo::builder() - .name("MODE".to_string()) - .description(Some("Read Mode".to_string())) - .bit_range(BitRange { - offset: 24, - width: 2, - range_type: BitRangeType::OffsetWidth, - }) - .access(Some(Access::ReadWrite)) - .enumerated_values(vec![EnumeratedValues::builder() - .values(vec![EnumeratedValue::builder() - .name("WS0".to_string()) - .description(Some( - "Zero wait-states inserted in fetch or read transfers".to_string(), - )) - .value(Some(0)) - .is_default(None) - .build(ValidateLevel::Strict) - .unwrap()]) - .build(ValidateLevel::Strict) - .unwrap()]) - .build(ValidateLevel::Strict) - .unwrap(), - " - - MODE - Read Mode - 24 - 2 - read-write - - - WS0 - Zero wait-states inserted in fetch or read transfers - 0 - - - - ", - ), - ( - FieldInfo::builder() - .name("MODE".to_string()) - .derived_from(Some("other_field".to_string())) - .bit_range(BitRange { - offset: 24, - width: 2, - range_type: BitRangeType::OffsetWidth, - }) - .build(ValidateLevel::Strict) - .unwrap(), - " - - MODE - 24 - 2 - - ", - ), - ]; - - run_test::(&tests[..]); -} diff --git a/tests/src/lib.rs b/tests/src/lib.rs index 5bb98002..d9fdcc03 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -50,11 +50,9 @@ mod endian; mod enumeratedvalue; //mod enumeratedvalues; mod field; -mod fieldinfo; mod interrupt; mod modifiedwritevalues; mod register; -mod registerinfo; //mod registerproperties; mod usage; mod writeconstraint; diff --git a/tests/src/register.rs b/tests/src/register.rs index 82b6e43f..332a9c0e 100644 --- a/tests/src/register.rs +++ b/tests/src/register.rs @@ -1,5 +1,8 @@ use super::run_test; -use crate::svd::{DimElement, Register, RegisterInfo, ValidateLevel}; +use crate::svd::{ + Access, BitRange, BitRangeType, DimElement, Field, FieldInfo, ModifiedWriteValues, Register, + RegisterInfo, ValidateLevel, +}; #[test] fn decode_encode() { @@ -29,3 +32,61 @@ fn decode_encode() { )]; run_test::(&tests[..]); } + +#[test] +fn decode_encode_info() { + let tests = vec![( + RegisterInfo::builder() + .name("WRITECTRL".to_string()) + .alternate_group(Some("alternate_group".to_string())) + .alternate_register(Some("alternate_register".to_string())) + .derived_from(Some("derived_from".to_string())) + .description(Some("Write Control Register".to_string())) + .address_offset(8) + .size(Some(32)) + .access(Some(Access::ReadWrite)) + .reset_value(Some(0x00000000)) + .reset_mask(Some(0x00000023)) + .fields(Some(vec![Field::Single( + FieldInfo::builder() + .name("WREN".to_string()) + .description(Some("Enable Write/Erase Controller".to_string())) + .bit_range(BitRange { + offset: 0, + width: 1, + range_type: BitRangeType::OffsetWidth, + }) + .access(Some(Access::ReadWrite)) + .build(ValidateLevel::Strict) + .unwrap(), + )])) + .modified_write_values(Some(ModifiedWriteValues::OneToToggle)) + .build(ValidateLevel::Strict) + .unwrap(), + " + + WRITECTRL + Write Control Register + alternate_group + alternate_register + 0x8 + 0x20 + read-write + 0x00000000 + 0x00000023 + oneToToggle + + + WREN + Enable Write/Erase Controller + 0 + 1 + read-write + + + + ", + )]; + + run_test::(&tests[..]); +} diff --git a/tests/src/registerinfo.rs b/tests/src/registerinfo.rs deleted file mode 100644 index 1ee39557..00000000 --- a/tests/src/registerinfo.rs +++ /dev/null @@ -1,63 +0,0 @@ -use super::run_test; -use crate::svd::{ - Access, BitRange, BitRangeType, Field, FieldInfo, ModifiedWriteValues, RegisterInfo, - ValidateLevel, -}; - -#[test] -fn decode_encode() { - let tests = vec![( - RegisterInfo::builder() - .name("WRITECTRL".to_string()) - .alternate_group(Some("alternate_group".to_string())) - .alternate_register(Some("alternate_register".to_string())) - .derived_from(Some("derived_from".to_string())) - .description(Some("Write Control Register".to_string())) - .address_offset(8) - .size(Some(32)) - .access(Some(Access::ReadWrite)) - .reset_value(Some(0x00000000)) - .reset_mask(Some(0x00000023)) - .fields(Some(vec![Field::Single( - FieldInfo::builder() - .name("WREN".to_string()) - .description(Some("Enable Write/Erase Controller".to_string())) - .bit_range(BitRange { - offset: 0, - width: 1, - range_type: BitRangeType::OffsetWidth, - }) - .access(Some(Access::ReadWrite)) - .build(ValidateLevel::Strict) - .unwrap(), - )])) - .modified_write_values(Some(ModifiedWriteValues::OneToToggle)) - .build(ValidateLevel::Strict) - .unwrap(), - " - - WRITECTRL - Write Control Register - alternate_group - alternate_register - 0x8 - 0x20 - read-write - 0x00000000 - 0x00000023 - oneToToggle - - - WREN - Enable Write/Erase Controller - 0 - 1 - read-write - - - - ", - )]; - - run_test::(&tests[..]); -}