use super::{EmptyToNone, EnumeratedValue, SvdError, Usage, ValidateLevel};
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct EnumeratedValues {
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Option::is_none")
)]
pub name: Option<String>,
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Option::is_none")
)]
pub usage: Option<Usage>,
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Option::is_none")
)]
pub derived_from: Option<String>,
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Vec::is_empty")
)]
pub values: Vec<EnumeratedValue>,
}
#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
pub enum Error {
#[error("EnumeratedValues is empty")]
Empty,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct EnumeratedValuesBuilder {
name: Option<String>,
usage: Option<Usage>,
derived_from: Option<String>,
values: Option<Vec<EnumeratedValue>>,
}
impl From<EnumeratedValues> for EnumeratedValuesBuilder {
fn from(e: EnumeratedValues) -> Self {
Self {
name: e.name,
usage: e.usage,
derived_from: e.derived_from,
values: Some(e.values),
}
}
}
impl EnumeratedValuesBuilder {
pub fn name(mut self, value: Option<String>) -> Self {
self.name = value;
self
}
pub fn usage(mut self, value: Option<Usage>) -> Self {
self.usage = value;
self
}
pub fn derived_from(mut self, value: Option<String>) -> Self {
self.derived_from = value;
self
}
pub fn values(mut self, value: Vec<EnumeratedValue>) -> Self {
self.values = Some(value);
self
}
pub fn build(self, lvl: ValidateLevel) -> Result<EnumeratedValues, SvdError> {
let evs = EnumeratedValues {
name: self.name.empty_to_none(),
usage: self.usage,
derived_from: self.derived_from,
values: self.values.unwrap_or_default(),
};
evs.validate(lvl)?;
Ok(evs)
}
}
impl EnumeratedValues {
pub fn default_value(&self) -> Option<&EnumeratedValue> {
self.values.iter().find(|&v| v.is_default())
}
pub fn builder() -> EnumeratedValuesBuilder {
EnumeratedValuesBuilder::default()
}
pub fn modify_from(
&mut self,
builder: EnumeratedValuesBuilder,
lvl: ValidateLevel,
) -> Result<(), SvdError> {
if builder.derived_from.is_some() {
self.name = None;
self.usage = None;
self.values = Vec::new();
} else {
if builder.name.is_some() {
self.name = builder.name.empty_to_none();
}
if builder.usage.is_some() {
self.usage = builder.usage;
}
if let Some(values) = builder.values {
self.values = values;
}
}
self.validate(lvl)
}
pub fn validate(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
if !lvl.is_disabled() {
if lvl.is_strict() {
if let Some(name) = self.name.as_ref() {
super::check_name(name, "name")?;
}
}
if let Some(_dname) = self.derived_from.as_ref() {
if lvl.is_strict() {
super::check_derived_name(_dname, "derivedFrom")?;
}
Ok(())
} else if self.values.is_empty() {
Err(Error::Empty.into())
} else {
Ok(())
}
} else {
Ok(())
}
}
pub fn validate_all(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
for ev in &self.values {
ev.validate(lvl)?;
}
self.validate(lvl)
}
pub(crate) fn check_range(&self, range: core::ops::Range<u64>) -> Result<(), SvdError> {
for v in self.values.iter() {
v.check_range(&range)?;
}
Ok(())
}
pub fn usage(&self) -> Option<Usage> {
if self.derived_from.is_some() {
None
} else {
Some(self.usage.unwrap_or_default())
}
}
pub fn get_value(&self, name: &str) -> Option<&EnumeratedValue> {
self.values.iter().find(|e| e.name == name)
}
pub fn get_mut_value(&mut self, name: &str) -> Option<&mut EnumeratedValue> {
self.values.iter_mut().find(|e| e.name == name)
}
}