use crate::library::*;
const RUST_DERIVE_ARRAY_SIZE_LIMIT: u16 = 32;
const RUST_DERIVE_PARAM_SIZE_LIMIT: usize = 12;
pub trait IsPtr {
fn is_ptr(&self) -> bool;
}
impl IsPtr for Field {
fn is_ptr(&self) -> bool {
if let Some(ref c_type) = self.c_type {
c_type.contains('*')
} else {
false
}
}
}
impl IsPtr for Alias {
fn is_ptr(&self) -> bool {
self.target_c_type.contains('*')
}
}
pub trait IsVolatile {
fn is_volatile(&self) -> bool;
}
impl IsVolatile for Field {
fn is_volatile(&self) -> bool {
if let Some(ref c_type) = self.c_type {
c_type.starts_with("volatile")
} else {
false
}
}
}
pub trait IsIncomplete {
fn is_incomplete(&self, lib: &Library) -> bool;
}
impl IsIncomplete for Basic {
fn is_incomplete(&self, _lib: &Library) -> bool {
matches!(*self, Self::None | Self::Unsupported | Self::VarArgs)
}
}
impl IsIncomplete for Alias {
fn is_incomplete(&self, lib: &Library) -> bool {
if self.is_ptr() {
false
} else {
lib.type_(self.typ).is_incomplete(lib)
}
}
}
impl IsIncomplete for Field {
fn is_incomplete(&self, lib: &Library) -> bool {
if self.is_ptr() {
false
} else {
lib.type_(self.typ).is_incomplete(lib)
}
}
}
impl IsIncomplete for &[Field] {
fn is_incomplete(&self, lib: &Library) -> bool {
if self.is_empty() {
return true;
}
let mut is_bitfield = false;
for field in self.iter() {
if field.is_incomplete(lib) {
return true;
}
if is_bitfield && field.bits.is_some() {
return true;
}
is_bitfield = field.bits.is_some();
}
false
}
}
impl IsIncomplete for Class {
fn is_incomplete(&self, lib: &Library) -> bool {
self.fields.as_slice().is_incomplete(lib)
}
}
impl IsIncomplete for Record {
fn is_incomplete(&self, lib: &Library) -> bool {
if self.c_type == "GHookList" || self.disguised || self.pointer {
false
} else {
self.fields.as_slice().is_incomplete(lib)
}
}
}
impl IsIncomplete for Union {
fn is_incomplete(&self, lib: &Library) -> bool {
self.fields.as_slice().is_incomplete(lib)
}
}
impl IsIncomplete for Function {
fn is_incomplete(&self, lib: &Library) -> bool {
self.parameters.iter().any(|p| {
matches!(
lib.type_(p.typ),
Type::Basic(Basic::Unsupported | Basic::VarArgs)
)
})
}
}
impl IsIncomplete for TypeId {
fn is_incomplete(&self, lib: &Library) -> bool {
lib.type_(*self).is_incomplete(lib)
}
}
impl IsIncomplete for Type {
fn is_incomplete(&self, lib: &Library) -> bool {
match self {
Type::Basic(basic) => basic.is_incomplete(lib),
Type::Alias(alias) => alias.is_incomplete(lib),
Type::FixedArray(tid, ..) => tid.is_incomplete(lib),
Type::Class(klass) => klass.is_incomplete(lib),
Type::Record(record) => record.is_incomplete(lib),
Type::Union(union) => union.is_incomplete(lib),
Type::Function(function) => function.is_incomplete(lib),
Type::Interface(..) => true,
Type::Custom(..)
| Type::Enumeration(..)
| Type::Bitfield(..)
| Type::Array(..)
| Type::CArray(..)
| Type::PtrArray(..)
| Type::HashTable(..)
| Type::List(..)
| Type::SList(..) => false,
}
}
}
pub trait IsExternal {
fn is_external(&self, lib: &Library) -> bool;
}
impl IsExternal for Class {
fn is_external(&self, _lib: &Library) -> bool {
self.fields.is_empty()
}
}
impl IsExternal for Record {
fn is_external(&self, _lib: &Library) -> bool {
self.fields.is_empty()
}
}
impl IsExternal for Union {
fn is_external(&self, _lib: &Library) -> bool {
self.fields.is_empty()
}
}
impl IsExternal for Alias {
fn is_external(&self, lib: &Library) -> bool {
if self.is_ptr() {
false
} else {
lib.type_(self.typ).is_external(lib)
}
}
}
impl IsExternal for Type {
fn is_external(&self, lib: &Library) -> bool {
match self {
Type::Alias(alias) => alias.is_external(lib),
Type::Class(klass) => klass.is_external(lib),
Type::Record(record) => record.is_external(lib),
Type::Union(union) => union.is_external(lib),
Type::Interface(..) => true,
Type::Custom(..)
| Type::Basic(..)
| Type::Enumeration(..)
| Type::Bitfield(..)
| Type::Function(..)
| Type::Array(..)
| Type::CArray(..)
| Type::FixedArray(..)
| Type::PtrArray(..)
| Type::HashTable(..)
| Type::List(..)
| Type::SList(..) => false,
}
}
}
pub trait DerivesCopy {
fn derives_copy(&self, lib: &Library) -> bool;
}
impl<T: IsIncomplete> DerivesCopy for T {
fn derives_copy(&self, lib: &Library) -> bool {
!self.is_incomplete(lib)
}
}
pub trait ImplementsDebug {
fn implements_debug(&self, lib: &Library) -> bool;
}
impl ImplementsDebug for Field {
fn implements_debug(&self, lib: &Library) -> bool {
match *lib.type_(self.typ) {
Type::FixedArray(_, size, _) => size <= RUST_DERIVE_ARRAY_SIZE_LIMIT,
Type::Function(Function { ref parameters, .. }) => {
parameters.len() <= RUST_DERIVE_PARAM_SIZE_LIMIT
}
_ => true,
}
}
}