from-scratch/lang/tests/bump.rs
2025-11-03 17:06:00 +01:00

69 lines
1.8 KiB
Rust

#![feature(allocator_api, box_as_ptr)]
#[path = "shared/shared.rs"]
mod util;
unsafe extern "C" {
unsafe fn bump_init();
unsafe fn bump_alloc(size: usize, align: usize) -> *mut u8;
}
struct BumpAllocator;
unsafe impl std::alloc::Allocator for BumpAllocator {
fn allocate(
&self,
layout: std::alloc::Layout,
) -> Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError> {
unsafe {
let ptr = bump_alloc(layout.size(), layout.align());
if ptr.is_null() {
Err(std::alloc::AllocError)
} else {
Ok(std::ptr::NonNull::slice_from_raw_parts(
std::ptr::NonNull::new_unchecked(ptr),
layout.size(),
))
}
}
}
unsafe fn deallocate(&self, _ptr: std::ptr::NonNull<u8>, _layout: std::alloc::Layout) {
// Bump allocator does not deallocate individual allocations
}
}
fn main() {
unsafe {
bump_init();
}
let a = Box::new_in(42u32, BumpAllocator);
let b = Box::new_in(42u32, BumpAllocator);
let c = Box::new_in(52u32, BumpAllocator);
eprintln!("a: {a}, b: {b}, c: {c}");
assert_ne!(Box::as_ptr(&a), Box::as_ptr(&b));
assert_eq!(*a, *b);
struct BigType {
data: [u8; 0x1010],
}
let mut big = Box::new_in(BigType { data: [0; 0x1010] }, BumpAllocator);
assert_ne!(Box::as_ptr(&big) as *const (), Box::as_ptr(&a) as *const ());
big.data[47] = 123;
assert_eq!(big.data[47], 123);
#[repr(align(256))]
struct AlignedType {
#[allow(dead_code)]
data: [u8; 512],
}
let aligned = Box::new_in(AlignedType { data: [0; 512] }, BumpAllocator);
assert_eq!(
(Box::as_ptr(&aligned) as usize) % 256,
0,
"Aligned allocation should be aligned to 256 bytes"
);
}