oxc/tasks/ast_tools/src/layout.rs
dalaoshu a48ebd6295
fix(tasks): cargo clippy error on rust 1.82.0 (#7283)
I mentioned this clippy issue in the discord help channel. The problem
seems to be related to using the stable rust toolchain, but when I
switched to version `1.81.0`, the issue was resolved.

However, some of the clippy suggestions might still be worth considering
and could be adopted.

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2024-11-15 00:08:04 +08:00

170 lines
4.2 KiB
Rust

#[derive(Debug, Default, Clone)]
pub enum Layout {
#[default]
Unknown,
Layout(KnownLayout),
}
impl Layout {
pub const fn known(size: usize, align: usize, niches: u128) -> Self {
Self::Layout(KnownLayout { size, align, niches, offsets: None })
}
pub fn layout(self) -> Option<KnownLayout> {
if let Self::Layout(layout) = self {
Some(layout)
} else {
None
}
}
}
impl From<KnownLayout> for Layout {
fn from(layout: KnownLayout) -> Self {
Self::Layout(layout)
}
}
#[derive(Debug, Default, Clone)]
pub struct KnownLayout {
size: usize,
align: usize,
/// number of available niches
niches: u128,
offsets: Option<Vec<usize>>,
}
impl KnownLayout {
pub const fn new(size: usize, align: usize, niches: u128) -> Self {
Self { size, align, niches, offsets: None }
}
#[inline]
pub fn size(&self) -> usize {
self.size
}
#[inline]
pub fn align(&self) -> usize {
self.align
}
/// number of available niches
#[inline]
pub fn niches(&self) -> u128 {
self.niches
}
#[expect(unused)]
#[inline]
pub fn offsets(&self) -> Option<&Vec<usize>> {
self.offsets.as_ref()
}
pub fn with_offsets(mut self, offsets: Vec<usize>) -> Self {
self.offsets = Some(offsets);
self
}
/// Panics
/// if doesn't have enough viable space and `can_resize` is false
pub fn consume_niches(&mut self, n: u128, can_resize: bool) {
if self.niches() >= n {
self.niches -= n;
} else if can_resize {
let align = self.align();
self.size += align;
self.niches += max_val_of_bytes(align);
self.consume_niches(n, can_resize);
} else {
panic!("`{}` called on a layout without enough space.", stringify!(consume_niches));
}
}
pub fn unpack(self) -> (/* size */ usize, /* align */ usize, /* offsets */ Option<Vec<usize>>) {
let Self { size, align, offsets, .. } = self;
(size, align, offsets)
}
}
impl Layout {
/// # Panics
/// If `T` has more than 8 niches.
pub const fn of<T>() -> Self {
// TODO: find a better way of calculating this.
struct N1<T>(Option<T>);
struct N2<T>(N1<N1<T>>);
struct N3<T>(N1<N2<T>>);
struct N4<T>(N1<N3<T>>);
struct N5<T>(N1<N4<T>>);
struct N6<T>(N1<N5<T>>);
struct N7<T>(N1<N6<T>>);
struct N8<T>(N1<N7<T>>);
let size = size_of::<T>();
let align = align_of::<T>();
let niches = if size_of::<N1<T>>() > size {
0
} else if size_of::<N2<T>>() > size {
1
} else if size_of::<N3<T>>() > size {
2
} else if size_of::<N4<T>>() > size {
3
} else if size_of::<N5<T>>() > size {
4
} else if size_of::<N6<T>>() > size {
5
} else if size_of::<N7<T>>() > size {
6
} else if size_of::<N8<T>>() > size {
7
} else if size_of::<N8<T>>() == size {
8
} else {
panic!("`T` has more niches than what we can infer automatically");
};
Self::known(size, align, niches)
}
pub const fn zero() -> Self {
#[repr(C)]
struct Empty;
Self::of::<Empty>()
}
pub const fn ptr_32() -> Self {
Layout::known(4, 4, 0)
}
pub const fn ptr_64() -> Self {
Layout::known(8, 8, 0)
}
pub const fn wide_ptr_32() -> Self {
Layout::known(8, 4, 1)
}
pub const fn wide_ptr_64() -> Self {
Layout::of::<&str>()
}
pub fn is_unknown(&self) -> bool {
matches!(self, Self::Unknown)
}
}
/// Returns the max valid number in a primitive with the size of `n` bytes.
/// Panics
/// For `n` bigger than `16`, Or if it's not a power of 2 number
fn max_val_of_bytes(n: usize) -> u128 {
match n {
1 => u128::from(u8::MAX),
2 => u128::from(u16::MAX),
4 => u128::from(u32::MAX),
8 => u128::from(u64::MAX),
16 => u128::MAX,
_ => panic!("We do not support `n` bigger than 16 bytes."),
}
}