Last active
March 23, 2025 15:23
-
-
Save lovely-error/f8e40be14118d8334b9e68f679996e53 to your computer and use it in GitHub Desktop.
Separate stride and size in rust
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(decl_macro)] | |
trait MemLayout where Self:Sized { | |
// size, excluding trailing padding | |
fn size() -> usize { | |
core::mem::size_of::<Self>() | |
} | |
/// highest alignment among the members | |
/// of the product | |
fn alignment() -> usize; | |
/// space taken by one instance of this type in linear addressing | |
fn stride() -> usize { | |
Self::size().next_multiple_of(Self::alignment()) | |
} | |
} | |
macro defstruct_fine_layout( | |
struct $name:ident { | |
$($field_name:ident : $ty:ty),* | |
} | |
) { | |
#[repr(packed)] | |
struct $name { | |
$($field_name : $ty),* | |
} | |
impl MemLayout for $name { | |
fn alignment() -> usize { | |
const { | |
let aligns = [ | |
$(core::mem::align_of::<$ty>()),* | |
]; | |
// let names = [ | |
// $(stringify!($field_name)),* | |
// ]; | |
// hint: core::intrinsics::const_allocate ? | |
if let Some(faulty_member) = check_field_seqv_aligned_ok(aligns) { | |
let err_msg = concat!( | |
"Member ", | |
// stringify!(names[faulty_member]), | |
"with index ", | |
stringify!(faulty_member), | |
" of struct ", | |
stringify!($name), | |
" does not follow next member in decreasing alignment order" | |
); | |
panic!("{}",err_msg); | |
} | |
compute_highest_seqv_alignment(aligns) | |
} | |
} | |
} | |
} | |
const fn check_field_seqv_aligned_ok<const LEN:usize>( | |
aligns: [usize;LEN] | |
) -> Option<usize> { | |
let mut current_index = 0; | |
loop { | |
if current_index + 1 >= LEN { break } | |
let this = aligns[current_index]; | |
let next = aligns[current_index + 1]; | |
if this < next { return Some(current_index) } | |
current_index += 1; | |
} | |
return None | |
} | |
const fn compute_highest_seqv_alignment<const LEN:usize>( | |
aligns: [usize;LEN] | |
) -> usize { | |
let end_index = LEN; | |
let mut current_index = 0; | |
let mut max_align_size = 1; | |
loop { | |
if current_index == end_index { break } | |
let align = aligns[current_index]; | |
if align > max_align_size { | |
max_align_size = align; | |
} | |
current_index += 1; | |
} | |
return max_align_size | |
} | |
defstruct_fine_layout! { | |
struct Test { | |
_m1: u32, | |
_m2: u16, | |
_m3: u8 | |
} | |
} | |
fn main() { | |
println!("size is {:?}", Test::size()); | |
println!("alignment is {:?}", Test::alignment()); | |
println!("stride is {:?}", Test::stride()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment