1use crate::error::{Error, Result};
2
3use std::collections::HashMap;
4
5#[derive(Clone, Copy, Debug, Default)]
7pub struct Integer {
8 pub used_bits: u32,
10
11 pub bits: u32,
13
14 pub is_signed: bool,
16}
17
18impl Integer {
19 pub fn get_size(&self) -> u32 {
21 self.used_bits / 8
22 }
23}
24
25#[derive(Clone, Copy, Debug, Default)]
27pub struct Float {
28 pub bits: u32,
30}
31
32impl Float {
33 pub fn get_size(&self) -> u32 {
35 self.bits / 8
36 }
37}
38
39#[derive(Clone, Copy, Debug, Default)]
41pub struct Array {
42 pub element_type_id: usize,
44
45 pub num_elements: u32,
47
48 pub size: u32,
50}
51
52impl Array {
53 pub fn create(
61 database: &TypeDatabase,
62 element_type_id: usize,
63 num_elements: u32,
64 ) -> Result<Self> {
65 let element_type = database
66 .get_type_by_id(element_type_id)
67 .ok_or(Error::InvalidTypeId)?;
68 let size = element_type.get_size() * num_elements;
69 Ok(Self {
70 element_type_id,
71 num_elements,
72 size,
73 })
74 }
75
76 pub fn get_size(&self) -> u32 {
78 self.size
79 }
80}
81
82#[derive(Clone, Copy, Debug, Default)]
84pub struct Field {
85 pub offset: u32,
87
88 pub type_id: usize,
90}
91
92impl Field {
93 pub fn get_type<'a>(&self, database: &'a TypeDatabase) -> Option<&'a Type> {
99 database.get_type_by_id(self.type_id)
100 }
101}
102
103#[derive(Clone, Debug, Default)]
105pub struct Struct {
106 pub fields: HashMap<String, Field>,
108
109 pub size: u32,
111}
112
113impl Struct {
114 pub fn create(database: &TypeDatabase, fields: &[(&str, Field)]) -> Result<Self> {
121 let mut new_fields = HashMap::with_capacity(fields.len());
122 let mut bits = 0;
123 for (name, field) in fields {
124 let field_type = database
125 .get_type_by_id(field.type_id)
126 .ok_or(Error::InvalidTypeId)?;
127 let reach = field.offset + field_type.get_size() * 8;
128 if reach > bits {
129 bits = reach
130 }
131 new_fields.insert(name.to_string(), *field);
132 }
133
134 Ok(Self {
135 fields: new_fields,
136 size: bits / 8,
137 })
138 }
139
140 pub fn get_size(&self) -> u32 {
142 self.size
143 }
144}
145
146#[derive(Clone, Debug, Default)]
148pub struct Enum {
149 pub bits: u32,
151
152 pub values: Vec<(String, i64)>,
154}
155
156impl Enum {
157 pub fn get_size(&self) -> u32 {
159 self.bits / 8
160 }
161}
162
163#[derive(Clone, Debug, Default)]
165pub struct Function {
166 pub param_type_ids: Vec<usize>,
168}
169
170impl Function {
171 pub fn create(param_type_ids: &[usize]) -> Self {
177 Self {
178 param_type_ids: param_type_ids.to_vec(),
179 }
180 }
181}
182
183#[derive(Clone, Debug, Default)]
185pub enum BaseType {
186 #[default]
187 Void,
188 Integer(Integer),
189 Float(Float),
190 Array(Array),
191 Struct(Struct),
192 Enum(Enum),
193 Function(Function),
194}
195
196impl BaseType {
197 pub fn get_size(&self) -> u32 {
200 match self {
201 BaseType::Void => 0,
202 BaseType::Integer(t) => t.get_size(),
203 BaseType::Float(t) => t.get_size(),
204 BaseType::Array(t) => t.get_size(),
205 BaseType::Struct(t) => t.get_size(),
206 BaseType::Enum(t) => t.get_size(),
207 BaseType::Function(_) => 0,
208 }
209 }
210}
211
212#[derive(Clone, Debug, Default)]
214pub struct Type {
215 pub base_type: BaseType,
217
218 pub num_refs: u32,
220}
221
222impl Type {
223 pub fn is_pointer(&self) -> bool {
226 self.num_refs > 0
227 }
228
229 pub fn get_size(&self) -> u32 {
233 if self.num_refs > 0 {
234 return 8;
235 }
236
237 self.base_type.get_size()
238 }
239}
240
241impl From<BaseType> for Type {
242 fn from(base_type: BaseType) -> Self {
243 Self {
244 base_type,
245 num_refs: 0,
246 }
247 }
248}
249
250#[derive(Clone, Debug, Default)]
252pub struct TypeDatabase {
253 types: Vec<Type>,
255 name_map: HashMap<String, usize>,
256}
257
258impl TypeDatabase {
259 pub fn add_type(&mut self, name: Option<&str>, ty: &Type) -> Result<usize> {
266 if let Some(name) = name {
267 if let Some(index) = self.name_map.get(name) {
268 self.types[*index] = ty.clone();
269 Ok(*index)
270 } else {
271 let index = self.types.len();
272 self.types.push(ty.clone());
273 self.name_map.insert(name.to_string(), index);
274 Ok(index)
275 }
276 } else {
277 self.types.push(ty.clone());
278 Ok(self.types.len() - 1)
279 }
280 }
281
282 pub fn get_type_by_name(&self, name: &str) -> Option<&Type> {
288 let index = self.name_map.get(name)?;
289 self.types.get(*index)
290 }
291
292 pub fn get_type_by_id(&self, id: usize) -> Option<&Type> {
298 self.types.get(id)
299 }
300
301 pub fn get_type_id_by_name(&self, name: &str) -> Option<usize> {
307 Some(*self.name_map.get(name)?)
308 }
309
310 pub fn add_integer(
318 &mut self,
319 name: Option<&str>,
320 bytes: u32,
321 is_signed: bool,
322 ) -> Result<usize> {
323 let bits = bytes * 8;
324 let new_integer = Integer {
325 used_bits: bits,
326 bits,
327 is_signed,
328 };
329
330 self.add_type(name, &BaseType::Integer(new_integer).into())
331 }
332
333 pub fn add_float(&mut self, name: Option<&str>, bits: u32) -> Result<usize> {
340 let new_float = Float { bits };
341
342 self.add_type(name, &BaseType::Float(new_float).into())
343 }
344
345 pub fn add_array(
353 &mut self,
354 name: Option<&str>,
355 element_type_id: usize,
356 num_elements: u32,
357 ) -> Result<usize> {
358 let new_array = Array::create(self, element_type_id, num_elements)?;
359 self.add_type(name, &BaseType::Array(new_array).into())
360 }
361
362 pub fn add_struct(&mut self, name: Option<&str>, fields: &[(&str, Field)]) -> Result<usize> {
369 let new_struct = Struct::create(self, fields)?;
370 self.add_type(name, &BaseType::Struct(new_struct).into())
371 }
372
373 pub fn add_struct_by_ids(
382 &mut self,
383 name: Option<&str>,
384 fields: &[(&str, usize)],
385 ) -> Result<usize> {
386 let mut new_fields = Vec::with_capacity(fields.len());
387 let mut offset = 0;
388 for (field_name, type_id) in fields {
389 let field_type = self
390 .get_type_by_id(*type_id)
391 .ok_or(Error::InvalidTypeName)?;
392 let field = Field {
393 offset,
394 type_id: *type_id,
395 };
396 offset += field_type.get_size() * 8;
397 new_fields.push((*field_name, field));
398 }
399 let new_struct = Struct::create(self, new_fields.as_slice())?;
400 self.add_type(name, &BaseType::Struct(new_struct).into())
401 }
402
403 pub fn add_struct_by_names(
412 &mut self,
413 name: Option<&str>,
414 fields: &[(&str, &str)],
415 ) -> Result<usize> {
416 let mut new_fields = Vec::with_capacity(fields.len());
417 let mut offset = 0;
418 for (field_name, type_name) in fields {
419 let field_type = self
420 .get_type_by_name(type_name)
421 .ok_or(Error::InvalidTypeName)?;
422 let type_id = self
423 .get_type_id_by_name(type_name)
424 .ok_or(Error::InvalidTypeName)?;
425 let field = Field { offset, type_id };
426 offset += field_type.get_size() * 8;
427 new_fields.push((*field_name, field));
428 }
429 let new_struct = Struct::create(self, new_fields.as_slice())?;
430 self.add_type(name, &BaseType::Struct(new_struct).into())
431 }
432}
433
434pub trait AddToTypeDatabase {
435 fn add_to_database(database: &mut TypeDatabase) -> Result<usize>;
436}
437
438impl AddToTypeDatabase for u8 {
439 fn add_to_database(database: &mut TypeDatabase) -> Result<usize> {
440 database.add_integer(Some("u8"), 1, false)
441 }
442}
443
444impl AddToTypeDatabase for u16 {
445 fn add_to_database(database: &mut TypeDatabase) -> Result<usize> {
446 database.add_integer(Some("u16"), 2, false)
447 }
448}
449
450impl AddToTypeDatabase for u32 {
451 fn add_to_database(database: &mut TypeDatabase) -> Result<usize> {
452 database.add_integer(Some("u32"), 4, false)
453 }
454}
455
456impl AddToTypeDatabase for u64 {
457 fn add_to_database(database: &mut TypeDatabase) -> Result<usize> {
458 database.add_integer(Some("u64"), 8, false)
459 }
460}
461
462impl AddToTypeDatabase for i8 {
463 fn add_to_database(database: &mut TypeDatabase) -> Result<usize> {
464 database.add_integer(Some("i8"), 1, true)
465 }
466}
467
468impl AddToTypeDatabase for i16 {
469 fn add_to_database(database: &mut TypeDatabase) -> Result<usize> {
470 database.add_integer(Some("i16"), 2, true)
471 }
472}
473
474impl AddToTypeDatabase for i32 {
475 fn add_to_database(database: &mut TypeDatabase) -> Result<usize> {
476 database.add_integer(Some("i32"), 4, true)
477 }
478}
479
480impl AddToTypeDatabase for i64 {
481 fn add_to_database(database: &mut TypeDatabase) -> Result<usize> {
482 database.add_integer(Some("i64"), 8, true)
483 }
484}
485
486impl<T: AddToTypeDatabase, const N: usize> AddToTypeDatabase for [T; N] {
487 fn add_to_database(database: &mut TypeDatabase) -> Result<usize> {
488 let type_id = T::add_to_database(database)?;
489 database.add_array(
490 Some(std::any::type_name::<[T; N]>()),
491 type_id,
492 N.try_into()?,
493 )
494 }
495}