[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