Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/kernel/bits.rs
29266 views
1
// SPDX-License-Identifier: GPL-2.0
2
3
//! Bit manipulation macros.
4
//!
5
//! C header: [`include/linux/bits.h`](srctree/include/linux/bits.h)
6
7
use crate::prelude::*;
8
use core::ops::RangeInclusive;
9
use macros::paste;
10
11
macro_rules! impl_bit_fn {
12
(
13
$ty:ty
14
) => {
15
paste! {
16
/// Computes `1 << n` if `n` is in bounds, i.e.: if `n` is smaller than
17
/// the maximum number of bits supported by the type.
18
///
19
/// Returns [`None`] otherwise.
20
#[inline]
21
pub fn [<checked_bit_ $ty>](n: u32) -> Option<$ty> {
22
(1 as $ty).checked_shl(n)
23
}
24
25
/// Computes `1 << n` by performing a compile-time assertion that `n` is
26
/// in bounds.
27
///
28
/// This version is the default and should be used if `n` is known at
29
/// compile time.
30
#[inline]
31
pub const fn [<bit_ $ty>](n: u32) -> $ty {
32
build_assert!(n < <$ty>::BITS);
33
(1 as $ty) << n
34
}
35
}
36
};
37
}
38
39
impl_bit_fn!(u64);
40
impl_bit_fn!(u32);
41
impl_bit_fn!(u16);
42
impl_bit_fn!(u8);
43
44
macro_rules! impl_genmask_fn {
45
(
46
$ty:ty,
47
$(#[$genmask_checked_ex:meta])*,
48
$(#[$genmask_ex:meta])*
49
) => {
50
paste! {
51
/// Creates a contiguous bitmask for the given range by validating
52
/// the range at runtime.
53
///
54
/// Returns [`None`] if the range is invalid, i.e.: if the start is
55
/// greater than the end or if the range is outside of the
56
/// representable range for the type.
57
$(#[$genmask_checked_ex])*
58
#[inline]
59
pub fn [<genmask_checked_ $ty>](range: RangeInclusive<u32>) -> Option<$ty> {
60
let start = *range.start();
61
let end = *range.end();
62
63
if start > end {
64
return None;
65
}
66
67
let high = [<checked_bit_ $ty>](end)?;
68
let low = [<checked_bit_ $ty>](start)?;
69
Some((high | (high - 1)) & !(low - 1))
70
}
71
72
/// Creates a compile-time contiguous bitmask for the given range by
73
/// performing a compile-time assertion that the range is valid.
74
///
75
/// This version is the default and should be used if the range is known
76
/// at compile time.
77
$(#[$genmask_ex])*
78
#[inline]
79
pub const fn [<genmask_ $ty>](range: RangeInclusive<u32>) -> $ty {
80
let start = *range.start();
81
let end = *range.end();
82
83
build_assert!(start <= end);
84
85
let high = [<bit_ $ty>](end);
86
let low = [<bit_ $ty>](start);
87
(high | (high - 1)) & !(low - 1)
88
}
89
}
90
};
91
}
92
93
impl_genmask_fn!(
94
u64,
95
/// # Examples
96
///
97
/// ```
98
/// # #![expect(clippy::reversed_empty_ranges)]
99
/// # use kernel::bits::genmask_checked_u64;
100
/// assert_eq!(genmask_checked_u64(0..=0), Some(0b1));
101
/// assert_eq!(genmask_checked_u64(0..=63), Some(u64::MAX));
102
/// assert_eq!(genmask_checked_u64(21..=39), Some(0x0000_00ff_ffe0_0000));
103
///
104
/// // `80` is out of the supported bit range.
105
/// assert_eq!(genmask_checked_u64(21..=80), None);
106
///
107
/// // Invalid range where the start is bigger than the end.
108
/// assert_eq!(genmask_checked_u64(15..=8), None);
109
/// ```
110
,
111
/// # Examples
112
///
113
/// ```
114
/// # use kernel::bits::genmask_u64;
115
/// assert_eq!(genmask_u64(21..=39), 0x0000_00ff_ffe0_0000);
116
/// assert_eq!(genmask_u64(0..=0), 0b1);
117
/// assert_eq!(genmask_u64(0..=63), u64::MAX);
118
/// ```
119
);
120
121
impl_genmask_fn!(
122
u32,
123
/// # Examples
124
///
125
/// ```
126
/// # #![expect(clippy::reversed_empty_ranges)]
127
/// # use kernel::bits::genmask_checked_u32;
128
/// assert_eq!(genmask_checked_u32(0..=0), Some(0b1));
129
/// assert_eq!(genmask_checked_u32(0..=31), Some(u32::MAX));
130
/// assert_eq!(genmask_checked_u32(21..=31), Some(0xffe0_0000));
131
///
132
/// // `40` is out of the supported bit range.
133
/// assert_eq!(genmask_checked_u32(21..=40), None);
134
///
135
/// // Invalid range where the start is bigger than the end.
136
/// assert_eq!(genmask_checked_u32(15..=8), None);
137
/// ```
138
,
139
/// # Examples
140
///
141
/// ```
142
/// # use kernel::bits::genmask_u32;
143
/// assert_eq!(genmask_u32(21..=31), 0xffe0_0000);
144
/// assert_eq!(genmask_u32(0..=0), 0b1);
145
/// assert_eq!(genmask_u32(0..=31), u32::MAX);
146
/// ```
147
);
148
149
impl_genmask_fn!(
150
u16,
151
/// # Examples
152
///
153
/// ```
154
/// # #![expect(clippy::reversed_empty_ranges)]
155
/// # use kernel::bits::genmask_checked_u16;
156
/// assert_eq!(genmask_checked_u16(0..=0), Some(0b1));
157
/// assert_eq!(genmask_checked_u16(0..=15), Some(u16::MAX));
158
/// assert_eq!(genmask_checked_u16(6..=15), Some(0xffc0));
159
///
160
/// // `20` is out of the supported bit range.
161
/// assert_eq!(genmask_checked_u16(6..=20), None);
162
///
163
/// // Invalid range where the start is bigger than the end.
164
/// assert_eq!(genmask_checked_u16(10..=5), None);
165
/// ```
166
,
167
/// # Examples
168
///
169
/// ```
170
/// # use kernel::bits::genmask_u16;
171
/// assert_eq!(genmask_u16(6..=15), 0xffc0);
172
/// assert_eq!(genmask_u16(0..=0), 0b1);
173
/// assert_eq!(genmask_u16(0..=15), u16::MAX);
174
/// ```
175
);
176
177
impl_genmask_fn!(
178
u8,
179
/// # Examples
180
///
181
/// ```
182
/// # #![expect(clippy::reversed_empty_ranges)]
183
/// # use kernel::bits::genmask_checked_u8;
184
/// assert_eq!(genmask_checked_u8(0..=0), Some(0b1));
185
/// assert_eq!(genmask_checked_u8(0..=7), Some(u8::MAX));
186
/// assert_eq!(genmask_checked_u8(6..=7), Some(0xc0));
187
///
188
/// // `10` is out of the supported bit range.
189
/// assert_eq!(genmask_checked_u8(6..=10), None);
190
///
191
/// // Invalid range where the start is bigger than the end.
192
/// assert_eq!(genmask_checked_u8(5..=2), None);
193
/// ```
194
,
195
/// # Examples
196
///
197
/// ```
198
/// # use kernel::bits::genmask_u8;
199
/// assert_eq!(genmask_u8(6..=7), 0xc0);
200
/// assert_eq!(genmask_u8(0..=0), 0b1);
201
/// assert_eq!(genmask_u8(0..=7), u8::MAX);
202
/// ```
203
);
204
205