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?
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;
}
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);
}