Re: [PATCH v2 17/21] rust: num: Add an upward alignment helper for usize

Joel Fernandes
2025-05-03T03:02:27Z

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
+ BitOr
+ Not
{
}

pub trait Unsigned:
Copy
+ Add
+ Sub
+ 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.