1use super::derive::CanDerive;
4use super::ty::{Type, TypeKind, RUST_DERIVE_IN_ARRAY_LIMIT};
5use crate::clang;
6use crate::ir::context::BindgenContext;
7use std::cmp;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub(crate) struct Layout {
12 pub(crate) size: usize,
14 pub(crate) align: usize,
16 pub(crate) packed: bool,
18}
19
20#[test]
21fn test_layout_for_size() {
22 use std::mem::size_of;
23 let ptr_size = size_of::<*mut ()>();
24 assert_eq!(
25 Layout::for_size_internal(ptr_size, ptr_size),
26 Layout::new(ptr_size, ptr_size)
27 );
28 assert_eq!(
29 Layout::for_size_internal(ptr_size, 3 * ptr_size),
30 Layout::new(3 * ptr_size, ptr_size)
31 );
32}
33
34impl Layout {
35 pub(crate) fn known_type_for_size(size: usize) -> Option<syn::Type> {
37 Some(match size {
38 16 => syn::parse_quote! { u128 },
39 8 => syn::parse_quote! { u64 },
40 4 => syn::parse_quote! { u32 },
41 2 => syn::parse_quote! { u16 },
42 1 => syn::parse_quote! { u8 },
43 _ => return None,
44 })
45 }
46
47 pub(crate) fn new(size: usize, align: usize) -> Self {
50 Layout {
51 size,
52 align,
53 packed: false,
54 }
55 }
56
57 fn for_size_internal(ptr_size: usize, size: usize) -> Self {
58 let mut next_align = 2;
59 while size % next_align == 0 && next_align <= ptr_size {
60 next_align *= 2;
61 }
62 Layout {
63 size,
64 align: next_align / 2,
65 packed: false,
66 }
67 }
68
69 pub(crate) fn for_size(ctx: &BindgenContext, size: usize) -> Self {
72 Self::for_size_internal(ctx.target_pointer_size(), size)
73 }
74
75 pub(crate) fn opaque(&self) -> Opaque {
77 Opaque(*self)
78 }
79}
80
81#[derive(Clone, Debug, PartialEq, Eq)]
83pub(crate) struct Opaque(pub(crate) Layout);
84
85impl Opaque {
86 pub(crate) fn from_clang_ty(
88 ty: &clang::Type,
89 ctx: &BindgenContext,
90 ) -> Type {
91 let layout = Layout::new(ty.size(ctx), ty.align(ctx));
92 let ty_kind = TypeKind::Opaque;
93 let is_const = ty.is_const();
94 Type::new(None, Some(layout), ty_kind, is_const)
95 }
96
97 pub(crate) fn known_rust_type_for_array(&self) -> Option<syn::Type> {
100 Layout::known_type_for_size(self.0.align)
101 }
102
103 pub(crate) fn array_size(&self) -> Option<usize> {
106 if self.known_rust_type_for_array().is_some() {
107 Some(self.0.size / cmp::max(self.0.align, 1))
108 } else {
109 None
110 }
111 }
112
113 pub(crate) fn array_size_within_derive_limit(&self) -> CanDerive {
117 if self
118 .array_size()
119 .is_some_and(|size| size <= RUST_DERIVE_IN_ARRAY_LIMIT)
120 {
121 CanDerive::Yes
122 } else {
123 CanDerive::Manually
124 }
125 }
126}