cdefmt_decoder/
var.rs

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
226/* Debug is implemented using derive */
227
228impl 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}