mod iter;
#[doc(inline)]
pub use iter::*;
mod kind;
#[doc(inline)]
pub use kind::*;
pub mod fields;
pub mod number;
pub mod primitive;
pub mod visitor;
mod records;
#[doc(inline)]
pub use records::*;
pub use fields::FieldList;
use self::primitive::dump_primitive_type_index;
use crate::parser::{Number, Parse, Parser, ParserError};
use bitfield::bitfield;
use bstr::BStr;
use std::fmt::Debug;
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned, LE, U16, U32};
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct TypeIndex(pub u32);
impl TypeIndex {
pub const MIN_BEGIN: TypeIndex = TypeIndex(0x1000);
}
impl std::fmt::Debug for TypeIndex {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
if self.0 < TypeIndex::MIN_BEGIN.0 {
dump_primitive_type_index(fmt, *self)
} else {
write!(fmt, "T#0x{:x}", self.0)
}
}
}
#[derive(
Copy, Clone, Eq, PartialEq, Hash, FromBytes, IntoBytes, Immutable, KnownLayout, Unaligned,
)]
#[repr(transparent)]
pub struct TypeIndexLe(pub U32<LE>);
impl From<TypeIndex> for TypeIndexLe {
#[inline(always)]
fn from(value: TypeIndex) -> TypeIndexLe {
TypeIndexLe(U32::new(value.0))
}
}
impl Debug for TypeIndexLe {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
let ti = self.get();
Debug::fmt(&ti, fmt)
}
}
impl TypeIndexLe {
#[inline(always)]
pub fn get(self) -> TypeIndex {
TypeIndex(self.0.get())
}
}
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub enum TypeData<'a> {
Array(Array<'a>),
Struct(Struct<'a>),
Union(Union<'a>),
Enum(Enum<'a>),
Proc(&'a Proc),
MemberFunc(&'a MemberFunc),
VTableShape(VTableShapeData<'a>),
Pointer(Pointer<'a>),
Modifier(TypeModifier),
FieldList(FieldList<'a>),
MethodList(MethodListData<'a>),
ArgList(ArgList<'a>),
Alias(Alias<'a>),
UdtSrcLine(&'a UdtSrcLine),
UdtModSrcLine(&'a UdtModSrcLine),
FuncId(FuncId<'a>),
MFuncId(MFuncId<'a>),
StringId(StringId<'a>),
SubStrList(SubStrList<'a>),
BuildInfo(BuildInfo<'a>),
VFTable(&'a VFTable),
Unknown,
}
impl<'a> TypeData<'a> {
pub fn parse_bytes(kind: Leaf, bytes: &'a [u8]) -> Result<Self, ParserError> {
let mut p = Parser::new(bytes);
Self::parse(kind, &mut p)
}
pub fn parse(kind: Leaf, p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(match kind {
Leaf::LF_ARRAY => Self::Array(p.parse()?),
Leaf::LF_CLASS | Leaf::LF_STRUCTURE | Leaf::LF_INTERFACE => Self::Struct(p.parse()?),
Leaf::LF_UNION => Self::Union(p.parse()?),
Leaf::LF_ENUM => Self::Enum(p.parse()?),
Leaf::LF_PROCEDURE => Self::Proc(p.get()?),
Leaf::LF_MEMBER => Self::MemberFunc(p.get()?),
Leaf::LF_VTSHAPE => {
let fixed: &VTableShapeFixed = p.get()?;
Self::VTableShape(VTableShapeData {
count: fixed.count.get(),
descriptors: p.take_rest(),
})
}
Leaf::LF_VFTABLE => Self::VFTable(p.get()?),
Leaf::LF_POINTER => {
let fixed = p.get()?;
let variant = p.take_rest();
Self::Pointer(Pointer { fixed, variant })
}
Leaf::LF_MFUNCTION => Self::MemberFunc(p.get()?),
Leaf::LF_MODIFIER => Self::Modifier(p.copy()?),
Leaf::LF_FIELDLIST => Self::FieldList(FieldList {
bytes: p.take_rest(),
}),
Leaf::LF_METHODLIST => Self::MethodList(MethodListData {
bytes: p.take_rest(),
}),
Leaf::LF_ARGLIST => Self::ArgList(p.parse()?),
Leaf::LF_ALIAS => Self::Alias(Alias::from_parser(p)?),
Leaf::LF_UDT_SRC_LINE => Self::UdtSrcLine(p.get()?),
Leaf::LF_UDT_MOD_SRC_LINE => Self::UdtModSrcLine(p.get()?),
Leaf::LF_FUNC_ID => Self::FuncId(p.parse()?),
Leaf::LF_MFUNC_ID => Self::MFuncId(p.parse()?),
Leaf::LF_STRING_ID => Self::StringId(p.parse()?),
Leaf::LF_SUBSTR_LIST => Self::SubStrList(p.parse()?),
Leaf::LF_BUILDINFO => Self::BuildInfo(p.parse()?),
_ => Self::Unknown,
})
}
pub fn name(&self) -> Option<&'a BStr> {
match self {
Self::Struct(t) => Some(t.name),
Self::Union(t) => Some(t.name),
Self::Enum(t) => Some(t.name),
Self::Alias(t) => Some(t.name),
Self::FuncId(t) => Some(t.name),
Self::StringId(t) => Some(t.name),
_ => None,
}
}
pub fn udt_name(&self) -> Option<&'a BStr> {
match self {
Self::Struct(t) => Some(t.name),
Self::Union(t) => Some(t.name),
Self::Enum(t) => Some(t.name),
Self::Alias(t) => Some(t.name),
_ => None,
}
}
}