1use isr_core::{Profile, types::Type};
2
3use crate::{Bitfield, Error, Field, offsets::FieldDescriptor, symbols::SymbolDescriptor};
4
5pub trait ProfileExt {
6 fn find_field(&self, type_name: &str, field_name: &str) -> Option<Field>;
7 fn find_bitfield(&self, type_name: &str, field_name: &str) -> Option<Bitfield>;
8 fn find_symbol_descriptor(&self, symbol_name: &str) -> Result<SymbolDescriptor, Error>;
9 fn find_field_descriptor(
10 &self,
11 type_name: &str,
12 field_name: &str,
13 ) -> Result<FieldDescriptor, Error>;
14}
15
16impl ProfileExt for Profile<'_> {
17 fn find_field(&self, type_name: &str, field_name: &str) -> Option<Field> {
18 let udt = self.find_struct(type_name)?;
19
20 if let Some(field) = udt.fields.get(field_name) {
21 return Some(Field {
22 offset: field.offset,
23 size: self.type_size(&field.type_)?,
24 });
25 }
26
27 for field in udt.fields.values() {
28 let udt = match &field.type_ {
29 Type::Struct(udt) => udt,
30 _ => continue,
31 };
32
33 if let Some(child) = self.find_field(&udt.name, field_name) {
34 return Some(Field {
35 offset: field.offset + child.offset,
36 size: child.size,
37 });
38 }
39 }
40
41 None
42 }
43
44 fn find_bitfield(&self, type_name: &str, field_name: &str) -> Option<Bitfield> {
45 let udt = self.find_struct(type_name)?;
46
47 if let Some(field) = udt.fields.get(field_name) {
48 if let Type::Bitfield(bitfield) = &field.type_ {
49 return Some(Bitfield {
50 field: Field {
51 offset: field.offset,
52 size: self.type_size(&field.type_)?,
53 },
54 bit_position: bitfield.bit_position,
55 bit_length: bitfield.bit_length,
56 });
57 }
58 }
59
60 for field in udt.fields.values() {
61 let udt = match &field.type_ {
62 Type::Struct(udt) => udt,
63 _ => continue,
64 };
65
66 if let Some(child) = self.find_bitfield(&udt.name, field_name) {
67 return Some(Bitfield {
68 field: Field {
69 offset: field.offset + child.offset,
70 size: child.size,
71 },
72 bit_position: child.bit_position,
73 bit_length: child.bit_length,
74 });
75 };
76 }
77
78 None
79 }
80
81 fn find_symbol_descriptor(&self, symbol_name: &str) -> Result<SymbolDescriptor, Error> {
82 match self.find_symbol(symbol_name) {
83 Some(offset) => Ok(SymbolDescriptor { offset }),
84 None => Err(Error::symbol_not_found(symbol_name)),
85 }
86 }
87
88 fn find_field_descriptor(
89 &self,
90 type_name: &str,
91 field_name: &str,
92 ) -> Result<FieldDescriptor, Error> {
93 let udt = match self.find_struct(type_name) {
94 Some(udt) => udt,
95 None => return Err(Error::type_not_found(type_name)),
96 };
97
98 if let Some(field) = udt.fields.get(field_name) {
99 return Ok(match &field.type_ {
100 Type::Bitfield(bitfield) => FieldDescriptor::Bitfield(Bitfield {
101 field: Field {
102 offset: field.offset,
103 size: match self.type_size(&field.type_) {
104 Some(size) => size,
105 None => {
106 return Err(Error::field_not_found(type_name, field_name));
107 }
108 },
109 },
110 bit_position: bitfield.bit_position,
111 bit_length: bitfield.bit_length,
112 }),
113 _ => FieldDescriptor::Field(Field {
114 offset: field.offset,
115 size: match self.type_size(&field.type_) {
116 Some(size) => size,
117 None => {
118 return Err(Error::field_not_found(type_name, field_name));
119 }
120 },
121 }),
122 });
123 }
124
125 for field in udt.fields.values() {
126 let udt = match &field.type_ {
127 Type::Struct(udt) => udt,
128 _ => continue,
129 };
130
131 if let Ok(child) = self.find_field_descriptor(&udt.name, field_name) {
132 return Ok(match child {
133 FieldDescriptor::Field(child) => FieldDescriptor::Field(Field {
134 offset: field.offset + child.offset,
135 size: child.size,
136 }),
137 FieldDescriptor::Bitfield(child) => FieldDescriptor::Bitfield(Bitfield {
138 field: Field {
139 offset: field.offset + child.offset,
140 size: child.size,
141 },
142 bit_position: child.bit_position,
143 bit_length: child.bit_length,
144 }),
145 });
146 }
147 }
148
149 Err(Error::field_not_found(type_name, field_name))
150 }
151}