use std::borrow::Cow;
use serde::{Deserialize, Serialize};
use crate::{
symbols::Symbols,
types::{BaseRef, Enum, Struct, Type, Types},
};
#[derive(Debug, Serialize, Deserialize)]
pub struct Profile<'a> {
#[serde(borrow)]
architecture: Cow<'a, str>,
#[serde(borrow)]
symbols: Symbols<'a>,
#[serde(borrow)]
types: Types<'a>,
}
impl<'a> Profile<'a> {
pub fn new(architecture: Cow<'a, str>, symbols: Symbols<'a>, types: Types<'a>) -> Self {
Self {
architecture,
symbols,
types,
}
}
pub fn symbols(&self) -> impl Iterator<Item = (&str, &u64)> {
self.symbols
.0
.iter()
.map(|(name, value)| (name.as_ref(), value))
}
pub fn types(&self) -> &Types {
&self.types
}
pub fn type_size(&self, type_: &Type) -> Option<u64> {
match type_ {
Type::Base(r) => Some(self.base_size(r)),
Type::Enum(r) => self.enum_size(&r.name),
Type::Struct(r) => self.struct_size(&r.name),
Type::Array(r) => self.type_size(&r.subtype),
Type::Pointer(_) => Some(self.pointer_size()),
Type::Bitfield(r) => self.type_size(&r.subtype),
Type::Function => Some(self.pointer_size()),
}
}
pub fn base_size(&self, base: &BaseRef) -> u64 {
match base {
BaseRef::Void => 0,
BaseRef::Bool | BaseRef::Char | BaseRef::I8 | BaseRef::U8 | BaseRef::F8 => 1,
BaseRef::Wchar | BaseRef::I16 | BaseRef::U16 | BaseRef::F16 => 2,
BaseRef::I32 | BaseRef::U32 | BaseRef::F32 => 4,
BaseRef::I64 | BaseRef::U64 | BaseRef::F64 => 8,
BaseRef::I128 | BaseRef::U128 | BaseRef::F128 => 16,
}
}
pub fn enum_size(&self, name: &str) -> Option<u64> {
self.type_size(&self.types.enums.get(name)?.subtype)
}
pub fn struct_size(&self, name: &str) -> Option<u64> {
self.types.structs.get(name).map(|udt| udt.size)
}
pub fn pointer_size(&self) -> u64 {
match self.architecture.as_ref() {
"X86" | "Arm" => 4,
"Amd64" | "Arm64" => 8,
_ => panic!("unsupported architecture"),
}
}
pub fn find_symbol(&self, symbol_name: &str) -> Option<u64> {
self.symbols.0.get(symbol_name).copied()
}
pub fn find_enum(&self, type_name: &str) -> Option<&Enum> {
self.types.enums.get(type_name)
}
pub fn find_struct(&self, type_name: &str) -> Option<&Struct> {
self.types.structs.get(type_name)
}
}