Alexandre Courbot
2025-Jun-12 14:01 UTC
[PATCH v5 04/23] rust: add new `num` module with `PowerOfTwo` type
Introduce the `num` module, featuring the `PowerOfTwo` unsigned wrapper
that guarantees (at build-time or runtime) that a value is a power of
two.
Such a property is often useful to maintain. In the context of the
kernel, powers of two are often used to align addresses or sizes up and
down, or to create masks. These operations are provided by this type.
It is introduced to be first used by the nova-core driver.
Signed-off-by: Alexandre Courbot <acourbot at nvidia.com>
---
rust/kernel/lib.rs | 1 +
rust/kernel/num.rs | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 174 insertions(+)
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index
6b4774b2b1c37f4da1866e993be6230bc6715841..2955f65da1278dd4cba1e4272ff178b8211a892c
100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -89,6 +89,7 @@
pub mod mm;
#[cfg(CONFIG_NET)]
pub mod net;
+pub mod num;
pub mod of;
#[cfg(CONFIG_PM_OPP)]
pub mod opp;
diff --git a/rust/kernel/num.rs b/rust/kernel/num.rs
new file mode 100644
index
0000000000000000000000000000000000000000..ee0f67ad1a89e69f5f8d2077eba5541b472e7d8a
--- /dev/null
+++ b/rust/kernel/num.rs
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Numerical and binary utilities for primitive types.
+
+use crate::build_assert;
+use core::borrow::Borrow;
+use core::fmt::Debug;
+use core::hash::Hash;
+use core::ops::Deref;
+
+/// An unsigned integer which is guaranteed to be a power of 2.
+#[derive(Debug, Clone, Copy)]
+#[repr(transparent)]
+pub struct PowerOfTwo<T>(T);
+
+macro_rules! power_of_two_impl {
+ ($($t:ty),+) => {
+ $(
+ impl PowerOfTwo<$t> {
+ /// Validates that `v` is a power of two at build-time, and
returns it wrapped into
+ /// `PowerOfTwo`.
+ ///
+ /// A build error is triggered if `v` cannot be asserted to be
a power of two.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use kernel::num::PowerOfTwo;
+ ///
+ /// let v = PowerOfTwo::<u32>::new(256);
+ /// assert_eq!(v.value(), 256);
+ /// ```
+ #[inline(always)]
+ pub const fn new(v: $t) -> Self {
+ build_assert!(v.count_ones() == 1);
+ Self(v)
+ }
+
+ /// Validates that `v` is a power of two at runtime, and
returns it wrapped into
+ /// `PowerOfTwo`.
+ ///
+ /// `None` is returned if `v` was not a power of two.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use kernel::num::PowerOfTwo;
+ ///
+ ///
assert_eq!(PowerOfTwo::<u32>::try_new(16).unwrap().value(), 16);
+ /// assert_eq!(PowerOfTwo::<u32>::try_new(15), None);
+ /// ```
+ #[inline(always)]
+ pub const fn try_new(v: $t) -> Option<Self> {
+ match v.count_ones() {
+ 1 => Some(Self(v)),
+ _ => None,
+ }
+ }
+
+ /// Returns the value of this instance.
+ ///
+ /// It is guaranteed to be a power of two.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use kernel::num::PowerOfTwo;
+ ///
+ /// let v = PowerOfTwo::<u32>::new(256);
+ /// assert_eq!(v.value(), 256);
+ /// ```
+ #[inline(always)]
+ pub const fn value(&self) -> $t {
+ self.0
+ }
+
+ /// Returns the mask corresponding to `self.value() - 1`.
+ #[inline(always)]
+ pub const fn mask(&self) -> $t {
+ self.0.wrapping_sub(1)
+ }
+
+ /// Aligns `self` down to `alignment`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use kernel::num::PowerOfTwo;
+ ///
+ ///
assert_eq!(PowerOfTwo::<u32>::new(0x1000).align_down(0x4fff), 0x4000);
+ /// ```
+ #[inline(always)]
+ pub const fn align_down(self, value: $t) -> $t {
+ value & !self.mask()
+ }
+
+ /// Aligns `value` up to `self`.
+ ///
+ /// Wraps around to `0` if the requested alignment pushes the
result above the
+ /// type's limits.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use kernel::num::PowerOfTwo;
+ ///
+ ///
assert_eq!(PowerOfTwo::<u32>::new(0x1000).align_up(0x4fff), 0x5000);
+ ///
assert_eq!(PowerOfTwo::<u32>::new(0x1000).align_up(0x4000), 0x4000);
+ ///
assert_eq!(PowerOfTwo::<u32>::new(0x1000).align_up(0x0), 0x0);
+ ///
assert_eq!(PowerOfTwo::<u16>::new(0x100).align_up(0xffff), 0x0);
+ /// ```
+ #[inline(always)]
+ pub const fn align_up(self, value: $t) -> $t {
+ self.align_down(value.wrapping_add(self.mask()))
+ }
+ }
+ )+
+ };
+}
+
+power_of_two_impl!(usize, u8, u16, u32, u64, u128);
+
+impl<T> Deref for PowerOfTwo<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<T> PartialEq for PowerOfTwo<T>
+where
+ T: PartialEq,
+{
+ fn eq(&self, other: &Self) -> bool {
+ self.0 == other.0
+ }
+}
+
+impl<T> Eq for PowerOfTwo<T> where T: Eq {}
+
+impl<T> PartialOrd for PowerOfTwo<T>
+where
+ T: PartialOrd,
+{
+ fn partial_cmp(&self, other: &Self) ->
Option<core::cmp::Ordering> {
+ self.0.partial_cmp(&other.0)
+ }
+}
+
+impl<T> Ord for PowerOfTwo<T>
+where
+ T: Ord,
+{
+ fn cmp(&self, other: &Self) -> core::cmp::Ordering {
+ self.0.cmp(&other.0)
+ }
+}
+
+impl<T> Hash for PowerOfTwo<T>
+where
+ T: Hash,
+{
+ fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
+ self.0.hash(state);
+ }
+}
+
+impl<T> Borrow<T> for PowerOfTwo<T> {
+ fn borrow(&self) -> &T {
+ &self.0
+ }
+}
--
2.49.0
Boqun Feng
2025-Jun-12 15:07 UTC
[PATCH v5 04/23] rust: add new `num` module with `PowerOfTwo` type
On Thu, Jun 12, 2025 at 11:01:32PM +0900, Alexandre Courbot wrote:> Introduce the `num` module, featuring the `PowerOfTwo` unsigned wrapper > that guarantees (at build-time or runtime) that a value is a power of > two. > > Such a property is often useful to maintain. In the context of the > kernel, powers of two are often used to align addresses or sizes up and > down, or to create masks. These operations are provided by this type. > > It is introduced to be first used by the nova-core driver. > > Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> > --- > rust/kernel/lib.rs | 1 + > rust/kernel/num.rs | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 174 insertions(+) > > diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs > index 6b4774b2b1c37f4da1866e993be6230bc6715841..2955f65da1278dd4cba1e4272ff178b8211a892c 100644 > --- a/rust/kernel/lib.rs > +++ b/rust/kernel/lib.rs > @@ -89,6 +89,7 @@ > pub mod mm; > #[cfg(CONFIG_NET)] > pub mod net; > +pub mod num; > pub mod of; > #[cfg(CONFIG_PM_OPP)] > pub mod opp; > diff --git a/rust/kernel/num.rs b/rust/kernel/num.rs > new file mode 100644 > index 0000000000000000000000000000000000000000..ee0f67ad1a89e69f5f8d2077eba5541b472e7d8a > --- /dev/null > +++ b/rust/kernel/num.rs > @@ -0,0 +1,173 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +//! Numerical and binary utilities for primitive types. > + > +use crate::build_assert; > +use core::borrow::Borrow; > +use core::fmt::Debug; > +use core::hash::Hash; > +use core::ops::Deref; > + > +/// An unsigned integer which is guaranteed to be a power of 2. > +#[derive(Debug, Clone, Copy)] > +#[repr(transparent)] > +pub struct PowerOfTwo<T>(T); > + > +macro_rules! power_of_two_impl { > + ($($t:ty),+) => { > + $( > + impl PowerOfTwo<$t> { > + /// Validates that `v` is a power of two at build-time, and returns it wrapped into > + /// `PowerOfTwo`. > + /// > + /// A build error is triggered if `v` cannot be asserted to be a power of two. > + /// > + /// # Examples > + /// > + /// ``` > + /// use kernel::num::PowerOfTwo; > + /// > + /// let v = PowerOfTwo::<u32>::new(256); > + /// assert_eq!(v.value(), 256); > + /// ``` > + #[inline(always)] > + pub const fn new(v: $t) -> Self {Then this function should be unsafe, because an invalid `v` can create an invalid PowerOfTwo.> + build_assert!(v.count_ones() == 1); > + Self(v) > + } > + > + /// Validates that `v` is a power of two at runtime, and returns it wrapped into > + /// `PowerOfTwo`. > + /// > + /// `None` is returned if `v` was not a power of two. > + /// > + /// # Examples > + /// > + /// ``` > + /// use kernel::num::PowerOfTwo; > + /// > + /// assert_eq!(PowerOfTwo::<u32>::try_new(16).unwrap().value(), 16); > + /// assert_eq!(PowerOfTwo::<u32>::try_new(15), None); > + /// ``` > + #[inline(always)] > + pub const fn try_new(v: $t) -> Option<Self> { > + match v.count_ones() { > + 1 => Some(Self(v)), > + _ => None, > + } > + } > + > + /// Returns the value of this instance. > + /// > + /// It is guaranteed to be a power of two. > + /// > + /// # Examples > + /// > + /// ``` > + /// use kernel::num::PowerOfTwo; > + /// > + /// let v = PowerOfTwo::<u32>::new(256); > + /// assert_eq!(v.value(), 256); > + /// ``` > + #[inline(always)] > + pub const fn value(&self) -> $t { > + self.0 > + } > + > + /// Returns the mask corresponding to `self.value() - 1`. > + #[inline(always)] > + pub const fn mask(&self) -> $t { > + self.0.wrapping_sub(1) > + } > + > + /// Aligns `self` down to `alignment`. > + /// > + /// # Examples > + /// > + /// ``` > + /// use kernel::num::PowerOfTwo; > + /// > + /// assert_eq!(PowerOfTwo::<u32>::new(0x1000).align_down(0x4fff), 0x4000); > + /// ``` > + #[inline(always)] > + pub const fn align_down(self, value: $t) -> $t {I'm late to party, but could we instead implement: pub const fn round_down<i32>(value: i32, shift: i32) -> i32 { value & !((1 << shift) - 1) } pub const fn round_up<i32>(value: i32, shift: i32) -> i32 { let mask = (1 << shift) - 1; value.wrapping_add(mask) & !mask } ? It's much harder to pass an invalid alignment with this. Regards, Boqun> + value & !self.mask() > + } > + > + /// Aligns `value` up to `self`. > + /// > + /// Wraps around to `0` if the requested alignment pushes the result above the > + /// type's limits. > + /// > + /// # Examples > + /// > + /// ``` > + /// use kernel::num::PowerOfTwo; > + /// > + /// assert_eq!(PowerOfTwo::<u32>::new(0x1000).align_up(0x4fff), 0x5000); > + /// assert_eq!(PowerOfTwo::<u32>::new(0x1000).align_up(0x4000), 0x4000); > + /// assert_eq!(PowerOfTwo::<u32>::new(0x1000).align_up(0x0), 0x0); > + /// assert_eq!(PowerOfTwo::<u16>::new(0x100).align_up(0xffff), 0x0); > + /// ``` > + #[inline(always)] > + pub const fn align_up(self, value: $t) -> $t { > + self.align_down(value.wrapping_add(self.mask())) > + } > + } > + )+ > + }; > +} > + > +power_of_two_impl!(usize, u8, u16, u32, u64, u128); > + > +impl<T> Deref for PowerOfTwo<T> { > + type Target = T; > + > + fn deref(&self) -> &Self::Target { > + &self.0 > + } > +} > + > +impl<T> PartialEq for PowerOfTwo<T> > +where > + T: PartialEq, > +{ > + fn eq(&self, other: &Self) -> bool { > + self.0 == other.0 > + } > +} > + > +impl<T> Eq for PowerOfTwo<T> where T: Eq {} > + > +impl<T> PartialOrd for PowerOfTwo<T> > +where > + T: PartialOrd, > +{ > + fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> { > + self.0.partial_cmp(&other.0) > + } > +} > + > +impl<T> Ord for PowerOfTwo<T> > +where > + T: Ord, > +{ > + fn cmp(&self, other: &Self) -> core::cmp::Ordering { > + self.0.cmp(&other.0) > + } > +} > + > +impl<T> Hash for PowerOfTwo<T> > +where > + T: Hash, > +{ > + fn hash<H: core::hash::Hasher>(&self, state: &mut H) { > + self.0.hash(state); > + } > +} > + > +impl<T> Borrow<T> for PowerOfTwo<T> { > + fn borrow(&self) -> &T { > + &self.0 > + } > +} > > -- > 2.49.0 >
John Hubbard
2025-Jun-12 20:00 UTC
[PATCH v5 04/23] rust: add new `num` module with `PowerOfTwo` type
On 6/12/25 8:07 AM, Boqun Feng wrote:> On Thu, Jun 12, 2025 at 11:01:32PM +0900, Alexandre Courbot wrote:...>> + #[inline(always)] >> + pub const fn align_down(self, value: $t) -> $t { > > I'm late to party, but could we instead implement: > > pub const fn round_down<i32>(value: i32, shift: i32) -> i32 { > value & !((1 << shift) - 1) > } > > pub const fn round_up<i32>(value: i32, shift: i32) -> i32 { > let mask = (1 << shift) - 1; > value.wrapping_add(mask) & !mask > }Just a naming concern here. The function name, and the "shift" argument is extremely odd there. And that's because it is re-inventing the concept of align_down() and align_up(), but with a misleading name and a hard to understand "shift" argument. If you are "rounding" to a power of two, that's normally called alignment, at least in kernel code. And if you are rounding to the nearest...integer, for example, that's rounding. But "rounding" with a "shift" argument? That's a little too creative! :)> > ? It's much harder to pass an invalid alignment with this.Hopefully we can address argument validation without blowing up the usual naming conventions. thanks, -- John Hubbard
Alexandre Courbot
2025-Jun-13 14:16 UTC
[PATCH v5 04/23] rust: add new `num` module with `PowerOfTwo` type
On Fri Jun 13, 2025 at 12:07 AM JST, Boqun Feng wrote:> On Thu, Jun 12, 2025 at 11:01:32PM +0900, Alexandre Courbot wrote: >> Introduce the `num` module, featuring the `PowerOfTwo` unsigned wrapper >> that guarantees (at build-time or runtime) that a value is a power of >> two. >> >> Such a property is often useful to maintain. In the context of the >> kernel, powers of two are often used to align addresses or sizes up and >> down, or to create masks. These operations are provided by this type. >> >> It is introduced to be first used by the nova-core driver. >> >> Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> >> --- >> rust/kernel/lib.rs | 1 + >> rust/kernel/num.rs | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 174 insertions(+) >> >> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs >> index 6b4774b2b1c37f4da1866e993be6230bc6715841..2955f65da1278dd4cba1e4272ff178b8211a892c 100644 >> --- a/rust/kernel/lib.rs >> +++ b/rust/kernel/lib.rs >> @@ -89,6 +89,7 @@ >> pub mod mm; >> #[cfg(CONFIG_NET)] >> pub mod net; >> +pub mod num; >> pub mod of; >> #[cfg(CONFIG_PM_OPP)] >> pub mod opp; >> diff --git a/rust/kernel/num.rs b/rust/kernel/num.rs >> new file mode 100644 >> index 0000000000000000000000000000000000000000..ee0f67ad1a89e69f5f8d2077eba5541b472e7d8a >> --- /dev/null >> +++ b/rust/kernel/num.rs >> @@ -0,0 +1,173 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> + >> +//! Numerical and binary utilities for primitive types. >> + >> +use crate::build_assert; >> +use core::borrow::Borrow; >> +use core::fmt::Debug; >> +use core::hash::Hash; >> +use core::ops::Deref; >> + >> +/// An unsigned integer which is guaranteed to be a power of 2. >> +#[derive(Debug, Clone, Copy)] >> +#[repr(transparent)] >> +pub struct PowerOfTwo<T>(T); >> + >> +macro_rules! power_of_two_impl { >> + ($($t:ty),+) => { >> + $( >> + impl PowerOfTwo<$t> { >> + /// Validates that `v` is a power of two at build-time, and returns it wrapped into >> + /// `PowerOfTwo`. >> + /// >> + /// A build error is triggered if `v` cannot be asserted to be a power of two. >> + /// >> + /// # Examples >> + /// >> + /// ``` >> + /// use kernel::num::PowerOfTwo; >> + /// >> + /// let v = PowerOfTwo::<u32>::new(256); >> + /// assert_eq!(v.value(), 256); >> + /// ``` >> + #[inline(always)] >> + pub const fn new(v: $t) -> Self { > > Then this function should be unsafe, because an invalid `v` can create > an invalid PowerOfTwo.Doesn't the `build_assert` below allow us to keep this method safe, since it will fail at build-time if it cannot be asserted that `v` is a power of two?> >> + build_assert!(v.count_ones() == 1); >> + Self(v) >> + } >> + >> + /// Validates that `v` is a power of two at runtime, and returns it wrapped into >> + /// `PowerOfTwo`. >> + /// >> + /// `None` is returned if `v` was not a power of two. >> + /// >> + /// # Examples >> + /// >> + /// ``` >> + /// use kernel::num::PowerOfTwo; >> + /// >> + /// assert_eq!(PowerOfTwo::<u32>::try_new(16).unwrap().value(), 16); >> + /// assert_eq!(PowerOfTwo::<u32>::try_new(15), None); >> + /// ``` >> + #[inline(always)] >> + pub const fn try_new(v: $t) -> Option<Self> { >> + match v.count_ones() { >> + 1 => Some(Self(v)), >> + _ => None, >> + } >> + } >> + >> + /// Returns the value of this instance. >> + /// >> + /// It is guaranteed to be a power of two. >> + /// >> + /// # Examples >> + /// >> + /// ``` >> + /// use kernel::num::PowerOfTwo; >> + /// >> + /// let v = PowerOfTwo::<u32>::new(256); >> + /// assert_eq!(v.value(), 256); >> + /// ``` >> + #[inline(always)] >> + pub const fn value(&self) -> $t { >> + self.0 >> + } >> + >> + /// Returns the mask corresponding to `self.value() - 1`. >> + #[inline(always)] >> + pub const fn mask(&self) -> $t { >> + self.0.wrapping_sub(1) >> + } >> + >> + /// Aligns `self` down to `alignment`. >> + /// >> + /// # Examples >> + /// >> + /// ``` >> + /// use kernel::num::PowerOfTwo; >> + /// >> + /// assert_eq!(PowerOfTwo::<u32>::new(0x1000).align_down(0x4fff), 0x4000); >> + /// ``` >> + #[inline(always)] >> + pub const fn align_down(self, value: $t) -> $t { > > I'm late to party, but could we instead implement: > > pub const fn round_down<i32>(value: i32, shift: i32) -> i32 { > value & !((1 << shift) - 1) > } > > pub const fn round_up<i32>(value: i32, shift: i32) -> i32 { > let mask = (1 << shift) - 1; > value.wrapping_add(mask) & !mask > } > > ? It's much harder to pass an invalid alignment with this.It also forces you to think in terms of shifts instead of values - i.e. you cannot round to `0x1000` as it commonly done in the kernel, now you need to do some mental gymnastics to know it is actually a shift of `12`. Being able to use the actual value to round to is more familiar (and natural) to me.
Boqun Feng
2025-Jun-14 17:31 UTC
[PATCH v5 04/23] rust: add new `num` module with `PowerOfTwo` type
On Thu, Jun 12, 2025 at 11:01:32PM +0900, Alexandre Courbot wrote: [...]> +/// An unsigned integer which is guaranteed to be a power of 2. > +#[derive(Debug, Clone, Copy)] > +#[repr(transparent)] > +pub struct PowerOfTwo<T>(T); > +[...]> +impl<T> Deref for PowerOfTwo<T> {Why do we need `impl Deref` (and the `impl Borrow` below)? A similar concept `NonZero` in std doesn't impl them as well.> + type Target = T; > + > + fn deref(&self) -> &Self::Target { > + &self.0 > + } > +} > + > +impl<T> PartialEq for PowerOfTwo<T>Any reason you want to impl these manually instead of deriving? For `NonZero`, the std wants to impl these traits only for `ZeroablePrimitive` types, but we don't have a similar trait here. Explaining the above in the comments is much appreciated. Regards, Boqun> +where > + T: PartialEq, > +{ > + fn eq(&self, other: &Self) -> bool { > + self.0 == other.0 > + } > +} > + > +impl<T> Eq for PowerOfTwo<T> where T: Eq {} > + > +impl<T> PartialOrd for PowerOfTwo<T> > +where > + T: PartialOrd, > +{ > + fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> { > + self.0.partial_cmp(&other.0) > + } > +} > + > +impl<T> Ord for PowerOfTwo<T> > +where > + T: Ord, > +{ > + fn cmp(&self, other: &Self) -> core::cmp::Ordering { > + self.0.cmp(&other.0) > + } > +} > + > +impl<T> Hash for PowerOfTwo<T> > +where > + T: Hash, > +{ > + fn hash<H: core::hash::Hasher>(&self, state: &mut H) { > + self.0.hash(state); > + } > +} > + > +impl<T> Borrow<T> for PowerOfTwo<T> { > + fn borrow(&self) -> &T { > + &self.0 > + } > +} > > -- > 2.49.0 >
Benno Lossin
2025-Jun-14 19:09 UTC
[PATCH v5 04/23] rust: add new `num` module with `PowerOfTwo` type
On Thu Jun 12, 2025 at 4:01 PM CEST, Alexandre Courbot wrote:> diff --git a/rust/kernel/num.rs b/rust/kernel/num.rs > new file mode 100644 > index 0000000000000000000000000000000000000000..ee0f67ad1a89e69f5f8d2077eba5541b472e7d8a > --- /dev/null > +++ b/rust/kernel/num.rs > @@ -0,0 +1,173 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +//! Numerical and binary utilities for primitive types. > + > +use crate::build_assert; > +use core::borrow::Borrow; > +use core::fmt::Debug; > +use core::hash::Hash; > +use core::ops::Deref; > + > +/// An unsigned integer which is guaranteed to be a power of 2. > +#[derive(Debug, Clone, Copy)] > +#[repr(transparent)]Let's add a `# Safety` section with the invariant that `T` is a power of 2. Maybe we should even have an `Int` trait for the different integer types that we constrain `T` to.> +pub struct PowerOfTwo<T>(T); > + > +macro_rules! power_of_two_impl { > + ($($t:ty),+) => { > + $( > + impl PowerOfTwo<$t> { > + /// Validates that `v` is a power of two at build-time, and returns it wrapped into > + /// `PowerOfTwo`. > + /// > + /// A build error is triggered if `v` cannot be asserted to be a power of two. > + /// > + /// # Examples > + /// > + /// ``` > + /// use kernel::num::PowerOfTwo; > + /// > + /// let v = PowerOfTwo::<u32>::new(256); > + /// assert_eq!(v.value(), 256); > + /// ``` > + #[inline(always)] > + pub const fn new(v: $t) -> Self { > + build_assert!(v.count_ones() == 1); > + Self(v) > + }We also probably want an `unsafe new_unchecked(v: $t) -> Self`. It can still use a `debug_assert!` to verify the value.> + > + /// Validates that `v` is a power of two at runtime, and returns it wrapped into > + /// `PowerOfTwo`. > + /// > + /// `None` is returned if `v` was not a power of two. > + /// > + /// # Examples > + /// > + /// ``` > + /// use kernel::num::PowerOfTwo; > + /// > + /// assert_eq!(PowerOfTwo::<u32>::try_new(16).unwrap().value(), 16); > + /// assert_eq!(PowerOfTwo::<u32>::try_new(15), None); > + /// ``` > + #[inline(always)] > + pub const fn try_new(v: $t) -> Option<Self> { > + match v.count_ones() { > + 1 => Some(Self(v)), > + _ => None, > + } > + } > + > + /// Returns the value of this instance. > + /// > + /// It is guaranteed to be a power of two. > + /// > + /// # Examples > + /// > + /// ``` > + /// use kernel::num::PowerOfTwo; > + /// > + /// let v = PowerOfTwo::<u32>::new(256); > + /// assert_eq!(v.value(), 256); > + /// ``` > + #[inline(always)] > + pub const fn value(&self) -> $t {Since this type is `Copy`, we should use `self` here instead of `&self`. Why not add if !self.0.is_power_of_two() { unsafe { ::core::hint::unreachable_unchecked() } } here?> + self.0 > + } > + > + /// Returns the mask corresponding to `self.value() - 1`. > + #[inline(always)] > + pub const fn mask(&self) -> $t { > + self.0.wrapping_sub(1)And then use `self.value()` here instead? (we could even use `self.value() - 1`, since the optimizer can remove the overflow check: https://godbolt.org/z/nvGaozGMW but wrapping_sub is fine. The optimizations will most likely be more useful in other arithmetic with `.value()`)> + } > + > + /// Aligns `self` down to `alignment`. > + /// > + /// # Examples > + /// > + /// ``` > + /// use kernel::num::PowerOfTwo; > + /// > + /// assert_eq!(PowerOfTwo::<u32>::new(0x1000).align_down(0x4fff), 0x4000); > + /// ``` > + #[inline(always)] > + pub const fn align_down(self, value: $t) -> $t { > + value & !self.mask() > + } > + > + /// Aligns `value` up to `self`. > + /// > + /// Wraps around to `0` if the requested alignment pushes the result above the > + /// type's limits. > + /// > + /// # Examples > + /// > + /// ``` > + /// use kernel::num::PowerOfTwo; > + /// > + /// assert_eq!(PowerOfTwo::<u32>::new(0x1000).align_up(0x4fff), 0x5000); > + /// assert_eq!(PowerOfTwo::<u32>::new(0x1000).align_up(0x4000), 0x4000); > + /// assert_eq!(PowerOfTwo::<u32>::new(0x1000).align_up(0x0), 0x0); > + /// assert_eq!(PowerOfTwo::<u16>::new(0x100).align_up(0xffff), 0x0); > + /// ``` > + #[inline(always)] > + pub const fn align_up(self, value: $t) -> $t { > + self.align_down(value.wrapping_add(self.mask())) > + } > + } > + )+ > + }; > +} > + > +power_of_two_impl!(usize, u8, u16, u32, u64, u128); > + > +impl<T> Deref for PowerOfTwo<T> { > + type Target = T; > + > + fn deref(&self) -> &Self::Target { > + &self.0 > + } > +} > + > +impl<T> PartialEq for PowerOfTwo<T> > +where > + T: PartialEq, > +{ > + fn eq(&self, other: &Self) -> bool { > + self.0 == other.0 > + } > +} > + > +impl<T> Eq for PowerOfTwo<T> where T: Eq {} > + > +impl<T> PartialOrd for PowerOfTwo<T> > +where > + T: PartialOrd, > +{ > + fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> { > + self.0.partial_cmp(&other.0) > + } > +} > + > +impl<T> Ord for PowerOfTwo<T> > +where > + T: Ord, > +{ > + fn cmp(&self, other: &Self) -> core::cmp::Ordering { > + self.0.cmp(&other.0) > + } > +} > + > +impl<T> Hash for PowerOfTwo<T> > +where > + T: Hash, > +{ > + fn hash<H: core::hash::Hasher>(&self, state: &mut H) { > + self.0.hash(state); > + } > +}Can't these traits also be implemented using the derive macros? --- Cheers, Benno> + > +impl<T> Borrow<T> for PowerOfTwo<T> { > + fn borrow(&self) -> &T { > + &self.0 > + } > +}
Miguel Ojeda
2025-Jun-15 13:32 UTC
[PATCH v5 04/23] rust: add new `num` module with `PowerOfTwo` type
On Thu, Jun 12, 2025 at 4:02?PM Alexandre Courbot <acourbot at nvidia.com> wrote:> > + /// assert_eq!(PowerOfTwo::<u32>::try_new(16).unwrap().value(), 16);By the way, we are trying to write examples close to normal kernel code as possible, so could you please use `?` here instead of `unwrap()`? It is not a big deal, when within `assert`s, but there is value in not showing any `unwrap()`s, and to spot easily places where we actually do `unwrap()`. Also, please use intra-doc links wherever they may work, e.g. I think [`PowerOfTwo`] and [`None`] will work. Thanks! Cheers, Miguel
Alexandre Courbot
2025-Jun-16 05:13 UTC
[PATCH v5 04/23] rust: add new `num` module with `PowerOfTwo` type
On Sun Jun 15, 2025 at 10:32 PM JST, Miguel Ojeda wrote:> On Thu, Jun 12, 2025 at 4:02?PM Alexandre Courbot <acourbot at nvidia.com> wrote: >> >> + /// assert_eq!(PowerOfTwo::<u32>::try_new(16).unwrap().value(), 16); > > By the way, we are trying to write examples close to normal kernel > code as possible, so could you please use `?` here instead of > `unwrap()`? > > It is not a big deal, when within `assert`s, but there is value in not > showing any `unwrap()`s, and to spot easily places where we actually > do `unwrap()`.The fact that `try_new` returns an `Option` makes it a bit difficult to do nicely - one would have to add a verbose `ok_or` to turn it into a `Result`. But that doesn't matter as this test can be (better) written as follows: assert_eq!(PowerOfTwo::<u32>::try_new(16), Some(PowerOfTwo::<u32>::new(16))); And all is well.> Also, please use intra-doc links wherever they may work, e.g. I think > [`PowerOfTwo`] and [`None`] will work.Added the links where relevant, sorry for the omission!
Alexandre Courbot
2025-Jun-16 05:19 UTC
[PATCH v5 04/23] rust: add new `num` module with `PowerOfTwo` type
On Sun Jun 15, 2025 at 2:31 AM JST, Boqun Feng wrote:> On Thu, Jun 12, 2025 at 11:01:32PM +0900, Alexandre Courbot wrote: > [...] >> +/// An unsigned integer which is guaranteed to be a power of 2. >> +#[derive(Debug, Clone, Copy)] >> +#[repr(transparent)] >> +pub struct PowerOfTwo<T>(T); >> + > [...] >> +impl<T> Deref for PowerOfTwo<T> { > > Why do we need `impl Deref` (and the `impl Borrow` below)? A similar > concept `NonZero` in std doesn't impl them as well.I wanted to be exhaustive but you're right, we don't really need these implementations (especially if `NonZero` doesn't provide them either).> >> + type Target = T; >> + >> + fn deref(&self) -> &Self::Target { >> + &self.0 >> + } >> +} >> + >> +impl<T> PartialEq for PowerOfTwo<T> > > Any reason you want to impl these manually instead of deriving? For > `NonZero`, the std wants to impl these traits only for > `ZeroablePrimitive` types, but we don't have a similar trait here.Deriving works perfectly well! :) Thanks for pointing this out.