Skip to content

Commit ad05b80

Browse files
bors[bot]burrbull
andauthored
Merge #181
181: use generic enum for arrays, remove OptIter, add more methods r=Emilgardis a=burrbull Co-authored-by: Andrey Zgarbul <zgarbul.andrey@gmail.com>
2 parents 460cdbf + 63044d2 commit ad05b80

22 files changed

+359
-537
lines changed

svd-parser/src/array.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use super::*;
2+
use svd_rs::{DimElement, Name, SingleArray};
3+
4+
pub fn parse_array<T>(tag: &str, tree: &Node, config: &Config) -> Result<SingleArray<T>, SVDErrorAt>
5+
where
6+
T: Parse<Object = T, Error = SVDErrorAt, Config = Config> + Name,
7+
{
8+
if !tree.has_tag_name(tag) {
9+
return Err(SVDError::NotExpectedTag(tag.into()).at(tree.id()));
10+
}
11+
12+
let info = T::parse(tree, config)?;
13+
14+
if tree.get_child("dimIncrement").is_some() {
15+
let array_info = DimElement::parse(tree, config)?;
16+
check_has_placeholder(info.name(), tag).map_err(|e| e.at(tree.id()))?;
17+
if let Some(indexes) = &array_info.dim_index {
18+
if array_info.dim as usize != indexes.len() {
19+
return Err(SVDError::IncorrectDimIndexesCount(
20+
array_info.dim as usize,
21+
indexes.len(),
22+
)
23+
.at(tree.id()));
24+
}
25+
}
26+
Ok(SingleArray::Array(info, array_info))
27+
} else {
28+
Ok(SingleArray::Single(info))
29+
}
30+
}

svd-parser/src/cluster.rs

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,12 @@
11
use super::*;
2-
use crate::svd::{Cluster, ClusterInfo, DimElement};
2+
use crate::svd::Cluster;
33

44
impl Parse for Cluster {
55
type Object = Self;
66
type Error = SVDErrorAt;
77
type Config = Config;
88

99
fn parse(tree: &Node, config: &Self::Config) -> Result<Self, Self::Error> {
10-
if !tree.has_tag_name("cluster") {
11-
return Err(SVDError::NotExpectedTag("cluster".to_string()).at(tree.id()));
12-
}
13-
14-
let info = ClusterInfo::parse(tree, config)?;
15-
16-
if tree.get_child("dimIncrement").is_some() {
17-
let array_info = DimElement::parse(tree, config)?;
18-
check_has_placeholder(&info.name, "cluster").map_err(|e| e.at(tree.id()))?;
19-
if let Some(indexes) = &array_info.dim_index {
20-
if array_info.dim as usize != indexes.len() {
21-
return Err(SVDError::IncorrectDimIndexesCount(
22-
array_info.dim as usize,
23-
indexes.len(),
24-
)
25-
.at(tree.id()));
26-
}
27-
}
28-
Ok(info.array(array_info))
29-
} else {
30-
Ok(info.single())
31-
}
10+
parse_array("cluster", tree, config)
3211
}
3312
}

svd-parser/src/field.rs

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,12 @@
11
use super::*;
2-
use crate::svd::{DimElement, Field, FieldInfo};
3-
use crate::{elementext::ElementExt, Config};
2+
use crate::svd::Field;
43

54
impl Parse for Field {
65
type Object = Self;
76
type Error = SVDErrorAt;
87
type Config = Config;
98

109
fn parse(tree: &Node, config: &Self::Config) -> Result<Self, Self::Error> {
11-
if !tree.has_tag_name("field") {
12-
return Err(SVDError::NotExpectedTag("field".to_string()).at(tree.id()));
13-
}
14-
15-
let info = FieldInfo::parse(tree, config)?;
16-
17-
if tree.get_child("dimIncrement").is_some() {
18-
let array_info = DimElement::parse(tree, config)?;
19-
check_has_placeholder(&info.name, "field").map_err(|e| e.at(tree.id()))?;
20-
if let Some(indexes) = &array_info.dim_index {
21-
if array_info.dim as usize != indexes.len() {
22-
return Err(SVDError::IncorrectDimIndexesCount(
23-
array_info.dim as usize,
24-
indexes.len(),
25-
)
26-
.at(tree.id()));
27-
}
28-
}
29-
Ok(info.array(array_info))
30-
} else {
31-
Ok(info.single())
32-
}
10+
parse_array("field", tree, config)
3311
}
3412
}

svd-parser/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ fn trim_utf8_bom(s: &str) -> &str {
146146
}
147147
}
148148

