svd_rs/
enumeratedvalue.rs1use super::{BuildError, Description, EmptyToNone, Name, SvdError, ValidateLevel};
2
3#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
5#[derive(Clone, Debug, PartialEq, Eq)]
6#[non_exhaustive]
7pub struct EnumeratedValue {
8 pub name: String,
10
11 #[cfg_attr(
13 feature = "serde",
14 serde(default, skip_serializing_if = "Option::is_none")
15 )]
16 pub description: Option<String>,
17
18 #[cfg_attr(
20 feature = "serde",
21 serde(default, skip_serializing_if = "Option::is_none")
22 )]
23 pub value: Option<u64>,
24
25 #[cfg_attr(
27 feature = "serde",
28 serde(default, skip_serializing_if = "Option::is_none")
29 )]
30 pub is_default: Option<bool>,
31}
32
33#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
35pub enum Error {
36 #[error("EnumeratedValue has no `value` or `is_default`")]
38 AbsentValue,
39 #[error("EnumeratedValue with `value` (passed {0:?}) should not have `is_default(True)`")]
41 ValueAndDefault(Option<u64>),
42 #[error("Value {0} out of range [{} - {}]", .1.start, .1.end - 1)]
44 OutOfRange(u64, core::ops::Range<u64>),
45}
46
47#[derive(Clone, Debug, Default, PartialEq, Eq)]
49pub struct EnumeratedValueBuilder {
50 name: Option<String>,
51 description: Option<String>,
52 value: Option<u64>,
53 is_default: Option<bool>,
54}
55
56impl From<EnumeratedValue> for EnumeratedValueBuilder {
57 fn from(e: EnumeratedValue) -> Self {
58 Self {
59 name: Some(e.name),
60 description: e.description,
61 value: e.value,
62 is_default: e.is_default,
63 }
64 }
65}
66
67impl EnumeratedValueBuilder {
68 pub fn name(mut self, value: String) -> Self {
70 self.name = Some(value);
71 self
72 }
73 pub fn description(mut self, value: Option<String>) -> Self {
75 self.description = value;
76 self
77 }
78 pub fn value(mut self, value: Option<u64>) -> Self {
80 self.value = value;
81 self
82 }
83 #[allow(clippy::wrong_self_convention)]
84 pub fn is_default(mut self, value: Option<bool>) -> Self {
86 self.is_default = value;
87 self
88 }
89 pub fn build(self, lvl: ValidateLevel) -> Result<EnumeratedValue, SvdError> {
91 let ev = EnumeratedValue {
92 name: self
93 .name
94 .ok_or_else(|| BuildError::Uninitialized("name".to_string()))?,
95 description: self.description.empty_to_none(),
96 value: self.value,
97 is_default: self.is_default,
98 };
99 ev.validate(lvl)?;
100 Ok(ev)
101 }
102}
103
104impl EnumeratedValue {
105 pub fn is_default(&self) -> bool {
107 matches!(self.is_default, Some(true))
108 }
109 pub fn builder() -> EnumeratedValueBuilder {
111 EnumeratedValueBuilder::default()
112 }
113 pub fn modify_from(
115 &mut self,
116 builder: EnumeratedValueBuilder,
117 lvl: ValidateLevel,
118 ) -> Result<(), SvdError> {
119 if let Some(name) = builder.name {
120 self.name = name;
121 }
122 if builder.description.is_some() {
123 self.description = builder.description.empty_to_none();
124 }
125 if builder.value.is_some() {
126 self.value = builder.value;
127 }
128 if builder.is_default.is_some() {
129 self.is_default = builder.is_default;
130 }
131 self.validate(lvl)
132 }
133 pub fn validate(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
135 if !lvl.is_disabled() {
136 if lvl.is_strict() {
137 super::check_name(&self.name, "name")?;
138 }
139 match (self.value.is_some(), self.is_default()) {
140 (false, false) => Err(Error::AbsentValue.into()),
141 (true, true) if lvl.is_strict() => Err(Error::ValueAndDefault(self.value).into()),
142 _ => Ok(()),
143 }
144 } else {
145 Ok(())
146 }
147 }
148 pub(crate) fn check_range(&self, range: &core::ops::Range<u64>) -> Result<(), SvdError> {
149 match &self.value {
150 Some(x) if !range.contains(x) => Err(Error::OutOfRange(*x, range.clone()).into()),
151 _ => Ok(()),
152 }
153 }
154}
155
156impl Name for EnumeratedValue {
157 fn name(&self) -> &str {
158 &self.name
159 }
160}
161
162impl Description for EnumeratedValue {
163 fn description(&self) -> Option<&str> {
164 self.description.as_deref()
165 }
166}