[PATCH v2 17/21] rust: num: Add an upward alignment helper for usize
Joel Fernandes
joelagnelf at nvidia.com
Sat May 3 03:02:20 UTC 2025
On 5/2/2025 9:59 PM, Alexandre Courbot wrote:
>> pub trait AlignUp {
>> fn align_up(self, alignment: Self) -> Self;
>> }
>>
>> macro_rules! align_up_impl {
>> ($($t:ty),+) => {
>> $(
>> impl AlignUp for $t {
>> fn align_up(self, alignment: Self) -> Self {
>> (self + alignment - 1) & !(alignment - 1)
>> }
>> }
>> )+
>> }
>> }
>>
>> align_up_impl!(usize, u8, u16, u32, u64, u128);
>>
>> Or, we can even combine the 2 approaches. Use macros for the "impl Alignable"
>> and use generics on the Alignable trait.
>>
>> macro_rules! impl_alignable {
>> ($($t:ty),+) => {
>> $(
>> impl Alignable for $t {}
>> )+
>> };
>> }
>>
>> impl_alignable!(usize, u8, u16, u32, u64, u128);
>>
>> pub trait AlignUp {
>> fn align_up(self, alignment: Self) -> Self;
>> }
>>
>> impl<T> AlignUp for T
>> where
>> T: Alignable,
>> {
>> fn align_up(self, alignment: Self) -> Self {
>> let one = T::from(1u8);
>> (self + alignment - one) & !(alignment - one)
>> }
>> }
>>
>> Thoughts?
> I think that's the correct way to do it and am fully on board with this
> approach.
>
> The only thing this doesn't solve is that it doesn't provide `const`
> functions. But maybe for that purpose we can use a single macro that
> nicely panics at build-time should an overflow occur.
Great, thanks. I split the traits as follows and it is cleaner and works. I will
look into the build-time overflow check and the returning of Result change on
Monday. Let me know if any objections. I added the #[inline] and hopefully that
gives similar benefits to const that you're seeking:
use core::ops::{BitAnd, BitOr, Not, Add, Sub};
pub trait BitOps:
Copy
+ BitAnd<Output = Self>
+ BitOr<Output = Self>
+ Not<Output = Self>
{
}
pub trait Unsigned:
Copy
+ Add<Output = Self>
+ Sub<Output = Self>
+ From<u8>
{
}
macro_rules! impl_unsigned_traits {
($($t:ty),+) => {
$(
impl Unsigned for $t {}
impl BitOps for $t {}
)+
};
}
impl_unsigned_traits!(usize, u8, u16, u32, u64, u128);
pub trait AlignUp {
fn align_up(self, alignment: Self) -> Self;
}
impl<T> AlignUp for T
where
T: BitOps + Unsigned,
{
#[inline]
fn align_up(self, alignment: Self) -> Self {
let one = T::from(1u8);
(self + alignment - one) & !(alignment - one)
}
}
Thanks.
More information about the dri-devel
mailing list