149+
mod array;
150+
use array::parse_array;
151+
149152
mod access;
150153
mod addressblock;
151154
mod bitrange;

svd-parser/src/peripheral.rs

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,12 @@
11
use super::*;
2-
use crate::elementext::ElementExt;
3-
use crate::svd::{DimElement, Peripheral, PeripheralInfo};
2+
use crate::svd::Peripheral;
43

54
impl Parse for Peripheral {
65
type Object = Self;
76
type Error = SVDErrorAt;
87
type Config = Config;
98

109
fn parse(tree: &Node, config: &Self::Config) -> Result<Self, Self::Error> {
11-
if !tree.has_tag_name("peripheral") {
12-
return Err(SVDError::NotExpectedTag("peripheral".to_string()).at(tree.id()));
13-
}
14-
15-
let info = PeripheralInfo::parse(tree, config)?;
16-
17-
if tree.get_child("dimIncrement").is_some() {
18-
let array_info = DimElement::parse(tree, config)?;
19-
check_has_placeholder(&info.name, "peripheral").map_err(|e| e.at(tree.id()))?;
20-
if let Some(indexes) = &array_info.dim_index {
21-
if array_info.dim as usize != indexes.len() {
22-
return Err(SVDError::IncorrectDimIndexesCount(
23-
array_info.dim as usize,
24-
indexes.len(),
25-
)
26-
.at(tree.id()));
27-
}
28-
}
29-
Ok(info.array(array_info))
30-
} else {
31-
Ok(info.single())
32-
}
10+
parse_array("peripheral", tree, config)
3311
}
3412
}

svd-parser/src/register.rs

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,12 @@
11
use super::*;
2-
use crate::elementext::ElementExt;
3-
use crate::svd::{DimElement, Register, RegisterInfo};
2+
use crate::svd::Register;
43

54
impl Parse for Register {
65
type Object = Self;
76
type Error = SVDErrorAt;
87
type Config = Config;
98

109
fn parse(tree: &Node, config: &Self::Config) -> Result<Self, Self::Error> {
11-
if !tree.has_tag_name("register") {
12-
return Err(SVDError::NotExpectedTag("register".to_string()).at(tree.id()));
13-
}
14-
15-
let info = RegisterInfo::parse(tree, config)?;
16-
17-
if tree.get_child("dimIncrement").is_some() {
18-
let array_info = DimElement::parse(tree, config)?;
19-
check_has_placeholder(&info.name, "register").map_err(|e| e.at(tree.id()))?;
20-
if let Some(indexes) = &array_info.dim_index {
21-
if array_info.dim as usize != indexes.len() {
22-
return Err(SVDError::IncorrectDimIndexesCount(
23-
array_info.dim as usize,
24-
indexes.len(),
25-
)
26-
.at(tree.id()));
27-
}
28-
}
29-
Ok(info.array(array_info))
30-
} else {
31-
Ok(info.single())
32-
}
10+
parse_array("register", tree, config)
3311
}
3412
}

svd-rs/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## Unreleased
99

10+
- `EnumeratedValues.usage()` now return `None` if it is derived, fix bug in usage check
11+
- Use generic `SingleArray` enum for types which can be either collected into SVD arrays or have only one instance
12+
- `Name` trait for structures that has `name` field
13+
- improves in iterators
14+
- `get_enumerated_values` by usage
15+
1016
## [v0.12.1] - 2021-12-08
1117

1218
- Rename `reg_iter` to `all_registers`,

