1#![deny(missing_docs)]
2pub mod array;
7pub use array::MaybeArray;
8
9pub mod endian;
11pub use self::endian::Endian;
12
13pub mod cpu;
15pub use self::cpu::{Cpu, CpuBuilder};
16
17pub mod interrupt;
19pub use self::interrupt::Interrupt;
20
21pub mod access;
23pub use self::access::Access;
24
25pub mod bitrange;
27pub use self::bitrange::{BitRange, BitRangeType};
28
29pub mod writeconstraint;
31pub use self::writeconstraint::{WriteConstraint, WriteConstraintRange};
32
33pub mod usage;
35pub use self::usage::Usage;
36
37pub mod enumeratedvalue;
39pub use self::enumeratedvalue::{EnumeratedValue, EnumeratedValueBuilder};
40
41pub mod enumeratedvalues;
43pub use self::enumeratedvalues::{EnumeratedValues, EnumeratedValuesBuilder};
44
45pub mod field;
47pub use self::field::{Field, FieldInfo, FieldInfoBuilder};
48
49pub mod registerproperties;
51pub use self::registerproperties::RegisterProperties;
52
53pub mod addressblock;
55pub use self::addressblock::{AddressBlock, AddressBlockUsage};
56
57pub mod cluster;
59pub use self::cluster::{Cluster, ClusterInfo, ClusterInfoBuilder};
60
61pub mod register;
63pub use self::register::{Register, RegisterInfo, RegisterInfoBuilder};
64
65pub mod registercluster;
67pub use self::registercluster::RegisterCluster;
68
69pub mod dimelement;
71pub use self::dimelement::{DimArrayIndex, DimElement, DimElementBuilder};
72
73pub mod peripheral;
75pub use self::peripheral::{Peripheral, PeripheralInfo, PeripheralInfoBuilder};
76
77pub mod device;
79pub use self::device::{Device, DeviceBuilder};
80
81pub mod modifiedwritevalues;
83pub use self::modifiedwritevalues::ModifiedWriteValues;
84
85pub mod readaction;
87pub use self::readaction::ReadAction;
88
89pub mod protection;
91pub use self::protection::Protection;
92
93pub mod datatype;
95pub use self::datatype::DataType;
96
97#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
99pub enum ValidateLevel {
100 Disabled,
102 #[default]
104 Weak,
105 Strict,
107}
108
109impl ValidateLevel {
110 pub fn is_disabled(self) -> bool {
112 self == ValidateLevel::Disabled
113 }
114 pub fn is_weak(self) -> bool {
116 self != ValidateLevel::Disabled
117 }
118 pub fn is_strict(self) -> bool {
120 self == ValidateLevel::Strict
121 }
122}
123
124#[cfg(feature = "derive-from")]
125pub mod derive_from;
126#[cfg(feature = "derive-from")]
127pub use derive_from::DeriveFrom;
128
129use once_cell::sync::Lazy;
130use regex::Regex;
131
132#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
134pub enum SvdError {
135 #[error("`Build error: {0}")]
137 Build(#[from] BuildError),
138 #[error("`Name check error: {0}")]
140 Name(#[from] NameError),
141 #[error("`Device error: {0}")]
143 Device(#[from] device::Error),
144 #[error("`Peripheral error: {0}")]
146 Peripheral(#[from] peripheral::Error),
147 #[error("`Cluster error: {0}")]
149 Cluster(#[from] cluster::Error),
150 #[error("`Register error: {0}")]
152 Register(#[from] register::Error),
153 #[error("`Field error: {0}")]
155 Field(#[from] field::Error),
156 #[error("`BitRange error: {0}")]
158 BitRange(#[from] bitrange::Error),
159 #[error("`EnumeratedValue error: {0}")]
161 EnumeratedValue(#[from] enumeratedvalue::Error),
162 #[error("`EnumeratedValues error: {0}")]
164 EnumeratedValues(#[from] enumeratedvalues::Error),
165 #[error("`RegisterProperties error: {0}")]
167 RegisterProperties(#[from] registerproperties::Error),
168 #[error("`WriteConstraint error: {0}")]
170 WriteConstraint(#[from] writeconstraint::Error),
171}
172
173#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
175pub enum BuildError {
176 #[error("`{0}` must be initialized")]
178 Uninitialized(String),
179}
180
181#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
183pub enum NameError {
184 #[error("Name `{0}` contains unexpected symbol")]
186 Invalid(String, String),
187}
188
189pub(crate) fn check_name(name: &str, tag: &str) -> Result<(), NameError> {
190 static PATTERN: Lazy<Regex> = Lazy::new(|| Regex::new("^[_A-Za-z0-9]*$").unwrap());
191 if PATTERN.is_match(name) {
192 Ok(())
193 } else {
194 Err(NameError::Invalid(name.to_string(), tag.to_string()))
195 }
196}
197
198pub(crate) fn check_dimable_name(name: &str, tag: &str) -> Result<(), NameError> {
199 static PATTERN: Lazy<Regex> = Lazy::new(|| {
200 Regex::new("^(((%s)|(%s)[_A-Za-z]{1}[_A-Za-z0-9]*)|([_A-Za-z]{1}[_A-Za-z0-9]*(\\[%s\\])?)|([_A-Za-z]{1}[_A-Za-z0-9]*(%s)?[_A-Za-z0-9]*))$").unwrap()
201 });
202 if PATTERN.is_match(name) {
203 Ok(())
204 } else {
205 Err(NameError::Invalid(name.to_string(), tag.to_string()))
206 }
207}
208
209pub(crate) fn check_derived_name(name: &str, tag: &str) -> Result<(), NameError> {
210 for x in name.split('.') {
211 check_dimable_name(x, tag)?
212 }
213 Ok(())
214}
215
216trait EmptyToNone {
217 fn empty_to_none(self) -> Self;
218}
219
220impl EmptyToNone for Option<String> {
221 fn empty_to_none(self) -> Self {
222 self.and_then(|s| if s.is_empty() { None } else { Some(s) })
223 }
224}
225
226impl<T> EmptyToNone for Option<Vec<T>> {
227 fn empty_to_none(self) -> Self {
228 self.and_then(|v| if v.is_empty() { None } else { Some(v) })
229 }
230}
231
232pub trait Name {
234 fn name(&self) -> &str;
236}
237
238impl<T> Name for &T
239where
240 T: Name,
241{
242 fn name(&self) -> &str {
243 T::name(*self)
244 }
245}
246
247impl<T> Name for &mut T
248where
249 T: Name,
250{
251 fn name(&self) -> &str {
252 T::name(*self)
253 }
254}
255
256pub trait Description {
258 fn description(&self) -> Option<&str>;
260}
261
262impl<T> Description for &T
263where
264 T: Description,
265{
266 fn description(&self) -> Option<&str> {
267 T::description(*self)
268 }
269}
270
271impl<T> Description for &mut T
272where
273 T: Description,
274{
275 fn description(&self) -> Option<&str> {
276 T::description(*self)
277 }
278}