1#![cfg_attr(not(test), no_std)]
6
7#[cfg(test)]
9extern crate self as bitrs;
10
11use core::fmt;
12
13#[doc(hidden)]
18pub use ::zerocopy as __zerocopy;
19
20pub use bitrs_macro::layout;
24
25pub use bitrs_macro::bitfield_repr;
41
42#[doc(hidden)]
51#[macro_export]
52macro_rules! get_bit {
53 ($int:expr, $low_bit:literal) => {
54 (($int) & (1 << $low_bit)) != 0
55 };
56}
57
58#[doc(hidden)]
59#[macro_export]
60macro_rules! set_bit {
61 ($int:expr, $low_bit:literal, $value:ident) => {
62 if $value {
63 $int |= (1 << $low_bit);
64 } else {
65 $int &= !(1 << $low_bit);
66 }
67 };
68}
69
70#[doc(hidden)]
71#[macro_export]
72macro_rules! shifted_mask {
73 ($base:ty, $high_bit:literal, $low_bit:literal) => {{
74 const WIDTH: usize = $high_bit - $low_bit + 1;
75 if (<$base>::BITS as usize) == WIDTH { <$base>::MAX } else { (1 << WIDTH) - 1 }
76 }};
77}
78
79#[doc(hidden)]
80#[macro_export]
81macro_rules! get_field {
82 ($base:ty, $clamped:ty, $high_bit:literal, $low_bit:literal, $shifted:literal, $int:expr) => {{
83 const SHIFTED_MASK: $base = $crate::shifted_mask!($base, $high_bit, $low_bit);
84 let value = if $shifted {
85 ($int >> $low_bit) & SHIFTED_MASK
86 } else {
87 const UNSHIFTED_MASK: $base = SHIFTED_MASK << $low_bit;
88 $int & UNSHIFTED_MASK
89 };
90 value as $clamped
91 }};
92}
93
94#[doc(hidden)]
95#[macro_export]
96macro_rules! set_field {
97 ($base:ty, $high_bit:literal, $low_bit:literal, $shifted:literal, $int:expr, $value:ident) => {
98 const SHIFTED_MASK: $base = $crate::shifted_mask!($base, $high_bit, $low_bit);
99 const UNSHIFTED_MASK: $base = SHIFTED_MASK << $low_bit;
100
101 $int &= !UNSHIFTED_MASK;
102 if $shifted {
103 debug_assert!(($value & !SHIFTED_MASK) == 0);
104 $int |= ($value & SHIFTED_MASK) << $low_bit;
105 } else {
106 debug_assert!(($value & !UNSHIFTED_MASK) == 0);
107 $int |= $value & UNSHIFTED_MASK;
108 }
109 };
110}
111
112pub trait Unsigned: fmt::Debug + private::Sealed {}
115impl Unsigned for u8 {}
116impl Unsigned for u16 {}
117impl Unsigned for u32 {}
118impl Unsigned for u64 {}
119impl Unsigned for u128 {}
120
121mod private {
123 pub trait Sealed {}
124 impl Sealed for u8 {}
125 impl Sealed for u16 {}
126 impl Sealed for u32 {}
127 impl Sealed for u64 {}
128 impl Sealed for u128 {}
129}
130
131#[derive(Debug)]
135pub struct InvalidBits<Base: Unsigned>(pub Base);
136
137#[derive(Debug)]
142pub struct FieldMetadata<Base: Unsigned> {
143 pub name: &'static str,
145 pub high_bit: u32,
147 pub low_bit: u32,
149 pub default: Base,
151}
152
153#[cfg(test)]
154mod tests {
155 use super::{FieldMetadata, bitfield_repr, layout};
156
157 layout!({
158 struct EmptyU8(u8);
159 {}
160 });
161
162 layout!({
163 struct OneFieldU16(u16);
164 {
165 let a @ 15..0;
166 }
167 });
168
169 layout!({
170 struct TwoFieldsU32(u32);
171 {
172 let a @ 31..16;
173 let b @ 15..0;
174 }
175 });
176
177 layout!({
178 struct ThreeFieldsU64(u64);
179 {
180 let a @ 63..32;
181 let b @ 31..16;
182 let c @ 15..0;
183 }
184 });
185
186 layout!({
187 struct FourFieldsU128(u128);
188 {
189 let a @ 127..96;
190 let b @ 95..64;
191 let c @ 63..32;
192 let d @ 31..0;
193 }
194 });
195
196 #[test]
197 fn size_and_alignment() {
198 assert_eq!(size_of::<EmptyU8>(), size_of::<u8>());
199 assert_eq!(align_of::<EmptyU8>(), align_of::<u8>());
200
201 assert_eq!(size_of::<OneFieldU16>(), size_of::<u16>());
202 assert_eq!(align_of::<OneFieldU16>(), align_of::<u16>());
203
204 assert_eq!(size_of::<TwoFieldsU32>(), size_of::<u32>());
205 assert_eq!(align_of::<TwoFieldsU32>(), align_of::<u32>());
206
207 assert_eq!(size_of::<ThreeFieldsU64>(), size_of::<u64>());
208 assert_eq!(align_of::<ThreeFieldsU64>(), align_of::<u64>());
209
210 assert_eq!(size_of::<FourFieldsU128>(), size_of::<u128>());
211 assert_eq!(align_of::<FourFieldsU128>(), align_of::<u128>());
212 }
213
214 #[bitfield_repr(u8)]
215 pub enum CustomFieldRepr {
216 Option1 = 0xa,
217 Option2 = 0xf,
218 }
219
220 layout!({
221 pub struct Example(u64);
222 {
223 let u32_repr @ 44..27;
224 let custom @ 26..23: CustomFieldRepr;
225 let custom_with_default @ 22..19: CustomFieldRepr = CustomFieldRepr::Option1;
226 let __ @ 18..11 = 0xef;
227 let with_default @ 10..9 = 0b11;
228 let bit @ 8;
229 let u8_repr @ 7..4;
230 let __ @ 3..2 = 1;
231 let __ @ 1..0;
232 }
233 });
234
235 #[test]
236 fn constants() {
237 assert_eq!(Example::RSVD1_MASK, (0xef << 11) | (0b01 << 2));
238 assert_eq!(Example::RSVD0_MASK, (0x10 << 11) | (0b10 << 2));
239
240 assert_eq!(
241 Example::DEFAULT,
242 (0xef << 11) | (0b01 << 2) | ((CustomFieldRepr::Option1 as u64) << 19) | (0b11 << 9)
243 );
244
245 assert_eq!(Example::U32_REPR_MASK, 0x1fff_f800_0000);
246 assert_eq!(Example::U32_REPR_SHIFT, 27usize,);
247
248 assert_eq!(Example::CUSTOM_MASK, 0x780_0000);
249 assert_eq!(Example::CUSTOM_SHIFT, 23usize);
250
251 assert_eq!(Example::CUSTOM_WITH_DEFAULT_MASK, 0x78_0000);
252 assert_eq!(Example::CUSTOM_WITH_DEFAULT_SHIFT, 19usize);
253
254 assert_eq!(Example::RSVD_18_11, 0xef << 11);
255
256 assert_eq!(Example::WITH_DEFAULT_MASK, 0x600);
257 assert_eq!(Example::WITH_DEFAULT_SHIFT, 9usize);
258
259 assert_eq!(Example::BIT_SHIFT, 8usize);
260
261 assert_eq!(Example::U8_REPR_MASK, 0xf0);
262 assert_eq!(Example::U8_REPR_SHIFT, 4usize);
263
264 assert_eq!(Example::RSVD_3_2, 1 << 2);
265 }
266
267 #[test]
269 fn new() {
270 assert_eq!(Example::new().bits(), Example::RSVD1_MASK);
271 }
272
273 #[test]
276 fn default() {
277 assert_eq!(Example::default().bits(), Example::DEFAULT);
278 }
279
280 #[test]
281 fn from() {
282 assert_eq!(Example::from(Example::RSVD1_MASK).bits(), Example::RSVD1_MASK);
283 assert_eq!(Example::from(1 | Example::RSVD1_MASK).bits(), 1 | Example::RSVD1_MASK);
284 assert_eq!(
285 Example::from(0xffff_0000_0000_0000 | Example::RSVD1_MASK).bits(),
286 0xffff_0000_0000_0000 | Example::RSVD1_MASK
287 );
288 }
289
290 #[test]
291 fn from_then_get() {
292 let example = Example::from(
293 0xabcd << 27
294 | (CustomFieldRepr::Option1 as u64) << 23
295 | (CustomFieldRepr::Option2 as u64) << 19
296 | 0b10 << 9
297 | 1 << 8
298 | 0xc << 4
299 | Example::RSVD1_MASK,
300 );
301 assert_eq!(example.u32_repr(), 0xabcd);
302 assert_eq!(example.custom(), CustomFieldRepr::Option1);
303 assert_eq!(example.custom_with_default(), CustomFieldRepr::Option2);
304 assert_eq!(example.with_default(), 0b10);
305 assert!(example.bit());
306 assert_eq!(example.u8_repr(), 0xc);
307 }
308
309 #[test]
310 fn set_then_get() {
311 let example = *Example::new()
312 .set_u32_repr(0xabcd)
313 .set_custom(CustomFieldRepr::Option1)
314 .set_custom_with_default(CustomFieldRepr::Option2)
315 .set_with_default(0b10)
316 .set_bit(true)
317 .set_u8_repr(0xc);
318 assert_eq!(example.u32_repr(), 0xabcd);
319 assert_eq!(example.custom(), CustomFieldRepr::Option1);
320 assert_eq!(example.custom_with_default(), CustomFieldRepr::Option2);
321 assert_eq!(example.with_default(), 0b10);
322 assert!(example.bit());
323 assert_eq!(example.u8_repr(), 0xc);
324 }
325
326 #[test]
327 fn iter() {
328 type Metadata = FieldMetadata<u64>;
329
330 const EXPECTED: [(u64, Metadata); 6] = [
331 (0xabcd, Metadata { name: "u32_repr", high_bit: 44, low_bit: 27, default: 0 }),
332 (0xa, Metadata { name: "custom", high_bit: 26, low_bit: 23, default: 0 }),
333 (
334 0xf,
335 Metadata { name: "custom_with_default", high_bit: 22, low_bit: 19, default: 0xa },
336 ),
337 (0b10, Metadata { name: "with_default", high_bit: 10, low_bit: 9, default: 0b11 }),
338 (0b1, Metadata { name: "bit", high_bit: 8, low_bit: 8, default: 0 }),
339 (0xc, Metadata { name: "u8_repr", high_bit: 7, low_bit: 4, default: 0 }),
340 ];
341
342 let example = *Example::new()
343 .set_u32_repr(0xabcd)
344 .set_custom(CustomFieldRepr::Option1)
345 .set_custom_with_default(CustomFieldRepr::Option2)
346 .set_with_default(0b10)
347 .set_bit(true)
348 .set_u8_repr(0xc);
349
350 let actual: Vec<(&'static Metadata, u64)> = example.into_iter().collect();
351 let rev_actual: Vec<(&'static Metadata, u64)> = example.into_iter().rev().collect();
352
353 assert_eq!(actual.len(), EXPECTED.len());
354 assert_eq!(rev_actual.len(), EXPECTED.len());
355 for i in 0..EXPECTED.len() {
356 let (expected_val, expected_metadata) = &EXPECTED[i];
357 for (label, (actual_metadata, actual_val)) in
358 [("fwd", &actual[i]), ("rev", &rev_actual[EXPECTED.len() - 1 - i])]
359 {
360 assert_eq!(actual_val, expected_val, "{label}:{i}");
361 assert_eq!(actual_metadata.name, expected_metadata.name, "{label}:{i}");
362 assert_eq!(actual_metadata.high_bit, expected_metadata.high_bit, "{label}:{i}");
363 assert_eq!(actual_metadata.low_bit, expected_metadata.low_bit, "{label}:{i}");
364 assert_eq!(actual_metadata.default, expected_metadata.default, "{label}:{i}");
365 }
366 }
367 }
368
369 layout!({
370 struct Unshifted(u32);
371 {
372 let field @ 19..16;
373 #[unshifted]
374 let unshifted_field @ 15..12;
375 let __ @ 11..9;
376 #[unshifted]
377 let unshifted_bit @ 8;
378 let normal_bit @ 7;
379 let __ @ 6..0;
380 }
381 });
382
383 #[test]
384 fn unshifted_multi_bit_getter() {
385 let val = Unshifted::from(0x5 << 12);
386 assert_eq!(val.unshifted_field(), 0x5000);
387 }
388
389 #[test]
390 fn unshifted_multi_bit_setter() {
391 let mut val = Unshifted::new();
392 val.set_unshifted_field(0xa000);
393 assert_eq!(val.unshifted_field(), 0xa000);
394 assert_eq!(val.bits() & (0xf << 12), 0xa000);
395 }
396
397 #[test]
398 fn unshifted_single_bit_getter() {
399 let val = Unshifted::from(1 << 8);
400 assert_eq!(val.unshifted_bit(), 1 << 8);
401
402 let val = Unshifted::from(0);
403 assert_eq!(val.unshifted_bit(), 0);
404 }
405
406 #[test]
407 fn unshifted_single_bit_setter() {
408 let mut val = Unshifted::new();
409 val.set_unshifted_bit(1 << 8);
410 assert_eq!(val.unshifted_bit(), 1 << 8);
411
412 val.set_unshifted_bit(0);
413 assert_eq!(val.unshifted_bit(), 0);
414 }
415
416 #[test]
417 fn unshifted_round_trip() {
418 let val = *Unshifted::new()
419 .set_unshifted_field(0x7000)
420 .set_unshifted_bit(1 << 8)
421 .set_field(0xa)
422 .set_normal_bit(true);
423 assert_eq!(val.unshifted_field(), 0x7000);
424 assert_eq!(val.unshifted_bit(), 1 << 8);
425 assert_eq!(val.field(), 0xa);
426 assert!(val.normal_bit());
427 }
428
429 #[test]
430 fn unshifted_ignores_other_bits() {
431 let val = Unshifted::from(0xffff_ffff);
432 assert_eq!(val.unshifted_field(), 0xf000);
433 assert_eq!(val.unshifted_bit(), 1 << 8);
434 }
435}