|
1 | 1 | use std::borrow::Cow;
|
2 |
| -use std::rc::Rc; |
3 | 2 |
|
4 |
| -use either::Either; |
5 | 3 | use inflections::Inflect;
|
6 |
| -use svd::{Access, EnumeratedValues, Field, Peripheral, Register, RegisterInfo, |
| 4 | +use svd::{self, Access, EnumeratedValues, Field, Peripheral, Register, |
7 | 5 | Usage};
|
8 |
| -use syn::{Ident, IntTy, Lit}; |
| 6 | +use syn::{self, Ident, IntTy, Lit}; |
9 | 7 |
|
10 | 8 | use errors::*;
|
11 | 9 |
|
| 10 | +pub const BITS_PER_BYTE: u32 = 8; |
| 11 | + |
12 | 12 | /// List of chars that some vendors use in their peripheral/field names but
|
13 | 13 | /// that are not valid in Rust ident
|
14 | 14 | const BLACKLIST_CHARS: &'static [char] = &['(', ')', '[', ']'];
|
@@ -136,86 +136,114 @@ pub fn respace(s: &str) -> String {
|
136 | 136 | s.split_whitespace().collect::<Vec<_>>().join(" ")
|
137 | 137 | }
|
138 | 138 |
|
139 |
| -pub struct ExpandedRegister<'a> { |
140 |
| - pub info: &'a RegisterInfo, |
141 |
| - pub name: String, |
142 |
| - pub offset: u32, |
143 |
| - pub ty: Either<String, Rc<String>>, |
144 |
| -} |
| 139 | +/// Takes a svd::Register which may be a register array, and turn in into |
| 140 | +/// a list of syn::Field where the register arrays have been expanded. |
| 141 | +pub fn expand_svd_register(register: &Register) -> Vec<syn::Field> { |
| 142 | + let name_to_ty = |name: &String| -> syn::Ty { |
| 143 | + syn::Ty::Path(None, syn::Path{ |
| 144 | + global: false, |
| 145 | + segments: vec![syn::PathSegment{ |
| 146 | + ident: Ident::new(name.to_sanitized_upper_case()), |
| 147 | + parameters: syn::PathParameters::none(), |
| 148 | + }], |
| 149 | + }) |
| 150 | + }; |
145 | 151 |
|
146 |
| -/// Takes a list of "registers", some of which may actually be register arrays, |
147 |
| -/// and turns it into a new *sorted* (by address offset) list of registers where |
148 |
| -/// the register arrays have been expanded. |
149 |
| -pub fn expand(registers: &[Register]) -> Vec<ExpandedRegister> { |
150 | 152 | let mut out = vec![];
|
151 | 153 |
|
152 |
| - for r in registers { |
153 |
| - match *r { |
154 |
| - Register::Single(ref info) => { |
155 |
| - out.push( |
156 |
| - ExpandedRegister { |
157 |
| - info: info, |
158 |
| - name: info.name.to_sanitized_snake_case().into_owned(), |
159 |
| - offset: info.address_offset, |
160 |
| - ty: Either::Left( |
161 |
| - info.name |
162 |
| - .to_sanitized_upper_case() |
163 |
| - .into_owned(), |
164 |
| - ), |
| 154 | + match *register { |
| 155 | + Register::Single(ref _info) => out.push( convert_svd_register(register) ), |
| 156 | + Register::Array(ref info, ref array_info) => { |
| 157 | + let has_brackets = info.name.contains("[%s]"); |
| 158 | + |
| 159 | + let indices = array_info |
| 160 | + .dim_index |
| 161 | + .as_ref() |
| 162 | + .map(|v| Cow::from(&**v)) |
| 163 | + .unwrap_or_else( |
| 164 | + || { |
| 165 | + Cow::from( |
| 166 | + (0..array_info.dim) |
| 167 | + .map(|i| i.to_string()) |
| 168 | + .collect::<Vec<_>>(), |
| 169 | + ) |
165 | 170 | },
|
166 |
| - ) |
167 |
| - } |
168 |
| - Register::Array(ref info, ref array_info) => { |
169 |
| - let has_brackets = info.name.contains("[%s]"); |
170 |
| - |
171 |
| - let ty = if has_brackets { |
| 171 | + ); |
| 172 | + |
| 173 | + for (idx, _i) in indices.iter().zip(0..) { |
| 174 | + let name = if has_brackets { |
| 175 | + info.name.replace("[%s]", format!("{}", idx).as_str()) |
| 176 | + } else { |
| 177 | + info.name.replace("%s", format!("{}", idx).as_str()) |
| 178 | + }; |
| 179 | + |
| 180 | + let ty_name = if has_brackets { |
172 | 181 | info.name.replace("[%s]", "")
|
173 | 182 | } else {
|
174 | 183 | info.name.replace("%s", "")
|
175 | 184 | };
|
| 185 | + |
| 186 | + let ident = Ident::new(name.to_sanitized_snake_case()); |
| 187 | + let ty = name_to_ty(&ty_name); |
176 | 188 |
|
177 |
| - let ty = Rc::new(ty.to_sanitized_upper_case().into_owned()); |
178 |
| - |
179 |
| - let indices = array_info |
180 |
| - .dim_index |
181 |
| - .as_ref() |
182 |
| - .map(|v| Cow::from(&**v)) |
183 |
| - .unwrap_or_else( |
184 |
| - || { |
185 |
| - Cow::from( |
186 |
| - (0..array_info.dim) |
187 |
| - .map(|i| i.to_string()) |
188 |
| - .collect::<Vec<_>>(), |
189 |
| - ) |
190 |
| - }, |
191 |
| - ); |
192 |
| - |
193 |
| - for (idx, i) in indices.iter().zip(0..) { |
194 |
| - let name = if has_brackets { |
195 |
| - info.name.replace("[%s]", idx) |
196 |
| - } else { |
197 |
| - info.name.replace("%s", idx) |
198 |
| - }; |
199 |
| - |
200 |
| - let offset = info.address_offset + |
201 |
| - i * array_info.dim_increment; |
202 |
| - |
203 |
| - out.push( |
204 |
| - ExpandedRegister { |
205 |
| - info: info, |
206 |
| - name: name.to_sanitized_snake_case().into_owned(), |
207 |
| - offset: offset, |
208 |
| - ty: Either::Right(ty.clone()), |
209 |
| - }, |
210 |
| - ); |
211 |
| - } |
| 189 | + out.push( |
| 190 | + syn::Field{ |
| 191 | + ident: Some(ident), |
| 192 | + vis: syn::Visibility::Public, |
| 193 | + attrs: vec![], |
| 194 | + ty: ty, |
| 195 | + } |
| 196 | + ); |
212 | 197 | }
|
213 |
| - } |
| 198 | + }, |
214 | 199 | }
|
| 200 | + out |
| 201 | +} |
215 | 202 |
|
216 |
| - out.sort_by_key(|x| x.offset); |
| 203 | +pub fn convert_svd_register(register: &svd::Register) -> syn::Field { |
| 204 | + let name_to_ty = |name: &String| -> syn::Ty { |
| 205 | + syn::Ty::Path(None, syn::Path{ |
| 206 | + global: false, |
| 207 | + segments: vec![syn::PathSegment{ |
| 208 | + ident: Ident::new(name.to_sanitized_upper_case()), |
| 209 | + parameters: syn::PathParameters::none(), |
| 210 | + }], |
| 211 | + }) |
| 212 | + }; |
| 213 | + |
| 214 | + match *register { |
| 215 | + Register::Single(ref info) => { |
| 216 | + syn::Field{ |
| 217 | + ident: Some(Ident::new(info.name.to_sanitized_snake_case())), |
| 218 | + vis: syn::Visibility::Public, |
| 219 | + attrs: vec![], |
| 220 | + ty: name_to_ty(&info.name), |
| 221 | + } |
| 222 | + }, |
| 223 | + Register::Array(ref info, ref array_info) => { |
| 224 | + let has_brackets = info.name.contains("[%s]"); |
217 | 225 |
|
218 |
| - out |
| 226 | + let name = if has_brackets { |
| 227 | + info.name.replace("[%s]", "") |
| 228 | + } else { |
| 229 | + info.name.replace("%s", "") |
| 230 | + }; |
| 231 | + |
| 232 | + let ident = Ident::new(name.to_sanitized_snake_case()); |
| 233 | + |
| 234 | + let ty = syn::Ty::Array( |
| 235 | + Box::new(name_to_ty(&name)), |
| 236 | + syn::ConstExpr::Lit(syn::Lit::Int(array_info.dim as u64, syn::IntTy::Unsuffixed)), |
| 237 | + ); |
| 238 | + |
| 239 | + syn::Field{ |
| 240 | + ident: Some(ident), |
| 241 | + vis: syn::Visibility::Public, |
| 242 | + attrs: vec![], |
| 243 | + ty: ty, |
| 244 | + } |
| 245 | + }, |
| 246 | + } |
219 | 247 | }
|
220 | 248 |
|
221 | 249 | pub fn name_of(register: &Register) -> Cow<str> {
|
|
0 commit comments