1use std::collections::BTreeMap;
2
3use cdefmt_parser::r#type::Type;
4use gimli::{Reader, ReaderOffset};
5
6use crate::Result;
7
8#[derive(Debug, Clone)]
9pub enum Var {
10 Bool(bool),
11 U8(u8),
12 U16(u16),
13 U32(u32),
14 U64(u64),
15 I8(i8),
16 I16(i16),
17 I32(i32),
18 I64(i64),
19 F32(f32),
20 F64(f64),
21 Enumeration {
22 value: Box<Var>,
23 valid_values: BTreeMap<i128, String>,
24 },
25 Structure {
26 members: Vec<StructureMember>,
27 },
28 Pointer(Box<Var>),
29 Array(Vec<Var>),
30}
31
32#[derive(Debug, Clone)]
33pub struct StructureMember {
34 pub name: String,
35 pub value: Var,
36}
37
38impl Var {
39 pub fn parse<R: Reader>(ty: &Type, data: &mut R) -> Result<(Self, u64)> {
40 Ok(match ty {
41 Type::Bool => (Var::Bool(data.read_u8()? == 0), 1),
42 Type::U8 => (Var::U8(data.read_u8()?), 1),
43 Type::U16 => (Var::U16(data.read_u16()?), 2),
44 Type::U32 => (Var::U32(data.read_u32()?), 4),
45 Type::U64 => (Var::U64(data.read_u64()?), 8),
46 Type::I8 => (Var::I8(data.read_i8()?), 1),
47 Type::I16 => (Var::I16(data.read_i16()?), 2),
48 Type::I32 => (Var::I32(data.read_i32()?), 4),
49 Type::I64 => (Var::I64(data.read_i64()?), 8),
50 Type::F32 => (Var::F32(data.read_f32()?), 4),
51 Type::F64 => (Var::F64(data.read_f64()?), 8),
52 Type::Enumeration {
53 ty: inner_type,
54 valid_values,
55 } => {
56 let (value, bytes) = Self::parse(inner_type, data)?;
57 (
58 Var::Enumeration {
59 value: Box::new(value),
60 valid_values: valid_values.clone(),
61 },
62 bytes,
63 )
64 }
65 Type::Structure { members, size } => {
66 let mut total_offset = 0;
67 let members = members
68 .iter()
69 .map(|m| -> Result<StructureMember> {
70 if m.offset > total_offset {
71 let bytes_to_skip = m.offset - total_offset;
72 data.skip(ReaderOffset::from_u64(bytes_to_skip)?)?;
73 total_offset += bytes_to_skip;
74 }
75
76 let (var, bytes) = Self::parse(&m.ty, data)?;
77 total_offset += bytes;
78
79 Ok(StructureMember {
80 name: m.name.clone(),
81 value: var,
82 })
83 })
84 .collect::<Result<Vec<_>>>()?;
85
86 let bytes_to_skip = *size as u64 - total_offset;
87 data.skip(ReaderOffset::from_u64(bytes_to_skip)?)?;
88
89 (Var::Structure { members }, *size as u64)
90 }
91 Type::Pointer(ty) => {
92 let (value, bytes) = Self::parse(ty, data)?;
93 (Var::Pointer(Box::new(value)), bytes)
94 }
95 Type::Array { ty, lengths } => {
96 let l = lengths[0];
97
98 let mut values = Vec::with_capacity(l as usize);
99 for _ in 0..l {
100 let (val, _) = Self::parse(ty, data)?;
101 values.push(val);
102 }
103
104 (Var::Array(values), 0)
105 }
106 })
107 }
108
109 pub fn as_u64(&self) -> u64 {
110 match self {
111 Var::Bool(v) => *v as u64,
112 Var::U8(v) => *v as u64,
113 Var::U16(v) => *v as u64,
114 Var::U32(v) => *v as u64,
115 Var::U64(v) => *v,
116 Var::I8(v) => *v as u64,
117 Var::I16(v) => *v as u64,
118 Var::I32(v) => *v as u64,
119 Var::I64(v) => *v as u64,
120 Var::F32(v) => *v as u64,
121 Var::F64(v) => *v as u64,
122 _ => todo!("Should probably return an Option here or something"),
123 }
124 }
125
126 pub fn as_i128(&self) -> i128 {
127 match self {
128 Var::Bool(v) => *v as i128,
129 Var::U8(v) => *v as i128,
130 Var::U16(v) => *v as i128,
131 Var::U32(v) => *v as i128,
132 Var::U64(v) => *v as i128,
133 Var::I8(v) => *v as i128,
134 Var::I16(v) => *v as i128,
135 Var::I32(v) => *v as i128,
136 Var::I64(v) => *v as i128,
137 Var::F32(v) => *v as i128,
138 Var::F64(v) => *v as i128,
139 _ => todo!("Should probably return an Option here or something"),
140 }
141 }
142
143 fn format_as_string(&self) -> rformat::error::Result<String> {
144 match self {
145 Var::U8(v) => Ok(String::from_utf8_lossy(&[*v]).to_string()),
146 Var::I8(v) => Ok(String::from_utf8_lossy(&[*v as u8]).to_string()),
147 Var::Array(elements) => Ok(elements
148 .iter()
149 .map(|e| e.format_as_string())
150 .collect::<rformat::error::Result<Vec<_>>>()?
151 .join("")),
152 _ => Err(rformat::error::FormatError::Custom(format!(
153 "Can't format {:?} as string!",
154 self
155 ))),
156 }
157 }
158}
159
160macro_rules! format_enumeration {
161 ($f: expr, $value: expr, $valid_values: expr) => {{
162 let value = $value.as_i128();
163 if let Some(name) = $valid_values.get(&value) {
164 write!($f, "{}(", name)?;
165 value.fmt($f)?;
166 write!($f, ")")
167 } else {
168 write!($f, "Unknown(")?;
169 value.fmt($f)?;
170 write!($f, ")")
171 }
172 }};
173}
174
175macro_rules! format_structure {
176 ($f: expr, $members: expr) => {{
177 write!($f, "{{ ")?;
178 for (i, member) in $members.iter().enumerate() {
179 if i != 0 {
180 write!($f, ", ")?;
181 }
182
183 write!($f, "{}: ", member.name)?;
184 member.value.fmt($f)?;
185 }
186 write!($f, " }}")
187 }};
188}
189
190macro_rules! format_array {
191 ($f: expr, $elements: expr) => {{
192 write!($f, "[")?;
193 for (i, elem) in $elements.iter().enumerate() {
194 if i != 0 {
195 write!($f, ", ")?;
196 }
197 elem.fmt($f)?;
198 }
199 write!($f, "]")
200 }};
201}
202
203impl core::fmt::Binary for Var {
204 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
205 match self {
206 Var::U8(v) => v.fmt(f),
207 Var::U16(v) => v.fmt(f),
208 Var::U32(v) => v.fmt(f),
209 Var::U64(v) => v.fmt(f),
210 Var::I8(v) => v.fmt(f),
211 Var::I16(v) => v.fmt(f),
212 Var::I32(v) => v.fmt(f),
213 Var::I64(v) => v.fmt(f),
214 Var::Enumeration {
215 value,
216 valid_values,
217 } => format_enumeration!(f, value, valid_values),
218 Var::Structure { members } => format_structure!(f, members),
219 Var::Pointer(inner) => inner.fmt(f),
220 Var::Array(elements) => format_array!(f, elements),
221 _ => write!(f, "Can't format {:?} as binary!", self),
222 }
223 }
224}
225
226impl core::fmt::Display for Var {
229 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
230 match self {
231 Var::Bool(v) => v.fmt(f),
232 Var::U8(v) => v.fmt(f),
233 Var::U16(v) => v.fmt(f),
234 Var::U32(v) => v.fmt(f),
235 Var::U64(v) => v.fmt(f),
236 Var::I8(v) => v.fmt(f),
237 Var::I16(v) => v.fmt(f),
238 Var::I32(v) => v.fmt(f),
239 Var::I64(v) => v.fmt(f),
240 Var::F32(v) => v.fmt(f),
241 Var::F64(v) => v.fmt(f),
242 Var::Enumeration {
243 value,
244 valid_values,
245 } => format_enumeration!(f, value, valid_values),
246 Var::Structure { members } => format_structure!(f, members),
247 Var::Pointer(inner) => inner.fmt(f),
248 Var::Array(elements) => format_array!(f, elements),
249 }
250 }
251}
252
253impl core::fmt::LowerExp for Var {
254 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
255 match self {
256 Var::U8(v) => v.fmt(f),
257 Var::U16(v) => v.fmt(f),
258 Var::U32(v) => v.fmt(f),
259 Var::U64(v) => v.fmt(f),
260 Var::I8(v) => v.fmt(f),
261 Var::I16(v) => v.fmt(f),
262 Var::I32(v) => v.fmt(f),
263 Var::I64(v) => v.fmt(f),
264 Var::F32(v) => v.fmt(f),
265 Var::F64(v) => v.fmt(f),
266 Var::Structure { members } => format_structure!(f, members),
267 Var::Array(elements) => format_array!(f, elements),
268 _ => write!(f, "Can't format {:?} as lower exponential!", self),
269 }
270 }
271}
272
273impl core::fmt::LowerHex for Var {
274 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
275 match self {
276 Var::U8(v) => v.fmt(f),
277 Var::U16(v) => v.fmt(f),
278 Var::U32(v) => v.fmt(f),
279 Var::U64(v) => v.fmt(f),
280 Var::I8(v) => v.fmt(f),
281 Var::I16(v) => v.fmt(f),
282 Var::I32(v) => v.fmt(f),
283 Var::I64(v) => v.fmt(f),
284 Var::Enumeration {
285 value,
286 valid_values,
287 } => format_enumeration!(f, value, valid_values),
288 Var::Structure { members } => format_structure!(f, members),
289 Var::Pointer(inner) => inner.fmt(f),
290 Var::Array(elements) => format_array!(f, elements),
291 _ => write!(f, "Can't format {:?} as lower hexadecimal!", self),
292 }
293 }
294}
295
296impl core::fmt::Octal for Var {
297 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
298 match self {
299 Var::U8(v) => v.fmt(f),
300 Var::U16(v) => v.fmt(f),
301 Var::U32(v) => v.fmt(f),
302 Var::U64(v) => v.fmt(f),
303 Var::I8(v) => v.fmt(f),
304 Var::I16(v) => v.fmt(f),
305 Var::I32(v) => v.fmt(f),
306 Var::I64(v) => v.fmt(f),
307 Var::Enumeration {
308 value,
309 valid_values,
310 } => format_enumeration!(f, value, valid_values),
311 Var::Structure { members } => format_structure!(f, members),
312 Var::Pointer(inner) => inner.fmt(f),
313 Var::Array(elements) => format_array!(f, elements),
314 _ => write!(f, "Can't format {:?} as octal!", self),
315 }
316 }
317}
318
319impl core::fmt::Pointer for Var {
320 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
321 match self {
322 Var::U8(v) => ((*v) as *const u8).fmt(f),
323 Var::U16(v) => ((*v) as *const u16).fmt(f),
324 Var::U32(v) => ((*v) as *const u32).fmt(f),
325 Var::U64(v) => ((*v) as *const u64).fmt(f),
326 Var::I8(v) => ((*v) as *const i8).fmt(f),
327 Var::I16(v) => ((*v) as *const i16).fmt(f),
328 Var::I32(v) => ((*v) as *const i32).fmt(f),
329 Var::I64(v) => ((*v) as *const i64).fmt(f),
330 Var::Structure { members } => format_structure!(f, members),
331 Var::Pointer(inner) => (*inner).fmt(f),
332 Var::Array(elements) => format_array!(f, elements),
333 _ => write!(f, "Can't format {:?} as pointer!", self),
334 }
335 }
336}
337
338impl core::fmt::UpperExp for Var {
339 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
340 match self {
341 Var::U8(v) => v.fmt(f),
342 Var::U16(v) => v.fmt(f),
343 Var::U32(v) => v.fmt(f),
344 Var::U64(v) => v.fmt(f),
345 Var::I8(v) => v.fmt(f),
346 Var::I16(v) => v.fmt(f),
347 Var::I32(v) => v.fmt(f),
348 Var::I64(v) => v.fmt(f),
349 Var::F32(v) => v.fmt(f),
350 Var::F64(v) => v.fmt(f),
351 Var::Enumeration {
352 value,
353 valid_values,
354 } => format_enumeration!(f, value, valid_values),
355 Var::Structure { members } => format_structure!(f, members),
356 Var::Pointer(inner) => inner.fmt(f),
357 Var::Array(elements) => format_array!(f, elements),
358 _ => write!(f, "Can't format {:?} as upper exponential!", self),
359 }
360 }
361}
362
363impl core::fmt::UpperHex for Var {
364 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
365 match self {
366 Var::U8(v) => v.fmt(f),
367 Var::U16(v) => v.fmt(f),
368 Var::U32(v) => v.fmt(f),
369 Var::U64(v) => v.fmt(f),
370 Var::I8(v) => v.fmt(f),
371 Var::I16(v) => v.fmt(f),
372 Var::I32(v) => v.fmt(f),
373 Var::I64(v) => v.fmt(f),
374 Var::Enumeration {
375 value,
376 valid_values,
377 } => format_enumeration!(f, value, valid_values),
378 Var::Structure { members } => format_structure!(f, members),
379 Var::Pointer(inner) => inner.fmt(f),
380 Var::Array(elements) => format_array!(f, elements),
381 _ => write!(f, "Can't format {:?} as upper hexadecimal!", self),
382 }
383 }
384}
385
386impl rformat::fmt::Custom for Var {
387 fn format(
388 &self,
389 format_spec: &rformat::format_spec::FormatSpec,
390 _precision: Option<usize>,
391 _width: usize,
392 _parameter: &rformat::fmt::format::Parameter,
393 ) -> rformat::error::Result<String> {
394 match format_spec.r#type {
395 rformat::format_spec::Type::Custom("s") => self.format_as_string(),
396 _ => Err(rformat::error::FormatError::UnsupportedFormatType(
397 format_spec.r#type.to_str().to_string(),
398 )),
399 }
400 }
401}