simple_bitfield/lib.rs
1#![no_std]
2
3
4//! Crate to create simple C-style bitfields with the same memory structure
5//! as the underlying data type (typically integer). Can be used in `#![no_std]` environments.
6//!
7//! Properties of such bitfields:
8//! * they have the exact same memory layout and size as the underlying primitive type;
9//! * their size is checked at compile-time, so it's not possible to add a field that won't fit into the underlying type;
10//! * their fields can be accessed by name (`my_bitfield.some_field`) which aids readability;
11//! * each field has the same set of functions (`get`, `set`, `set_checked` and more);
12//! * each field has its own distinct type;
13//! * it's possible to skip (and not name) any number of bits
14//!
15//! The [bitfield] macro was inspired by [https://guiand.xyz/blog-posts/bitfields.html](https://guiand.xyz/blog-posts/bitfields.html).
16//!
17//! ## Example:
18//! ```
19//! use simple_bitfield::{bitfield, Field};
20//!
21//! bitfield! {
22//! // Bitfield with underlying type `u32`
23//! struct MyBitfield<u32> {
24//! field1: 3, // First field (least significant) of size 3 bits
25//! field2: 9,
26//! _: 6, // Fields named `_` are skipped (offsets are preserved)
27//! field3: 1 // Last bit (closest to the highest bit of `u32`)
28//! }
29//!
30//! // Multiple bitfields can be defined within one macro invocation
31//! struct AnotherBitfield<u8> {
32//! _: 7,
33//! highest_bit: 1
34//! }
35//! }
36//!
37//! fn main() {
38//! // Create bitfield object
39//! let mut a_bitfield = MyBitfield::new(12345);
40//!
41//! // Get the field's value (of underlying type)
42//! let field3: u32 = a_bitfield.field3.get();
43//!
44//! println!(
45//! "{:#b} => {:#b}, {:#b}, {:#b}",
46//! u32::from(a_bitfield), // Convert bitfield to underlying type
47//! field3,
48//! a_bitfield.field2.get(),
49//! a_bitfield.field1.get()
50//! );
51//!
52//! // Update just that field
53//! a_bitfield.field1.set(0);
54//!
55//! println!("{:#b}", u32::from(a_bitfield));
56//!
57//! println!("{}\n{:?}", a_bitfield, a_bitfield);
58//! // MyBitfield(12344)
59//! // MyBitfield(field1: 0, field2: 7, field3: 0)
60//!
61//! // The type can be inferred, of course
62//! let another_one: AnotherBitfield::AnotherBitfield = AnotherBitfield::new(184);
63//!
64//! // Fields cannot be moved or copied!
65//! // let another_one_highest = another_one.highest_bit;
66//!
67//! // Each field has its own type
68//! let another_one_highest: &AnotherBitfield::highest_bit = &another_one.highest_bit;
69//! println!("{:#b}", another_one_highest.get())
70//! }
71//! ```
72//!
73//! ## These bitfields are _simple_
74//! One bitfield is essentially one integer that has fields whose `get` methods
75//! return data of the same integer type. Bitfields that contain more than one integer
76//! or any type that doesn't satisfy the [Bitfield] and [Field] traits are not yet possible.
77//!
78//! Structs that contain multiple bitfields _are_ possible, and their size can be preserved
79//! via the `#[repr(packed)]` attribute. Care must be taken of the field access
80//! because code like `a_bitfield.field.get()` borrows `a_bitfield`, which can result in
81//! unaligned access if the struct with the bitfields is `#[repr(packed)]`.
82//!
83//! The [TestBitfield] module is only present in the documentation and shows how a bitfield is structured internally.
84
85use core::{
86 ops::{ Shl, Shr, BitAnd, BitOrAssign, BitXorAssign },
87 fmt::{ Debug, Display }
88};
89
90#[doc(hidden)]
91pub use static_assertions::const_assert;
92
93pub trait Bitfield {
94 //! The trait that's implemented for all bitfields.
95 //! Used mainly to access the bitfield's underlying type, [Self::BaseType].
96
97 /// The bitfield's underlying type.
98 type BaseType: Copy + Debug + Display;
99
100 /// The maximum number of bits that the bitfield can hold.
101 /// Used for compile-time checking that no newly added field requires a [Self::BaseType] wider than this.
102 const MAX_BITS: u8 = 8 * core::mem::size_of::<Self::BaseType>() as u8;
103}
104
105pub trait Field<B: Bitfield>
106 where B::BaseType:
107 Shl<u8, Output=B::BaseType> +
108 Shr<u8, Output=B::BaseType> +
109 BitAnd<Output=B::BaseType> +
110 BitOrAssign + BitXorAssign + PartialEq
111{
112 //! The trait that's implemented for all fields of all bitfields.
113 //! Allows the nice `my_bitfield.some_field.get()` syntax.
114
115 /// The field's size _in bits_. Specified by the user.
116 const SIZE: u8;
117
118 /// The field's offset from the underlying value's least significant bit,
119 /// _in bits_.
120 ///
121 /// The first field's offset is 0, the second field's offset is
122 /// `previous_field::SIZE` and so on. Computed automatically.
123 const OFFSET: u8;
124
125 /// The field's mask that can be used to extract the last [Self::SIZE] bits from any `B::BaseType`.
126 /// Computed automatically.
127 ///
128 /// Example usage:
129 /// ```
130 /// use simple_bitfield::{ bitfield, Field };
131 ///
132 /// bitfield! {
133 /// struct TestBitfield<u32> {
134 /// field1: 4
135 /// }
136 /// }
137 ///
138 /// fn main() {
139 /// let the_bf = TestBitfield::new(123);
140 ///
141 /// assert_eq!(TestBitfield::field1::MASK, 0b1111);
142 /// assert_eq!(0b1011_1010 & TestBitfield::field1::MASK, 0b1010);
143 /// }
144 /// ```
145 const MASK: B::BaseType;
146
147 /// Returns `true` if the field is not equal to zero.
148 fn is_set(&self) -> bool;
149
150 /// `true` if the field is within the bitfield's bounds. Used for compile-time checking.
151 const VALID: bool = Self::SIZE + Self::OFFSET <= B::MAX_BITS;
152
153 /// Returns the size of a field _at runtime_, while [Self::SIZE] is used on the _type_ of the field at compile-time.
154 fn size(&self) -> u8 { Self::SIZE }
155
156 /// Returns the offset of a field _at runtime_, while [Self::OFFSET] is used on the _type_ of the field at compile-time.
157 fn offset(&self) -> u8 { Self::OFFSET }
158
159 /// Returns the mask of a field _at runtime_, while [Self::MASK] is used on the _type_ of the field at compile-time.
160 fn mask(&self) -> B::BaseType { Self::MASK }
161
162 /// Returns the current value of the field.
163 ///
164 /// Example:
165 /// ```
166 /// use simple_bitfield::{ bitfield, Field };
167 ///
168 /// bitfield! {
169 /// struct TestBitfield<u32> {
170 /// field1: 4
171 /// }
172 /// }
173 ///
174 /// fn main() {
175 /// let my_bitfield = TestBitfield::new(0b10_1111);
176 ///
177 /// assert_eq!(my_bitfield.field1.get(), 0b1111);
178 /// }
179 /// ```
180 fn get(&self) -> B::BaseType {
181 let data_ptr: *const B::BaseType = self as *const Self as *const B::BaseType;
182
183 (unsafe { *data_ptr } >> Self::OFFSET) & Self::MASK
184 }
185
186 /// Sets the value of a field. If the value is wider than the field,
187 /// the value's lowest [Self::SIZE] bits will be used.
188 ///
189 /// Example:
190 /// ```
191 /// use simple_bitfield::{ bitfield, Field };
192 ///
193 /// bitfield! {
194 /// struct TestBitfield<u32> {
195 /// field1: 4
196 /// }
197 /// }
198 ///
199 /// fn main() {
200 /// let mut my_bitfield = TestBitfield::new(0b10_1111); // Must be mutable
201 ///
202 /// my_bitfield.field1.set(0b1_1100);
203 /// assert_eq!(my_bitfield.field1.get(), 0b1100);
204 /// }
205 /// ```
206 fn set(&mut self, new_value: B::BaseType) {
207 let data_ptr: *mut B::BaseType = self as *const Self as *mut B::BaseType;
208
209 let old_value: B::BaseType = self.get() << Self::OFFSET;
210
211 unsafe {
212 *data_ptr ^= old_value;
213 *data_ptr |= (new_value & Self::MASK) << Self::OFFSET
214 }
215 }
216
217 /// Sets the value of a field. If the value is wider than the field,
218 /// returns an `Err` result containing the value's lowest [Self::SIZE] bits
219 /// and doesn't modify the field.
220 ///
221 /// Example:
222 /// ```
223 /// use simple_bitfield::{ bitfield, Field };
224 ///
225 /// bitfield! {
226 /// struct TestBitfield<u32> {
227 /// field1: 4
228 /// }
229 /// }
230 ///
231 /// fn main() {
232 /// let mut my_bitfield = TestBitfield::new(0b10_1111); // Must be mutable
233 ///
234 /// assert_eq!(
235 /// my_bitfield.field1.set_checked(0b1_1100),
236 /// Err(0b1100)
237 /// );
238 ///
239 /// // The field's value didn't change
240 /// assert_eq!(my_bitfield.field1.get(), 0b1111);
241 /// }
242 /// ```
243 fn set_checked(&mut self, new_value: B::BaseType) -> Result<(), B::BaseType> {
244 let masked = new_value & Self::MASK;
245
246 if masked != new_value {
247 Err(masked)
248 } else {
249 self.set(masked);
250
251 Ok(())
252 }
253 }
254}
255
256/// Generates the format args for all fields of a bitfield.
257///
258/// The result looks like this: `field_low: value, field: value, field_high: value`. Used internally.
259#[macro_export]
260#[doc(hidden)]
261macro_rules! gen_format_debug {
262 ($self:ident) => { format_args!("{}", "") };
263 ($self:ident | $first_field:ident) => {
264 format_args!(
265 "{}: {:?}",
266 // Can't just refer to `self` because it's a keyword?!
267 // So have to pass it from call site
268 stringify!($first_field), $self.$first_field.get()
269 )
270 };
271 ($self:ident | $first_field:ident | $second_field:ident $(| $other_field:ident)*) => {
272 format_args!(
273 "{}: {:?}, {}",
274 stringify!($first_field), $self.$first_field.get(),
275 $crate::gen_format_debug!($self | $second_field $(| $other_field)*)
276 )
277 };
278}
279
280
281/// Creates bitfield types.
282///
283/// Adapted from [https://guiand.xyz/blog-posts/bitfields.html](https://guiand.xyz/blog-posts/bitfields.html)
284///
285/// Example:
286/// ```
287/// use core::mem::{size_of, size_of_val};
288/// use simple_bitfield::{
289/// bitfield, Field // For field access
290/// };
291///
292/// bitfield!{
293/// struct BitfieldName<u8> {
294/// first_two_bits: 2,
295/// three_more_bits: 3
296/// }
297///
298/// struct AnotherBitfield<u32> {
299/// _: 31, // Skip first 31 bits
300/// last_bit: 1
301/// }
302/// }
303///
304/// # pub fn main() {
305/// let value: u8 = 0b111_011_10;
306/// let my_bitfield: BitfieldName::BitfieldName = BitfieldName::new(value);
307/// let another_bitfield = AnotherBitfield::new(value.into());
308///
309/// assert_eq!(
310/// size_of_val(&my_bitfield),
311/// size_of::<u8>()
312/// );
313/// assert_eq!(
314/// size_of_val(&my_bitfield),
315/// size_of::<u8>()
316/// );
317///
318/// assert_eq!(my_bitfield.first_two_bits.size(), 2);
319/// assert_eq!(my_bitfield.three_more_bits.size(), 3);
320///
321/// assert_eq!(my_bitfield.first_two_bits.get(), value & 0b11);
322/// assert_eq!(
323/// my_bitfield.three_more_bits.get(),
324/// (value >> my_bitfield.first_two_bits.size()) & 0b111
325/// );
326///
327/// assert_eq!(another_bitfield.last_bit.get(), 0);
328/// # }
329/// ```
330///
331/// The bitfield `BitfieldName` is actually a module. The type that holds the data is `BitfieldName::BitfieldName`,
332/// which is unique for each bitfield. Each field is a zero-size struct that cannot be instantiated separately from the bitfield.
333/// The memory representation of the bitfield is exactly the same as that of the underlying type.
334#[macro_export]
335macro_rules! bitfield {
336 ($($(#[$attr:meta])* $visibility:vis struct $bitfield_name:ident < $big_type:ty > { $($field:tt : $size:literal),* })*) => {$(
337 // Construct the whole module
338 #[allow(non_snake_case)]
339 #[allow(dead_code)]
340 $visibility mod $bitfield_name {
341 //! This module represents a single bitfield.
342
343 /// Struct with the actual data.
344 #[repr(transparent)]
345 #[derive(Copy, Clone)]
346 $(#[$attr])*
347 pub struct $bitfield_name($big_type);
348 impl $crate::Bitfield for $bitfield_name {
349 type BaseType = $big_type;
350 }
351
352 impl From<$big_type> for $bitfield_name
353 {
354 fn from(val: $big_type) -> Self {
355 Self(val)
356 }
357 }
358
359 impl From<$bitfield_name> for $big_type {
360 fn from(val: $bitfield_name) -> Self {
361 val.0
362 }
363 }
364
365 /// Creates a new bitfield
366 pub const fn new(val: $big_type) -> $bitfield_name {
367 // Can't use `val.into()` because `into` is not `const`.
368 $bitfield_name(val)
369 }
370
371 /* Generate a zero-sized (!!) `struct` for each `$field`
372 * and a zero-sized (!!) `struct Field` whose elements are objects of these structs.
373 */
374 $crate::bitfield!{
375 impl
376 $($field : $size),* end_marker // List of fields to process
377
378 Fields, // Name of the struct that will hold the resulting fields
379 $bitfield_name, // Name of the underlying bitfield struct that holds the actual data
380 0, // Offset of the current bitfield
381 processed // Empty (!) list of processed field names
382 }
383
384 $crate::const_assert!(Fields::VALID);
385
386 /// Implement this so that accesses to fields of `$bitfield_name`
387 /// actually access the zero-sized struct `Fields`
388 impl core::ops::Deref for $bitfield_name {
389 type Target = Fields;
390
391 fn deref(&self) -> &Self::Target {
392 // We go through Deref here because Fields MUST NOT be moveable.
393 unsafe { &*(self as *const Self as *const Fields) }
394 }
395 }
396
397 impl core::ops::DerefMut for $bitfield_name {
398 fn deref_mut(&mut self) -> &mut Self::Target {
399 // We go through Deref here because Fields MUST NOT be moveable.
400 unsafe { &mut *(self as *mut Self as *mut Fields) }
401 }
402 }
403 }
404 )*};
405
406 (impl end_marker $struct_name:ident, $bitfield_type:ty, $curr_offset:expr, processed $(| $field_processed:ident)*) => {
407 /// Struct whose fields' names' are those of the bitfield's fields.
408 ///
409 /// When accessing a field of a bitfield like `some_bitfield.a_field`, a reference to `some_bitfield` is created
410 /// and `unsafe`ly treated as a reference to _this struct_.
411 /// However, this should actually be OK because this struct can't be constructed since none of its fields can be constructed.
412 ///
413 /// This struct's size is zero:
414 /// ```
415 /// use simple_bitfield::bitfield;
416 ///
417 /// bitfield!{
418 /// struct BitfieldName<u8> {
419 /// first_two_bits: 2,
420 /// three_more_bits: 3
421 /// }
422 /// }
423 ///
424 /// # fn main() {
425 /// assert_eq!(core::mem::size_of::<BitfieldName::Fields>(), 0);
426 /// # }
427 /// ```
428 #[repr(C)]
429 pub struct $struct_name {
430 $(pub $field_processed: $field_processed),*
431 }
432
433 impl $struct_name {
434 /// `true` if ALL fields are valid, `false` otherwise
435 const VALID: bool = $(<$field_processed as $crate::Field<$bitfield_type>>::VALID &)* true;
436 }
437
438 impl core::fmt::Display for $bitfield_type {
439 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::result::Result<(), core::fmt::Error> {
440 write!(f, "{}({})", stringify!($bitfield_type), self.0)
441 }
442 }
443
444 impl core::fmt::Debug for $bitfield_type {
445 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::result::Result<(), core::fmt::Error> {
446 use $crate::Field; // because `gen_format` accesses fields
447
448 write!(f, "{}", format_args!(
449 "{}({})", stringify!($bitfield_type),
450 $crate::gen_format_debug!(self $(| $field_processed)*)
451 ))
452 }
453 }
454 };
455
456 (impl _ : $size:literal $(, $other_field:tt : $other_size:literal)* end_marker $struct_name:ident, $bitfield_type:ty, $curr_offset:expr, processed $(| $field_processed:ident)*) => {
457 // Skip field that's equal to `_`
458 $crate::bitfield!{
459 impl
460 $($other_field : $other_size),* end_marker
461 $struct_name, $bitfield_type,
462 $curr_offset + $size,
463 processed $(| $field_processed)*
464 }
465 };
466
467 (impl $field:ident : $size:literal $(, $other_field:tt : $other_size:literal)* end_marker $struct_name:ident, $bitfield_type:ty, $curr_offset:expr, processed $(| $field_processed:ident)*) => {
468 // Create one field
469
470 /// The bitfield's field. Can't be constructed outside of a bitfield.
471 ///
472 /// It's actually a struct of size ZERO and implements `Field<UnderlyingBitfieldType>`, so that its value can be obtained with `get()` and changed with `set()`.
473 ///
474 /// This struct cannot be constructed explicitly:
475 /// ```compile_fail
476 /// use simple_bitfield::bitfield;
477 ///
478 /// bitfield!{
479 /// struct BitfieldName<u8> {
480 /// first_two_bits: 2,
481 /// three_more_bits: 3
482 /// }
483 /// }
484 ///
485 /// # fn main() {
486 /// let tried_to_construct_field = BitfieldName::first_two_bits(());
487 /// # }
488 /// ```
489 #[allow(non_camel_case_types)]
490 pub struct $field(());
491 /*
492 * `struct thing(())` is a "unit-valued tuple struct",
493 * basically the same as `struct thing(<any type>)`,
494 * which can be constucted like `thing(<value of type>)`,
495 * but the constructor is invisible outside the module.
496 *
497 * https://stackoverflow.com/questions/50162597/what-are-the-differences-between-the-multiple-ways-to-create-zero-sized-structs
498 */
499
500 #[allow(dead_code)]
501 impl $crate::Field<$bitfield_type> for $field {
502 const SIZE: u8 = $size;
503 const OFFSET: u8 = $curr_offset;
504 const MASK: <$bitfield_type as $crate::Bitfield>::BaseType = (1 << Self::SIZE) - 1;
505
506 #[inline]
507 fn is_set(&self) -> bool {
508 self.get() != 0
509 }
510 }
511
512 $crate::const_assert!(<$field as $crate::Field<$bitfield_type>>::VALID);
513
514 // Process the next fields
515 $crate::bitfield!{
516 impl
517 $($other_field : $other_size),* end_marker // Schedule the next fields
518 $struct_name, $bitfield_type, // Pass along
519 $curr_offset + $size, // INCREMENT the current offset!!
520 processed $(| $field_processed)* | $field // Add the field name to processed fields
521 /* The trick with field names being separated by pipes (`|`) like `| $field`
522 * is needed because `$(| $field_processed)*` may be empty, but we apparently need SOME separator,
523 * so the separator must be in front of the field name
524 */
525 }
526 }
527}
528
529
530#[cfg(doc)]
531bitfield! {
532 pub struct TestBitfield<u32> {
533 field_1: 2,
534 _: 3,
535 field_2: 5
536 }
537}
538
539
540// Should be AFTER the macro definition
541#[cfg(test)]
542mod tests;