1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
//! A bitfields crate.
//!
//! ```
//! use superbitty::{bitfields, BitFieldCompatible};
//!
//! #[derive(BitFieldCompatible, Debug, Clone, Copy, PartialEq, Eq)]
//! pub enum Enum {
//! A,
//! B,
//! C,
//! D,
//! }
//!
//! #[derive(Clone, Copy)]
//! pub struct Rest(pub u8);
//!
//! // SAFETY: We only set this via `Bitfields`, and thus the values are guaranteed
//! // to stay in range.
//! unsafe impl BitFieldCompatible for Rest {
//! const SHIFT: u32 = 0;
//! const BITS_LEN: u32 = 6;
//! fn into_raw(self) -> u128 { self.0 as u128 }
//! unsafe fn from_raw(v: u128) -> Self { Self(v as u8) }
//! }
//!
//! bitfields! {
//! pub struct Bitfields : u8 {
//! pub e: Enum,
//! pub r: Rest,
//! }
//! }
//!
//! fn main() {
//! let mut instance = Bitfields::new(Enum::B, Rest(0b010));
//! assert_eq!(instance.e(), Enum::B);
//! instance.set_r(Rest(0b101));
//! assert_eq!(instance.r().0, 0b101);
//! }
//! ```
#![no_std]
#![forbid(unsafe_op_in_unsafe_fn, rust_2018_idioms)]
#![warn(missing_docs)]
mod raw;
/// A bitfield struct.
///
/// All fields must implement [`BitFieldCompatible`] and their ranges must be non-overlapping
/// and big enough to hold the bitfields.
///
/// ```
/// # use superbitty::{bitfields, BitFieldCompatible};
/// #[derive(BitFieldCompatible, Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
/// enum EnumA { #[default] A, B }
/// #[derive(BitFieldCompatible, Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
/// enum EnumB { #[default] A, B, C }
///
/// bitfields! {
/// #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
/// pub struct Bitfields : u8 {
/// enum_a: EnumA, // from bit 0 to bit 1 (exclusive)
/// pub enum_b: EnumB, // from bit 1 to bit 3
/// }
/// }
///
/// let mut instance = Bitfields::new(EnumA::B, EnumB::A);
/// assert_eq!(instance.enum_a(), EnumA::B);
/// assert_eq!(instance.enum_b(), EnumB::A);
///
/// instance.set_enum_b(EnumB::C);
/// assert_eq!(instance.enum_a(), EnumA::B);
/// assert_eq!(instance.enum_b(), EnumB::C);
/// ```
///
/// The traits derived in the example - [`Debug`], [`Clone`], [`Copy`], [`Default`],
/// [`PartialEq`], [`Eq`], [`PartialOrd`], [`Ord`] and [`Hash`] - are the only you
/// can `#[derive()]`. All others need to be manually implemented.
///
/// By default, the constructor function will be called `new` and will have the same
/// visibility as the struct. You can control that by adding
/// `construct = <visibility> fn <name>();` after the struct, like the following:
/// ```ignore
/// bitfields! {
/// // ...
/// construct = pub fn new();
/// }
/// ```
///
/// The base type is stored as [`Raw`] in a (private) tuple field `0`. You can call its
/// [`raw()`] method to get the raw bitfields data (but you cannot modify it):
/// ```rust
/// # use superbitty::{bitfields, BitFieldCompatible};
/// #[derive(BitFieldCompatible, Clone, Copy)]
/// enum Enum { A, B }
///
/// bitfields! {
/// pub struct Bitfields : u8 {
/// a: Enum,
/// b: Enum,
/// c: Enum,
/// }
/// }
///
/// let mut instance = Bitfields::new(Enum::B, Enum::A, Enum::B);
/// assert_eq!(instance.0.raw(), 0b101); // `Enum::B` is 1, `Enum::A` is 0.
/// ```
///
/// [`BitFieldCompatible`]: crate::BitFieldCompatible
/// [`Debug`]: core::fmt::Debug
/// [`Hash`]: core::hash::Hash
/// [`raw()`]: Raw::raw
pub use superbitty_macros::bitfields;
/// An enum that can be used as a bitfield.
///
/// It must be [`Copy`].
///
/// It must carry no payload and have no negative discriminants.
///
/// ```
/// # use superbitty::BitFieldCompatible;
/// #[derive(BitFieldCompatible, Clone, Copy)]
/// enum BitFieldCompatibleEnum { A, B, C }
/// ```
pub use superbitty_macros::BitFieldCompatible;
pub use crate::raw::Raw;
/// A type that can be used as a bitfield. This is usually [derived] for enums.
/// Structs and unions can implement this explicitly, as the safety requirements cannot be
/// guaranteed for them with `#[derive()]` (at least not easily).
///
/// # Safety
///
/// [`into_raw()`] must provide a value within the range specified by [`SHIFT`] and [`BITS_LEN`].
///
/// [derived]: macro@BitFieldCompatible
/// [`into_raw()`]: BitFieldCompatible::into_raw
/// [`SHIFT`]: BitFieldCompatible::SHIFT
/// [`BITS_LEN`]: BitFieldCompatible::BITS_LEN
pub unsafe trait BitFieldCompatible: Copy {
/// The number we need to left-shift with to reach a valid value from a compressed
/// value which has all trailing zeros trimmed.
///
/// For example, in an enum with the discriminants `0b01000`, `0b10000` and `0b11000`,
/// the value of [`BITS_LEN`] will be 2 and the value of `SHIFT` will be 3, because
/// we need to left-shift three times to go from `0b01`, `0b10` and `0b11` to the
/// corresponding variants.
///
/// [`BITS_LEN`]: BitFieldCompatible::BITS_LEN
const SHIFT: u32;
/// The minimum number of bits required to represent any bit pattern that is valid
/// for this type.
///
/// Note that enums with only one variant may still have this value greater than zero
/// if the discriminant of this variant is not zero, for example if the discriminant is
/// `0b11` it needs two bits to be stored.
const BITS_LEN: u32;
/// This value must not be overridden! Doing so can cause UB.
#[doc(hidden)]
const BITS_MASK: u128 = (1 << Self::BITS_LEN) - 1;
/// Retrieves the raw int representation of a value.
fn into_raw(self) -> u128;
/// Converts a raw int representation to this type.
///
/// # Safety
///
/// `v` must be a valid value for this type.
unsafe fn from_raw(v: u128) -> Self;
}
#[doc(hidden)]
pub mod __helpers {
pub use core::clone::Clone;
pub use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
pub use core::default::Default;
pub use core::fmt::{Debug, Formatter, Result as FmtResult};
pub use core::hash::{Hash, Hasher};
pub use core::hint::unreachable_unchecked;
pub use core::marker::Copy;
pub type PartialCmpResult = Option<Ordering>;
pub const SOME_EQ: PartialCmpResult = Some(Ordering::Equal);
pub const fn assert_bitfield_compatible<T: super::BitFieldCompatible>() {}
}