Skip to content

Commit 38efc40

Browse files
authored
Merge pull request #540 from wedsonaf/bits_iter
rust: add `bits_iter`.
2 parents 7407571 + c70681d commit 38efc40

File tree

2 files changed

+87
-2
lines changed

2 files changed

+87
-2
lines changed

rust/kernel/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub mod user_ptr;
8686
pub use build_error::build_error;
8787

8888
pub use crate::error::{Error, Result};
89-
pub use crate::types::{Mode, Opaque, ScopeGuard};
89+
pub use crate::types::{bits_iter, Mode, Opaque, ScopeGuard};
9090

9191
use core::marker::PhantomData;
9292

rust/kernel/types.rs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
sync::{Ref, RefBorrow},
1010
};
1111
use alloc::boxed::Box;
12-
use core::{cell::UnsafeCell, mem::MaybeUninit, ops::Deref, pin::Pin, ptr::NonNull};
12+
use core::{cell::UnsafeCell, mem::MaybeUninit, ops, ops::Deref, pin::Pin, ptr::NonNull};
1313

1414
/// Permissions.
1515
///
@@ -248,3 +248,88 @@ impl<T> Opaque<T> {
248248
UnsafeCell::raw_get(self.0.as_ptr())
249249
}
250250
}
251+
252+
/// Implemented by integer types that allow counting the number of trailing zeroes.
253+
pub trait TrailingZeros {
254+
/// Returns the number of trailing zeroes in the binary representation of `self`.
255+
fn trailing_zeros(&self) -> u32;
256+
}
257+
258+
macro_rules! impl_trailing_zeros {
259+
($type_name:ty) => {
260+
impl TrailingZeros for $type_name {
261+
fn trailing_zeros(&self) -> u32 {
262+
<$type_name>::trailing_zeros(*self)
263+
}
264+
}
265+
};
266+
}
267+
268+
impl_trailing_zeros!(u8);
269+
impl_trailing_zeros!(u16);
270+
impl_trailing_zeros!(u32);
271+
impl_trailing_zeros!(u64);
272+
impl_trailing_zeros!(usize);
273+
274+
/// Returns an iterator over the set bits of `value`.
275+
///
276+
/// # Examples
277+
///
278+
/// ```
279+
/// # use kernel::prelude::*;
280+
/// use kernel::bits_iter;
281+
///
282+
/// let mut iter = bits_iter(5usize);
283+
/// assert_eq!(iter.next().unwrap(), 0);
284+
/// assert_eq!(iter.next().unwrap(), 2);
285+
/// assert!(iter.next().is_none());
286+
/// ```
287+
///
288+
/// ```
289+
/// # use kernel::prelude::*;
290+
/// use kernel::bits_iter;
291+
///
292+
/// fn print_bits(x: usize) {
293+
/// for bit in bits_iter(x) {
294+
/// println!("{}", bit);
295+
/// }
296+
/// }
297+
/// ```
298+
#[inline]
299+
pub fn bits_iter<T>(value: T) -> impl Iterator<Item = u32>
300+
where
301+
T: core::cmp::PartialEq
302+
+ From<u8>
303+
+ ops::Shl<u32, Output = T>
304+
+ ops::Not<Output = T>
305+
+ ops::BitAndAssign
306+
+ TrailingZeros,
307+
{
308+
struct BitIterator<U> {
309+
value: U,
310+
}
311+
312+
impl<U> Iterator for BitIterator<U>
313+
where
314+
U: core::cmp::PartialEq
315+
+ From<u8>
316+
+ ops::Shl<u32, Output = U>
317+
+ ops::Not<Output = U>
318+
+ ops::BitAndAssign
319+
+ TrailingZeros,
320+
{
321+
type Item = u32;
322+
323+
#[inline]
324+
fn next(&mut self) -> Option<u32> {
325+
if self.value == U::from(0u8) {
326+
return None;
327+
}
328+
let ret = self.value.trailing_zeros();
329+
self.value &= !(U::from(1u8) << ret);
330+
Some(ret)
331+
}
332+
}
333+
334+
BitIterator { value }
335+
}

0 commit comments

Comments
 (0)