blob: 03d43b51ba5acefbebf5581b5bd151b405012619 [file] [log] [blame]
//! Intermediate representation for the physical layout of some type.
use super::context::BindgenContext;
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
use super::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
use std::cmp;
/// A type that represents the struct layout of a type.
#[derive(Debug, Clone, Copy)]
pub struct Layout {
/// The size (in bytes) of this layout.
pub size: usize,
/// The alignment (in bytes) of this layout.
pub align: usize,
/// Whether this layout's members are packed or not.
pub packed: bool,
}
impl Layout {
/// Construct a new `Layout` with the given `size` and `align`. It is not
/// packed.
pub fn new(size: usize, align: usize) -> Self {
Layout {
size: size,
align: align,
packed: false,
}
}
/// Is this a zero-sized layout?
pub fn is_zero(&self) -> bool {
self.size == 0 && self.align == 0
}
/// Construct a zero-sized layout.
pub fn zero() -> Self {
Self::new(0, 0)
}
/// Get this layout as an opaque type.
pub fn opaque(&self) -> Opaque {
Opaque(*self)
}
}
/// When we are treating a type as opaque, it is just a blob with a `Layout`.
pub struct Opaque(pub Layout);
impl Opaque {
/// Return the known rust type we should use to create a correctly-aligned
/// field with this layout.
pub fn known_rust_type_for_array(&self) -> Option<&'static str> {
Some(match self.0.align {
8 => "u64",
4 => "u32",
2 => "u16",
1 => "u8",
_ => return None,
})
}
/// Return the array size that an opaque type for this layout should have if
/// we know the correct type for it, or `None` otherwise.
pub fn array_size(&self) -> Option<usize> {
if self.known_rust_type_for_array().is_some() {
Some(self.0.size / cmp::max(self.0.align, 1))
} else {
None
}
}
}
impl CanDeriveDebug for Opaque {
type Extra = ();
fn can_derive_debug(&self, _: &BindgenContext, _: ()) -> bool {
self.array_size()
.map_or(false, |size| size <= RUST_DERIVE_IN_ARRAY_LIMIT)
}
}
impl CanDeriveDefault for Opaque {
type Extra = ();
fn can_derive_default(&self, _: &BindgenContext, _: ()) -> bool {
self.array_size()
.map_or(false, |size| size <= RUST_DERIVE_IN_ARRAY_LIMIT)
}
}
impl<'a> CanDeriveCopy<'a> for Opaque {
type Extra = ();
fn can_derive_copy(&self, _: &BindgenContext, _: ()) -> bool {
self.array_size()
.map_or(false, |size| size <= RUST_DERIVE_IN_ARRAY_LIMIT)
}
fn can_derive_copy_in_array(&self, ctx: &BindgenContext, _: ()) -> bool {
self.can_derive_copy(ctx, ())
}
}