|
1 | | -#[cfg(feature = "unproven")] |
2 | | -use std::collections::HashMap; |
| 1 | +use core::ops::Deref; |
3 | 2 |
|
4 | | -use crate::elementext::ElementExt; |
5 | | -use failure::ResultExt; |
6 | 3 | use xmltree::Element; |
7 | 4 |
|
8 | | -#[cfg(feature = "unproven")] |
9 | | -use crate::encode::Encode; |
10 | | -use crate::error::*; |
11 | | -#[cfg(feature = "unproven")] |
12 | | -use crate::new_element; |
13 | | -use crate::parse; |
14 | 5 | use crate::types::Parse; |
15 | 6 |
|
16 | | -use crate::svd::{ |
17 | | - access::Access, bitrange::BitRange, enumeratedvalues::EnumeratedValues, |
18 | | - modifiedwritevalues::ModifiedWriteValues, writeconstraint::WriteConstraint, |
19 | | -}; |
| 7 | +#[cfg(feature = "unproven")] |
| 8 | +use crate::elementext::ElementExt; |
| 9 | +#[cfg(feature = "unproven")] |
| 10 | +use crate::encode::Encode; |
| 11 | +use crate::error::SVDError; |
| 12 | +use crate::svd::{dimelement::DimElement, fieldinfo::FieldInfo}; |
20 | 13 |
|
21 | 14 | #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] |
22 | 15 | #[derive(Clone, Debug, PartialEq)] |
23 | | -pub struct Field { |
24 | | - pub name: String, |
25 | | - pub derived_from: Option<String>, |
26 | | - pub description: Option<String>, |
27 | | - pub bit_range: BitRange, |
28 | | - pub access: Option<Access>, |
29 | | - pub enumerated_values: Vec<EnumeratedValues>, |
30 | | - pub write_constraint: Option<WriteConstraint>, |
31 | | - pub modified_write_values: Option<ModifiedWriteValues>, |
32 | | - // Reserve the right to add more fields to this struct |
33 | | - pub(crate) _extensible: (), |
| 16 | +pub enum Field { |
| 17 | + Single(FieldInfo), |
| 18 | + Array(FieldInfo, DimElement), |
| 19 | +} |
| 20 | + |
| 21 | +impl Deref for Field { |
| 22 | + type Target = FieldInfo; |
| 23 | + |
| 24 | + fn deref(&self) -> &FieldInfo { |
| 25 | + match self { |
| 26 | + Field::Single(info) => info, |
| 27 | + Field::Array(info, _) => info, |
| 28 | + } |
| 29 | + } |
34 | 30 | } |
35 | 31 |
|
36 | 32 | impl Parse for Field { |
37 | 33 | type Object = Field; |
38 | 34 | type Error = SVDError; |
| 35 | + |
39 | 36 | fn parse(tree: &Element) -> Result<Field, SVDError> { |
40 | | - if tree.name != "field" { |
41 | | - return Err(SVDErrorKind::NotExpectedTag(tree.clone(), "field".to_string()).into()); |
| 37 | + assert_eq!(tree.name, "field"); |
| 38 | + |
| 39 | + let info = FieldInfo::parse(tree)?; |
| 40 | + |
| 41 | + if tree.get_child("dimIncrement").is_some() { |
| 42 | + let array_info = DimElement::parse(tree)?; |
| 43 | + assert!(info.name.contains("%s")); |
| 44 | + if let Some(indices) = &array_info.dim_index { |
| 45 | + assert_eq!(array_info.dim as usize, indices.len()) |
| 46 | + } |
| 47 | + Ok(Field::Array(info, array_info)) |
| 48 | + } else { |
| 49 | + Ok(Field::Single(info)) |
42 | 50 | } |
43 | | - let name = tree.get_child_text("name")?; |
44 | | - Field::_parse(tree, name.clone()) |
45 | | - .context(SVDErrorKind::Other(format!("In field `{}`", name))) |
46 | | - .map_err(|e| e.into()) |
47 | | - } |
48 | | -} |
49 | | - |
50 | | -impl Field { |
51 | | - fn _parse(tree: &Element, name: String) -> Result<Field, SVDError> { |
52 | | - Ok(Field { |
53 | | - name, |
54 | | - derived_from: tree.attributes.get("derivedFrom").map(|s| s.to_owned()), |
55 | | - description: tree.get_child_text_opt("description")?, |
56 | | - bit_range: BitRange::parse(tree)?, |
57 | | - access: parse::optional::<Access>("access", tree)?, |
58 | | - enumerated_values: { |
59 | | - let values: Result<Vec<_>, _> = tree |
60 | | - .children |
61 | | - .iter() |
62 | | - .filter(|t| t.name == "enumeratedValues") |
63 | | - .map(EnumeratedValues::parse) |
64 | | - .collect(); |
65 | | - values? |
66 | | - }, |
67 | | - write_constraint: parse::optional::<WriteConstraint>("writeConstraint", tree)?, |
68 | | - modified_write_values: parse::optional::<ModifiedWriteValues>( |
69 | | - "modifiedWriteValues", |
70 | | - tree, |
71 | | - )?, |
72 | | - _extensible: (), |
73 | | - }) |
74 | 51 | } |
75 | 52 | } |
76 | 53 |
|
77 | 54 | #[cfg(feature = "unproven")] |
78 | 55 | impl Encode for Field { |
79 | 56 | type Error = SVDError; |
80 | | - fn encode(&self) -> Result<Element, SVDError> { |
81 | | - let mut children = vec![new_element("name", Some(self.name.clone()))]; |
82 | | - |
83 | | - if let Some(description) = &self.description { |
84 | | - children.push(new_element("description", Some(description.clone()))) |
85 | | - } |
86 | | - |
87 | | - let mut elem = Element { |
88 | | - prefix: None, |
89 | | - namespace: None, |
90 | | - namespaces: None, |
91 | | - name: String::from("field"), |
92 | | - attributes: HashMap::new(), |
93 | | - children, |
94 | | - text: None, |
95 | | - }; |
96 | 57 |
|
97 | | - if let Some(v) = &self.derived_from { |
98 | | - elem.attributes |
99 | | - .insert(String::from("derivedFrom"), format!("{}", v)); |
| 58 | + fn encode(&self) -> Result<Element, SVDError> { |
| 59 | + match self { |
| 60 | + Field::Single(info) => info.encode(), |
| 61 | + Field::Array(info, array_info) => { |
| 62 | + // TODO: is this correct? probably not, need tests |
| 63 | + let base = info.encode()?; |
| 64 | + base.merge(&array_info.encode()?); |
| 65 | + Ok(base) |
| 66 | + } |
100 | 67 | } |
101 | | - |
102 | | - // Add bit range |
103 | | - elem.children.append(&mut self.bit_range.encode()?); |
104 | | - |
105 | | - if let Some(v) = &self.access { |
106 | | - elem.children.push(v.encode()?); |
107 | | - }; |
108 | | - |
109 | | - let enumerated_values: Result<Vec<Element>, SVDError> = |
110 | | - self.enumerated_values.iter().map(|v| v.encode()).collect(); |
111 | | - elem.children.append(&mut enumerated_values?); |
112 | | - |
113 | | - if let Some(v) = &self.write_constraint { |
114 | | - elem.children.push(v.encode()?); |
115 | | - }; |
116 | | - |
117 | | - if let Some(v) = &self.modified_write_values { |
118 | | - elem.children.push(v.encode()?); |
119 | | - }; |
120 | | - |
121 | | - Ok(elem) |
122 | 68 | } |
123 | 69 | } |
124 | 70 |
|
125 | | -#[cfg(test)] |
126 | | -#[cfg(feature = "unproven")] |
127 | | -mod tests { |
128 | | - use super::*; |
129 | | - use crate::run_test; |
130 | | - use crate::svd::{bitrange::BitRangeType, enumeratedvalue::EnumeratedValue}; |
131 | | - |
132 | | - #[test] |
133 | | - fn decode_encode() { |
134 | | - let tests = vec![ |
135 | | - ( |
136 | | - Field { |
137 | | - name: String::from("MODE"), |
138 | | - derived_from: None, |
139 | | - description: Some(String::from("Read Mode")), |
140 | | - bit_range: BitRange { |
141 | | - offset: 24, |
142 | | - width: 2, |
143 | | - range_type: BitRangeType::OffsetWidth, |
144 | | - }, |
145 | | - access: Some(Access::ReadWrite), |
146 | | - enumerated_values: vec![EnumeratedValues { |
147 | | - name: None, |
148 | | - usage: None, |
149 | | - derived_from: None, |
150 | | - values: vec![EnumeratedValue { |
151 | | - name: String::from("WS0"), |
152 | | - description: Some(String::from( |
153 | | - "Zero wait-states inserted in fetch or read transfers", |
154 | | - )), |
155 | | - value: Some(0), |
156 | | - is_default: None, |
157 | | - _extensible: (), |
158 | | - }], |
159 | | - _extensible: (), |
160 | | - }], |
161 | | - write_constraint: None, |
162 | | - modified_write_values: None, |
163 | | - _extensible: (), |
164 | | - }, |
165 | | - " |
166 | | - <field> |
167 | | - <name>MODE</name> |
168 | | - <description>Read Mode</description> |
169 | | - <bitOffset>24</bitOffset> |
170 | | - <bitWidth>2</bitWidth> |
171 | | - <access>read-write</access> |
172 | | - <enumeratedValues> |
173 | | - <enumeratedValue> |
174 | | - <name>WS0</name> |
175 | | - <description>Zero wait-states inserted in fetch or read transfers</description> |
176 | | - <value>0x00000000</value> |
177 | | - </enumeratedValue> |
178 | | - </enumeratedValues> |
179 | | - </field> |
180 | | - ", |
181 | | - ), |
182 | | - ( |
183 | | - Field { |
184 | | - name: String::from("MODE"), |
185 | | - derived_from: Some(String::from("other field")), |
186 | | - description: None, |
187 | | - bit_range: BitRange { |
188 | | - offset: 24, |
189 | | - width: 2, |
190 | | - range_type: BitRangeType::OffsetWidth, |
191 | | - }, |
192 | | - access: None, |
193 | | - enumerated_values: vec![], |
194 | | - write_constraint: None, |
195 | | - modified_write_values: None, |
196 | | - _extensible: (), |
197 | | - }, |
198 | | - " |
199 | | - <field derivedFrom=\"other field\"> |
200 | | - <name>MODE</name> |
201 | | - <bitOffset>24</bitOffset> |
202 | | - <bitWidth>2</bitWidth> |
203 | | - </field> |
204 | | - ", |
205 | | - ), |
206 | | - ]; |
207 | | - |
208 | | - run_test::<Field>(&tests[..]); |
209 | | - } |
210 | | -} |
| 71 | +// TODO: add Field encode and decode tests |
0 commit comments