use super::derive::{CanTriviallyDeriveCopy, CanTriviallyDeriveDebug,
CanTriviallyDeriveDefault, CanTriviallyDeriveHash,
CanTriviallyDerivePartialEqOrPartialOrd, CanDerive};
use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type, TypeKind};
use ir::context::BindgenContext;
use clang;
use std::cmp;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Layout {
pub size: usize,
pub align: usize,
pub packed: bool,
}
#[test]
fn test_layout_for_size() {
use std::mem;
let ptr_size = mem::size_of::<*mut ()>();
assert_eq!(
Layout::for_size_internal(ptr_size, ptr_size),
Layout::new(ptr_size, ptr_size)
);
assert_eq!(
Layout::for_size_internal(ptr_size, 3 * ptr_size),
Layout::new(3 * ptr_size, ptr_size)
);
}
impl Layout {
pub fn known_type_for_size(
ctx: &BindgenContext,
size: usize,
) -> Option<&'static str> {
Some(match size {
16 if ctx.options().rust_features.i128_and_u128 => "u128",
8 => "u64",
4 => "u32",
2 => "u16",
1 => "u8",
_ => return None,
})
}
pub fn new(size: usize, align: usize) -> Self {
Layout {
size,
align,
packed: false,
}
}
fn for_size_internal(ptr_size: usize, size: usize) -> Self {
let mut next_align = 2;
while size % next_align == 0 && next_align <= ptr_size {
next_align *= 2;
}
Layout {
size: size,
align: next_align / 2,
packed: false,
}
}
pub fn for_size(ctx: &BindgenContext, size: usize) -> Self {
Self::for_size_internal(ctx.target_pointer_size(), size)
}
pub fn is_zero(&self) -> bool {
self.size == 0 && self.align == 0
}
pub fn zero() -> Self {
Self::new(0, 0)
}
pub fn opaque(&self) -> Opaque {
Opaque(*self)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Opaque(pub Layout);
impl Opaque {
pub fn from_clang_ty(ty: &clang::Type) -> Type {
let layout = Layout::new(ty.size(), ty.align());
let ty_kind = TypeKind::Opaque;
let is_const = ty.is_const();
Type::new(None, Some(layout), ty_kind, is_const)
}
pub fn known_rust_type_for_array(&self,ctx: &BindgenContext) -> Option<&'static str> {
Layout::known_type_for_size(ctx, self.0.align)
}
pub fn array_size(&self, ctx: &BindgenContext) -> Option<usize> {
if self.known_rust_type_for_array(ctx).is_some() {
Some(self.0.size / cmp::max(self.0.align, 1))
} else {
None
}
}
pub fn array_size_within_derive_limit(&self, ctx: &BindgenContext) -> bool {
self.array_size(ctx).map_or(false, |size| {
size <= RUST_DERIVE_IN_ARRAY_LIMIT
})
}
}
impl CanTriviallyDeriveDebug for Opaque {
fn can_trivially_derive_debug(&self, ctx: &BindgenContext) -> bool {
self.array_size_within_derive_limit(ctx)
}
}
impl CanTriviallyDeriveDefault for Opaque {
fn can_trivially_derive_default(&self, ctx: &BindgenContext) -> bool {
self.array_size_within_derive_limit(ctx)
}
}
impl CanTriviallyDeriveCopy for Opaque {
fn can_trivially_derive_copy(&self, ctx: &BindgenContext) -> bool {
self.array_size_within_derive_limit(ctx)
}
}
impl CanTriviallyDeriveHash for Opaque {
fn can_trivially_derive_hash(&self, ctx: &BindgenContext) -> bool {
self.array_size_within_derive_limit(ctx)
}
}
impl CanTriviallyDerivePartialEqOrPartialOrd for Opaque {
fn can_trivially_derive_partialeq_or_partialord(&self, ctx: &BindgenContext) -> CanDerive {
if self.array_size_within_derive_limit(ctx) {
CanDerive::Yes
} else {
CanDerive::ArrayTooLarge
}
}
}