1use super::{
2 array::{descriptions, names},
3 bitrange, Access, BitRange, BuildError, Description, DimElement, EmptyToNone, EnumeratedValues,
4 MaybeArray, ModifiedWriteValues, Name, ReadAction, SvdError, Usage, ValidateLevel,
5 WriteConstraint,
6};
7use std::ops::Deref;
8
9pub type Field = MaybeArray<FieldInfo>;
11
12#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
14pub enum Error {
15 #[error("You can have 0, 1 or 2 enumeratedValues with different usage")]
17 IncompatibleEnumeratedValues,
18}
19
20#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
22#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
23#[derive(Clone, Debug, PartialEq, Eq)]
24#[non_exhaustive]
25pub struct FieldInfo {
26 pub name: String,
29
30 #[cfg_attr(
32 feature = "serde",
33 serde(default, skip_serializing_if = "Option::is_none")
34 )]
35 pub description: Option<String>,
36
37 #[cfg_attr(feature = "serde", serde(flatten))]
39 pub bit_range: BitRange,
40
41 #[cfg_attr(
44 feature = "serde",
45 serde(default, skip_serializing_if = "Option::is_none")
46 )]
47 pub access: Option<Access>,
48
49 #[cfg_attr(
51 feature = "serde",
52 serde(default, skip_serializing_if = "Option::is_none")
53 )]
54 pub modified_write_values: Option<ModifiedWriteValues>,
55
56 #[cfg_attr(
58 feature = "serde",
59 serde(default, skip_serializing_if = "Option::is_none")
60 )]
61 pub write_constraint: Option<WriteConstraint>,
62
63 #[cfg_attr(
66 feature = "serde",
67 serde(default, skip_serializing_if = "Option::is_none")
68 )]
69 pub read_action: Option<ReadAction>,
70
71 #[cfg_attr(
73 feature = "serde",
74 serde(default, skip_serializing_if = "Vec::is_empty")
75 )]
76 pub enumerated_values: Vec<EnumeratedValues>,
77
78 #[cfg_attr(
81 feature = "serde",
82 serde(default, skip_serializing_if = "Option::is_none")
83 )]
84 pub derived_from: Option<String>,
85}
86
87pub fn bit_offsets<'a>(info: &'a FieldInfo, dim: &'a DimElement) -> impl Iterator<Item = u32> + 'a {
89 (0..dim.dim).map(|i| info.bit_offset() + i * dim.dim_increment)
90}
91
92pub fn expand<'a>(
94 info: &'a FieldInfo,
95 dim: &'a DimElement,
96) -> impl Iterator<Item = FieldInfo> + 'a {
97 names(info, dim)
98 .zip(descriptions(info, dim))
99 .zip(bit_offsets(info, dim))
100 .map(|((name, description), bit_offset)| {
101 let mut info = info.clone();
102 info.name = name;
103 info.description = description;
104 info.bit_range = BitRange::from_offset_width(bit_offset, info.bit_width());
105 info
106 })
107}
108
109#[derive(Clone, Debug, Default, PartialEq, Eq)]
112pub struct FieldInfoBuilder {
113 name: Option<String>,
114 description: Option<String>,
115 bit_range: Option<BitRange>,
116 bit_offset: Option<u32>,
117 bit_width: Option<u32>,
118 access: Option<Access>,
119 modified_write_values: Option<ModifiedWriteValues>,
120 write_constraint: Option<WriteConstraint>,
121 read_action: Option<ReadAction>,
122 enumerated_values: Option<Vec<EnumeratedValues>>,
123 derived_from: Option<String>,
124}
125
126impl From<FieldInfo> for FieldInfoBuilder {
127 fn from(f: FieldInfo) -> Self {
128 Self {
129 name: Some(f.name),
130 description: f.description,
131 bit_range: Some(f.bit_range),
132 bit_offset: None,
133 bit_width: None,
134 access: f.access,
135 modified_write_values: f.modified_write_values,
136 write_constraint: f.write_constraint,
137 read_action: f.read_action,
138 enumerated_values: Some(f.enumerated_values),
139 derived_from: f.derived_from,
140 }
141 }
142}
143
144impl FieldInfoBuilder {
145 pub fn name(mut self, value: String) -> Self {
147 self.name = Some(value);
148 self
149 }
150 pub fn description(mut self, value: Option<String>) -> Self {
152 self.description = value;
153 self
154 }
155 pub fn bit_range(mut self, value: BitRange) -> Self {
157 self.bit_range = Some(value);
158 self.bit_offset = None;
159 self.bit_width = None;
160 self
161 }
162 pub fn bit_offset(mut self, value: u32) -> Self {
164 if let Some(bit_range) = self.bit_range.as_mut() {
165 bit_range.offset = value;
166 } else if let Some(width) = self.bit_offset {
167 self.bit_range = Some(BitRange::from_offset_width(value, width));
168 self.bit_width = None;
169 } else {
170 self.bit_offset = Some(value);
171 }
172 self
173 }
174 pub fn bit_width(mut self, value: u32) -> Self {
176 if let Some(bit_range) = self.bit_range.as_mut() {
177 bit_range.width = value;
178 } else if let Some(offset) = self.bit_offset {
179 self.bit_range = Some(BitRange::from_offset_width(offset, value));
180 self.bit_offset = None;
181 } else {
182 self.bit_width = Some(value);
183 }
184 self
185 }
186 pub fn access(mut self, value: Option<Access>) -> Self {
188 self.access = value;
189 self
190 }
191 pub fn modified_write_values(mut self, value: Option<ModifiedWriteValues>) -> Self {
193 self.modified_write_values = value;
194 self
195 }
196 pub fn write_constraint(mut self, value: Option<WriteConstraint>) -> Self {
198 self.write_constraint = value;
199 self
200 }
201 pub fn read_action(mut self, value: Option<ReadAction>) -> Self {
203 self.read_action = value;
204 self
205 }
206 pub fn enumerated_values(mut self, value: Vec<EnumeratedValues>) -> Self {
208 self.enumerated_values = Some(value);
209 self
210 }
211 pub fn derived_from(mut self, value: Option<String>) -> Self {
213 self.derived_from = value;
214 self
215 }
216 pub fn build(self, lvl: ValidateLevel) -> Result<FieldInfo, SvdError> {
218 let field = FieldInfo {
219 name: self
220 .name
221 .ok_or_else(|| BuildError::Uninitialized("name".to_string()))?,
222 description: self.description.empty_to_none(),
223 bit_range: self
224 .bit_range
225 .ok_or_else(|| BuildError::Uninitialized("bit_range".to_string()))?,
226 access: self.access,
227 modified_write_values: self.modified_write_values,
228 write_constraint: self.write_constraint,
229 read_action: self.read_action,
230 enumerated_values: self.enumerated_values.unwrap_or_default(),
231 derived_from: self.derived_from,
232 };
233 field.validate(lvl)?;
234 Ok(field)
235 }
236}
237
238impl FieldInfo {
239 pub fn builder() -> FieldInfoBuilder {
241 FieldInfoBuilder::default()
242 }
243 pub const fn single(self) -> Field {
245 Field::Single(self)
246 }
247 pub const fn array(self, dim: DimElement) -> Field {
249 Field::Array(self, dim)
250 }
251 pub fn maybe_array(self, dim: Option<DimElement>) -> Field {
253 if let Some(dim) = dim {
254 self.array(dim)
255 } else {
256 self.single()
257 }
258 }
259 pub fn modify_from(
261 &mut self,
262 builder: FieldInfoBuilder,
263 lvl: ValidateLevel,
264 ) -> Result<(), SvdError> {
265 if let Some(name) = builder.name {
266 self.name = name;
267 }
268 if builder.description.is_some() {
269 self.description = builder.description.empty_to_none();
270 }
271 if let Some(bit_range) = builder.bit_range {
272 self.bit_range = bit_range;
273 }
274 if let Some(offset) = builder.bit_offset {
275 self.bit_range.offset = offset;
276 }
277 if let Some(width) = builder.bit_width {
278 self.bit_range.width = width;
279 }
280 if builder.access.is_some() {
281 self.access = builder.access;
282 }
283 if builder.derived_from.is_some() {
284 self.derived_from = builder.derived_from;
285 self.modified_write_values = None;
286 self.write_constraint = None;
287 self.enumerated_values = Vec::new();
288 } else {
289 if builder.modified_write_values.is_some() {
290 self.modified_write_values = builder.modified_write_values;
291 }
292 if builder.write_constraint.is_some() {
293 self.write_constraint = builder.write_constraint;
294 }
295 if builder.read_action.is_some() {
296 self.read_action = builder.read_action;
297 }
298 if let Some(enumerated_values) = builder.enumerated_values {
299 self.enumerated_values = enumerated_values;
300 }
301 }
302 self.validate(lvl)
303 }
304 pub fn validate(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
306 if !lvl.is_disabled() {
307 if lvl.is_strict() {
308 super::check_dimable_name(&self.name, "name")?;
309 if let Some(name) = self.derived_from.as_ref() {
310 super::check_derived_name(name, "derivedFrom")?;
311 }
312 }
313
314 if self.bit_range.width == 0 {
315 return Err(bitrange::Error::ZeroWidth.into());
316 }
317
318 if self.bit_range.width < 64 {
321 for ev in &self.enumerated_values {
322 ev.check_range(0..2_u64.pow(self.bit_range.width))?;
323 }
324 }
325
326 if lvl.is_strict() {
327 match self.enumerated_values.as_slice() {
328 [] | [_] => {}
329 [ev1, ev2]
330 if matches!(ev1.usage(), None | Some(Usage::Read))
331 && matches!(ev2.usage(), None | Some(Usage::Write)) => {}
332 [ev1, ev2]
333 if matches!(ev2.usage(), None | Some(Usage::Read))
334 && matches!(ev1.usage(), None | Some(Usage::Write)) => {}
335 _ => return Err(Error::IncompatibleEnumeratedValues.into()),
336 }
337 }
338
339 match self.write_constraint {
340 Some(WriteConstraint::Range(constraint)) if self.bit_range.width < 64 => {
343 constraint.check_range(0..2_u64.pow(self.bit_range.width))?;
344 }
345 _ => (),
346 }
347 }
348
349 Ok(())
350 }
351 pub fn validate_all(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
353 for evs in &self.enumerated_values {
354 evs.validate_all(lvl)?;
355 }
356 self.validate(lvl)
357 }
358
359 pub fn bit_offset(&self) -> u32 {
361 self.bit_range.offset
362 }
363
364 pub fn bit_width(&self) -> u32 {
366 self.bit_range.width
367 }
368
369 pub fn lsb(&self) -> u32 {
371 self.bit_range.lsb()
372 }
373 pub fn msb(&self) -> u32 {
375 self.bit_range.msb()
376 }
377
378 pub fn bitmask(&self) -> u64 {
380 let BitRange { offset, width, .. } = self.bit_range;
381 (!0u64 >> (64 - width)) << offset
382 }
383
384 pub fn get_enumerated_values(&self, usage: Usage) -> Option<&EnumeratedValues> {
386 match self.enumerated_values.len() {
387 1 | 2 => self
388 .enumerated_values
389 .iter()
390 .find(|ev| ev.usage() == Some(usage)),
391 _ => None,
392 }
393 }
394
395 pub fn get_mut_enumerated_values(&mut self, usage: Usage) -> Option<&mut EnumeratedValues> {
397 match self.enumerated_values.len() {
398 1 | 2 => self
399 .enumerated_values
400 .iter_mut()
401 .find(|ev| ev.usage() == Some(usage)),
402 _ => None,
403 }
404 }
405}
406
407impl Field {
408 pub fn validate_all(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
410 if let Self::Array(_, dim) = self {
411 dim.validate(lvl)?;
412 }
413 self.deref().validate_all(lvl)
414 }
415
416 pub fn bitmask(&self) -> u64 {
418 match self {
419 Field::Single(f) => f.bitmask(),
420 Field::Array(f, d) => {
421 let mask = f.bitmask();
422 let mut bits = 0;
423 for i in 0..d.dim {
424 bits |= mask << (i * d.dim_increment);
425 }
426 bits
427 }
428 }
429 }
430}
431
432impl Name for FieldInfo {
433 fn name(&self) -> &str {
434 &self.name
435 }
436}
437
438impl Description for FieldInfo {
439 fn description(&self) -> Option<&str> {
440 self.description.as_deref()
441 }
442}