Currently, constructing an alignment is quite verbose:

`Alignment::new::<8>()`

It's unfortunate because it disincentivizes using it at interface
boundaries. Implement `SizeConstants` for `Alignment` and add some more
size constants (mirroring include/linux/sizes.h) so we can write e.g.
`Alignment::SZ_8` instead.

Link: https://lore.kernel.org/an4xDp29VX8Am0uR@yury
Signed-off-by: Eliot Courtney <[email protected]>
---
 rust/kernel/sizes.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/sizes.rs b/rust/kernel/sizes.rs
index 521b2b38bfe7..825d6b566952 100644
--- a/rust/kernel/sizes.rs
+++ b/rust/kernel/sizes.rs
@@ -13,6 +13,11 @@
 //! these constants as [`u64`] (or [`u32`]) rather than [`usize`], because
 //! device address spaces are sized independently of the CPU pointer width.
 //!
+//! The trait is also implemented for [`Alignment`], providing each size as a
+//! compile-time validated alignment.
+//!
+//! [`Alignment`]: crate::ptr::Alignment
+//!
 //! # Examples
 //!
 //! ```
@@ -35,6 +40,26 @@
 macro_rules! define_sizes {
     ($($type:ty),* $(,)?) => {
         define_sizes!(@internal [$($type),*]
+            /// `0x0000_0001`.
+            SZ_1,
+            /// `0x0000_0002`.
+            SZ_2,
+            /// `0x0000_0004`.
+            SZ_4,
+            /// `0x0000_0008`.
+            SZ_8,
+            /// `0x0000_0010`.
+            SZ_16,
+            /// `0x0000_0020`.
+            SZ_32,
+            /// `0x0000_0040`.
+            SZ_64,
+            /// `0x0000_0080`.
+            SZ_128,
+            /// `0x0000_0100`.
+            SZ_256,
+            /// `0x0000_0200`.
+            SZ_512,
             /// `0x0000_0400`.
             SZ_1K,
             /// `0x0000_0800`.
@@ -85,6 +110,7 @@ macro_rules! define_sizes {
     (@internal [$($type:ty),*] $($names_and_metas:tt)*) => {
         define_sizes!(@consts_and_trait $($names_and_metas)*);
         define_sizes!(@impls [$($type),*] $($names_and_metas)*);
+        define_sizes!(@impl_alignment $($names_and_metas)*);
     };
 
     (@consts_and_trait $($(#[$meta:meta])* $name:ident,)*) => {
@@ -99,13 +125,22 @@ macro_rules! define_sizes {
         /// choose the width that matches their hardware. All `SZ_*` values fit
         /// in a [`u32`], so all implementations are lossless.
         ///
+        /// Also implemented for [`Alignment`], providing each size as a
+        /// compile-time validated alignment.
+        ///
+        /// [`Alignment`]: crate::ptr::Alignment
+        ///
         /// # Examples
         ///
         /// ```
-        /// use kernel::sizes::SizeConstants;
+        /// use kernel::{
+        ///     ptr::Alignment,
+        ///     sizes::SizeConstants, //
+        /// };
         ///
         /// let gpu_heap = 14 * u64::SZ_1M;
         /// let mmio_window = u32::SZ_16M;
+        /// let page_align = Alignment::SZ_4K;
         /// ```
         pub trait SizeConstants {
             $(
@@ -117,6 +152,16 @@ pub trait SizeConstants {
 
     (@impls [] $($(#[$meta:meta])* $name:ident,)*) => {};
 
+    (@impl_alignment $($(#[$meta:meta])* $name:ident,)*) => {
+        impl SizeConstants for crate::ptr::Alignment {
+            $(
+                $(#[$meta])*
+                // A non-power-of-two constant will fail the build here if 
used.
+                const $name: Self = 
crate::ptr::Alignment::new_checked(self::$name).unwrap();
+            )*
+        }
+    };
+
     (@impls [$first:ty $(, $rest:ty)*] $($(#[$meta:meta])* $name:ident,)*) => {
         impl SizeConstants for $first {
             $(

-- 
2.55.0

Reply via email to