How to create an array of u8 with 32bit aligned?

I'm rewriting some functions written in C with Rust, and found something like this:

void hash(....)
{
    u8 key[BLOCK_SIZE] __aligned(__alignof__(u32)) = { 0 };
    ...
}

this array is allocated on stack, how to do this in Rust?

You can do something like this:

const BLOCK_SIZE: usize = 32;

#[repr(C, align(4))]
struct AlignedBlock(pub [u8;BLOCK_SIZE]);

fn hash()
{
    let key = AlignedBlock([0;BLOCK_SIZE]);
    let _aligned_key_ref = &key.0;
}

In a few weeks (or on nightly now), you will also be able to define AlignedBlock with a const generic argument, which will let it hold any sized array:

const BLOCK_SIZE: usize = 32;

#[repr(C, align(4))]
struct AlignedBlock<const N:usize>(pub [u8;N]);

fn hash()
{
    let key = AlignedBlock([0;BLOCK_SIZE]);
    let _aligned_key_ref = &key.0;
}
2 Likes

Playing around with this some more, you can define a generic Align32<T> wrapper with some suitable Deref implementations. This lets each function specify whether it needs the data to be aligned or not individually:

use std::ops::{Deref,DerefMut};

const BLOCK_SIZE: usize = 32;

#[repr(C, align(4))]
struct Align32<T:?Sized>(pub T);

impl<T:?Sized> Deref for Align32<T> {
    type Target = T;
    fn deref(&self)->&T { &self.0 }
}

impl<T:?Sized> DerefMut for Align32<T> {
    fn deref_mut(&mut self)->&mut T { &mut self.0 }
}

fn needs_aligned_array(_:&Align32<[u8;BLOCK_SIZE]>) {}
fn needs_aligned_slice(_:&Align32<[u8]>) {}
fn needs_array(_:&[u8;BLOCK_SIZE]) {}
fn needs_slice(_:&[u8]) {}

fn hash()
{
    let key = Align32([0;BLOCK_SIZE]);
    
    needs_aligned_array(&key);
    needs_aligned_slice(&key);
    needs_array(&key);
    needs_slice(&*key);
}

(Playground)

2 Likes