use super::*;
#[derive(Clone, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)]
pub enum Type {
Void,
Bool,
Char,
I8,
U8,
I16,
U16,
I32,
U32,
I64,
U64,
F32,
F64,
ISize,
USize,
GUID, String, IInspectable, Type, TypeRef(TypeName),
GenericParam(GenericParam),
TypeDef(TypeDef, Vec<Self>),
MutPtr(Box<Self>, usize),
ConstPtr(Box<Self>, usize),
Win32Array(Box<Self>, usize),
WinrtArray(Box<Self>),
WinrtArrayRef(Box<Self>),
ConstRef(Box<Self>),
PrimitiveOrEnum(Box<Self>, Box<Self>),
HRESULT, IUnknown, PSTR,
PWSTR,
PCSTR,
PCWSTR,
BSTR,
}
impl Type {
pub fn from_code(code: usize) -> Option<Self> {
match code as u8 {
ELEMENT_TYPE_VOID => Some(Self::Void),
ELEMENT_TYPE_BOOLEAN => Some(Self::Bool),
ELEMENT_TYPE_CHAR => Some(Self::Char),
ELEMENT_TYPE_I1 => Some(Self::I8),
ELEMENT_TYPE_U1 => Some(Self::U8),
ELEMENT_TYPE_I2 => Some(Self::I16),
ELEMENT_TYPE_U2 => Some(Self::U16),
ELEMENT_TYPE_I4 => Some(Self::I32),
ELEMENT_TYPE_U4 => Some(Self::U32),
ELEMENT_TYPE_I8 => Some(Self::I64),
ELEMENT_TYPE_U8 => Some(Self::U64),
ELEMENT_TYPE_R4 => Some(Self::F32),
ELEMENT_TYPE_R8 => Some(Self::F64),
ELEMENT_TYPE_I => Some(Self::ISize),
ELEMENT_TYPE_U => Some(Self::USize),
ELEMENT_TYPE_STRING => Some(Self::String),
ELEMENT_TYPE_OBJECT => Some(Self::IInspectable),
_ => None,
}
}
pub fn to_const_type(self) -> Self {
match self {
Self::MutPtr(kind, pointers) => Self::MutPtr(Box::new(kind.to_const_type()), pointers),
Self::ConstPtr(kind, pointers) => Self::ConstPtr(Box::new(kind.to_const_type()), pointers),
Self::PSTR => Self::PCSTR,
Self::PWSTR => Self::PCWSTR,
_ => self,
}
}
pub fn to_underlying_type(&self) -> Self {
match self {
Type::MutPtr(ty, _) => *ty.clone(),
Type::ConstPtr(ty, _) => *ty.clone(),
Type::Win32Array(ty, _) => *ty.clone(),
Type::WinrtArray(ty) => *ty.clone(),
Type::WinrtArrayRef(ty) => *ty.clone(),
Type::ConstRef(ty) => *ty.clone(),
_ => self.clone(),
}
}
pub fn to_const_ptr(self) -> Self {
match self {
Self::MutPtr(kind, pointers) => Self::ConstPtr(kind, pointers),
_ => self,
}
}
pub fn deref(&self) -> Self {
match self {
Self::ConstPtr(kind, 1) | Self::MutPtr(kind, 1) => {
if **kind == Self::Void {
Self::U8
} else {
*kind.clone()
}
}
Self::ConstPtr(kind, pointers) => Self::ConstPtr(kind.clone(), pointers - 1),
Self::MutPtr(kind, pointers) => Self::MutPtr(kind.clone(), pointers - 1),
Self::PSTR | Self::PCSTR => Self::U8,
Self::PWSTR | Self::PCWSTR => Self::U16,
_ => panic!("`deref` can only be called on pointer types"),
}
}
pub fn is_winrt_array(&self) -> bool {
matches!(self, Type::WinrtArray(_))
}
pub fn is_winrt_array_ref(&self) -> bool {
matches!(self, Type::WinrtArrayRef(_))
}
pub fn is_const_ref(&self) -> bool {
matches!(self, Type::ConstRef(_))
}
pub fn is_generic(&self) -> bool {
matches!(self, Type::GenericParam(_))
}
pub fn is_pointer(&self) -> bool {
matches!(self, Type::ConstPtr(_, _) | Type::MutPtr(_, _))
}
pub fn is_unsigned(&self) -> bool {
matches!(self, Type::U8 | Type::U16 | Type::U32 | Type::U64 | Type::USize)
}
pub fn is_void(&self) -> bool {
match self {
Type::ConstPtr(kind, _) | Type::MutPtr(kind, _) => kind.is_void(),
Type::Void => true,
_ => false,
}
}
pub fn is_byte_size(&self) -> bool {
match self {
Type::ConstPtr(kind, _) | Type::MutPtr(kind, _) => kind.is_byte_size(),
Type::I8 | Type::U8 | Type::PSTR | Type::PCSTR => true,
_ => false,
}
}
pub fn size(&self) -> usize {
match self {
Type::I8 | Type::U8 => 1,
Type::I16 | Type::U16 => 2,
Type::I64 | Type::U64 | Type::F64 => 8,
Type::GUID => 16,
Type::TypeDef(def, _) => def.size(),
Type::Win32Array(ty, len) => ty.size() * len,
Type::PrimitiveOrEnum(ty, _) => ty.size(),
_ => 4,
}
}
pub fn align(&self) -> usize {
match self {
Type::I8 | Type::U8 => 1,
Type::I16 | Type::U16 => 2,
Type::I64 | Type::U64 | Type::F64 => 8,
Type::GUID => 4,
Type::TypeDef(def, _) => def.align(),
Type::Win32Array(ty, len) => ty.align() * len,
_ => 4,
}
}
}