svd-rs/src/array.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use super::{DimElement, Name};
2+
use core::ops::{Deref, DerefMut};
3+
4+
/// A single SVD instance or array of instances
5+
#[derive(Clone, Debug, PartialEq)]
6+
pub enum SingleArray<T> {
7+
/// A single instance
8+
Single(T),
9+
/// An array of instances
10+
Array(T, DimElement),
11+
}
12+
13+
impl<T> Deref for SingleArray<T> {
14+
type Target = T;
15+
16+
fn deref(&self) -> &T {
17+
match self {
18+
Self::Single(info) => info,
19+
Self::Array(info, _) => info,
20+
}
21+
}
22+
}
23+
24+
impl<T> DerefMut for SingleArray<T> {
25+
fn deref_mut(&mut self) -> &mut T {
26+
match self {
27+
Self::Single(info) => info,
28+
Self::Array(info, _) => info,
29+
}
30+
}
31+
}
32+
33+
impl<T> SingleArray<T> {
34+
/// Return `true` if instance is single
35+
pub const fn is_single(&self) -> bool {
36+
matches!(self, Self::Single(_))
37+
}
38+
/// Return `true` if it is an array
39+
pub const fn is_array(&self) -> bool {
40+
matches!(self, Self::Array(_, _))
41+
}
42+
}
43+
44+
impl<T> Name for SingleArray<T>
45+
where
46+
T: Name,
47+
{
48+
fn name(&self) -> &str {
49+
T::name(self)
50+
}
51+
}
52+
53+
#[cfg(feature = "serde")]
54+
mod ser_de {
55+
use super::*;
56+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
57+
58+
#[derive(serde::Serialize)]
59+
struct SerArray<'a, T> {
60+
#[serde(flatten)]
61+
dim: &'a DimElement,
62+
#[serde(flatten)]
63+
info: &'a T,
64+
}
65+
66+
#[derive(serde::Deserialize)]
67+
struct DeserArray<T> {
68+
#[serde(flatten, default)]
69+
dim: Option<DimElement>,
70+
#[serde(flatten)]
71+
info: T,
72+
}
73+
74+
impl<T> Serialize for SingleArray<T>
75+
where
76+
T: Serialize,
77+
{
78+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
79+
where
80+
S: Serializer,
81+
{
82+
match self {
83+
Self::Single(info) => info.serialize(serializer),
84+
Self::Array(info, dim) => SerArray::<T> { dim, info }.serialize(serializer),
85+
}
86+
}
87+
}
88+
89+
impl<'de, T> Deserialize<'de> for SingleArray<T>
90+
where
91+
T: Deserialize<'de>,
92+
{
93+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
94+
where
95+
D: Deserializer<'de>,
96+
{
97+
let DeserArray { dim, info } = DeserArray::<T>::deserialize(deserializer)?;
98+
if let Some(dim) = dim {
99+
Ok(Self::Array(info, dim))
100+
} else {
101+
Ok(Self::Single(info))
102+
}
103+
}
104+
}
105+
}

svd-rs/src/cluster.rs

Lines changed: 2 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,4 @@
1-
use core::ops::{Deref, DerefMut};
2-
3-
use super::{ClusterInfo, DimElement};
1+
use super::{array::SingleArray, ClusterInfo};
42

53
/// Cluster describes a sequence of neighboring registers within a peripheral.
6-
#[derive(Clone, Debug, PartialEq)]
7-
pub enum Cluster {
8-
/// A single cluster, without any dimension.
9-
Single(ClusterInfo),
10-
/// A cluster array
11-
Array(ClusterInfo, DimElement),
12-
}
13-
14-
impl Deref for Cluster {
15-
type Target = ClusterInfo;
16-
17-
fn deref(&self) -> &ClusterInfo {
18-
match self {
19-
Self::Single(info) => info,
20-
Self::Array(info, _) => info,
21-
}
22-
}
23-
}
24-
25-
impl DerefMut for Cluster {
26-
fn deref_mut(&mut self) -> &mut ClusterInfo {
27-
match self {
28-
Self::Single(info) => info,
29-
Self::Array(info, _) => info,
30-
}
31-
}
32-
}
33-
34-
impl Cluster {
35-
/// Return `true` if cluster instance is single
36-
pub const fn is_single(&self) -> bool {
37-
matches!(self, Self::Single(_))
38-
}
39-
/// Return `true` if it is cluster array
40-
pub const fn is_array(&self) -> bool {
41-
matches!(self, Self::Array(_, _))
42-
}
43-
}
44-
45-
#[cfg(feature = "serde")]
46-
mod ser_de {
47-
use super::*;
48-
use crate::{DeserArray, SerArray};
49-
use serde::{Deserialize, Deserializer, Serialize, Serializer};
50-
51-
impl Serialize for Cluster {
52-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
53-
where
54-
S: Serializer,
55-
{
56-
match self {
57-
Self::Single(info) => info.serialize(serializer),
58-
Self::Array(info, dim) => SerArray { dim, info }.serialize(serializer),
59-
}
60-
}
61-
}
62-
63-
impl<'de> Deserialize<'de> for Cluster {
64-
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
65-
where
66-
D: Deserializer<'de>,
67-
{
68-
let DeserArray { dim, info } = DeserArray::<ClusterInfo>::deserialize(deserializer)?;
69-
if let Some(dim) = dim {
70-
Ok(info.array(dim))
71-
} else {
72-
Ok(info.single())
73-
}
74-
}
75-
}
76-
}
4+
pub type Cluster = SingleArray<ClusterInfo>;

0 commit comments

Comments
 (0)