Skip to content

Commit 223c178

Browse files
committed
rust: add bit function.
It behaves similarly to C's `BIT` macro. It is used to seamlessly convert C code that uses this macro, for example the PL061 driver. Some of this was discussed in Zulip. We couldn't find a simpler solution that offered the same ergonomics. Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
1 parent f29f951 commit 223c178

File tree

2 files changed

+114
-7
lines changed

2 files changed

+114
-7
lines changed

rust/kernel/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ pub mod user_ptr;
9191
pub use build_error::build_error;
9292

9393
pub use crate::error::{to_result, Error, Result};
94-
pub use crate::types::{bits_iter, Mode, Opaque, ScopeGuard};
94+
pub use crate::types::{bit, bits_iter, Mode, Opaque, ScopeGuard};
9595

9696
use core::marker::PhantomData;
9797

rust/kernel/types.rs

Lines changed: 113 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -302,27 +302,134 @@ impl<T> Opaque<T> {
302302
}
303303
}
304304

305+
/// A bitmask.
306+
///
307+
/// It has a restriction that all bits must be the same, except one. For example, `0b1110111` and
308+
/// `0b1000` are acceptable masks.
309+
#[derive(Clone, Copy)]
310+
pub struct Bit<T> {
311+
index: T,
312+
inverted: bool,
313+
}
314+
315+
/// Creates a bit mask with a single bit set.
316+
///
317+
/// # Examples
318+
///
319+
/// ```
320+
/// # use kernel::prelude::*;
321+
/// # use kernel::bit;
322+
/// let mut x = 0xfeu32;
323+
///
324+
/// assert_eq!(x & bit(0), 0);
325+
/// assert_eq!(x & bit(1), 2);
326+
/// assert_eq!(x & bit(2), 4);
327+
/// assert_eq!(x & bit(3), 8);
328+
///
329+
/// x |= bit(0);
330+
/// assert_eq!(x, 0xff);
331+
///
332+
/// x &= !bit(1);
333+
/// assert_eq!(x, 0xfd);
334+
///
335+
/// x &= !bit(7);
336+
/// assert_eq!(x, 0x7d);
337+
///
338+
/// let y: u64 = bit(34).into();
339+
/// assert_eq!(y, 0x400000000);
340+
///
341+
/// assert_eq!(y | bit(35), 0xc00000000);
342+
/// ```
343+
pub fn bit<T: Copy>(index: T) -> Bit<T> {
344+
Bit {
345+
index,
346+
inverted: false,
347+
}
348+
}
349+
350+
impl<T: Copy> ops::Not for Bit<T> {
351+
type Output = Self;
352+
fn not(self) -> Self {
353+
Self {
354+
index: self.index,
355+
inverted: !self.inverted,
356+
}
357+
}
358+
}
359+
305360
/// Implemented by integer types that allow counting the number of trailing zeroes.
306361
pub trait TrailingZeros {
307362
/// Returns the number of trailing zeroes in the binary representation of `self`.
308363
fn trailing_zeros(&self) -> u32;
309364
}
310365

311-
macro_rules! impl_trailing_zeros {
366+
macro_rules! define_unsigned_number_traits {
312367
($type_name:ty) => {
313368
impl TrailingZeros for $type_name {
314369
fn trailing_zeros(&self) -> u32 {
315370
<$type_name>::trailing_zeros(*self)
316371
}
317372
}
373+
374+
impl<T: Copy> core::convert::From<Bit<T>> for $type_name
375+
where
376+
Self: ops::Shl<T, Output = Self> + core::convert::From<u8> + ops::Not<Output = Self>,
377+
{
378+
fn from(v: Bit<T>) -> Self {
379+
let c = Self::from(1u8) << v.index;
380+
if v.inverted {
381+
!c
382+
} else {
383+
c
384+
}
385+
}
386+
}
387+
388+
impl<T: Copy> ops::BitAnd<Bit<T>> for $type_name
389+
where
390+
Self: ops::Shl<T, Output = Self> + core::convert::From<u8>,
391+
{
392+
type Output = Self;
393+
fn bitand(self, rhs: Bit<T>) -> Self::Output {
394+
self & Self::from(rhs)
395+
}
396+
}
397+
398+
impl<T: Copy> ops::BitOr<Bit<T>> for $type_name
399+
where
400+
Self: ops::Shl<T, Output = Self> + core::convert::From<u8>,
401+
{
402+
type Output = Self;
403+
fn bitor(self, rhs: Bit<T>) -> Self::Output {
404+
self | Self::from(rhs)
405+
}
406+
}
407+
408+
impl<T: Copy> ops::BitAndAssign<Bit<T>> for $type_name
409+
where
410+
Self: ops::Shl<T, Output = Self> + core::convert::From<u8>,
411+
{
412+
fn bitand_assign(&mut self, rhs: Bit<T>) {
413+
*self &= Self::from(rhs)
414+
}
415+
}
416+
417+
impl<T: Copy> ops::BitOrAssign<Bit<T>> for $type_name
418+
where
419+
Self: ops::Shl<T, Output = Self> + core::convert::From<u8>,
420+
{
421+
fn bitor_assign(&mut self, rhs: Bit<T>) {
422+
*self |= Self::from(rhs)
423+
}
424+
}
318425
};
319426
}
320427

321-
impl_trailing_zeros!(u8);
322-
impl_trailing_zeros!(u16);
323-
impl_trailing_zeros!(u32);
324-
impl_trailing_zeros!(u64);
325-
impl_trailing_zeros!(usize);
428+
define_unsigned_number_traits!(u8);
429+
define_unsigned_number_traits!(u16);
430+
define_unsigned_number_traits!(u32);
431+
define_unsigned_number_traits!(u64);
432+
define_unsigned_number_traits!(usize);
326433

327434
/// Returns an iterator over the set bits of `value`.
328435
///

0 commit comments

Comments
 (0)