-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathlayout_polyfill.rs
62 lines (55 loc) · 1.95 KB
/
layout_polyfill.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use core::{
alloc::{Layout, LayoutErr},
cmp,
};
#[inline]
pub(crate) fn extend_layout(this: &Layout, next: Layout) -> Result<(Layout, usize), LayoutErr> {
let new_align = cmp::max(this.align(), next.align());
let pad = layout_padding_needed_for(&this, next.align());
let offset = this.size().checked_add(pad).ok_or_else(layout_err)?;
let new_size = offset.checked_add(next.size()).ok_or_else(layout_err)?;
let layout = Layout::from_size_align(new_size, new_align)?;
Ok((layout, offset))
}
#[inline]
pub(crate) fn pad_layout_to_align(this: &Layout) -> Layout {
let pad = layout_padding_needed_for(this, this.align());
let new_size = this.size() + pad;
unsafe { Layout::from_size_align_unchecked(new_size, this.align()) }
}
#[inline]
pub(crate) fn layout_array<T>(n: usize) -> Result<Layout, LayoutErr> {
repeat_layout(&Layout::new::<T>(), n).map(|(k, _)| k)
}
#[inline]
pub(crate) fn repr_c_3(fields: [Layout; 3]) -> Result<(Layout, [usize; 3]), LayoutErr> {
let mut offsets: [usize; 3] = [0; 3];
let mut layout = fields[0];
for i in 1..3 {
let (new_layout, this_offset) = extend_layout(&layout, fields[i])?;
layout = new_layout;
offsets[i] = this_offset;
}
Ok((pad_layout_to_align(&layout), offsets))
}
#[inline]
fn layout_padding_needed_for(this: &Layout, align: usize) -> usize {
let len = this.size();
let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1);
len_rounded_up.wrapping_sub(len)
}
#[inline]
fn repeat_layout(this: &Layout, n: usize) -> Result<(Layout, usize), LayoutErr> {
let padded_size = pad_layout_to_align(this).size();
let alloc_size = padded_size.checked_mul(n).ok_or_else(layout_err)?;
unsafe {
Ok((
Layout::from_size_align_unchecked(alloc_size, this.align()),
padded_size,
))
}
}
#[inline]
fn layout_err() -> LayoutErr {
Layout::from_size_align(0, 0).unwrap_err()
}