bitx 0.2.0

More ergonomic way to deal with bitfield-like struct.
Documentation
#![doc = include_str!("../README.md")]
#![no_std]

/// Defines a structure with precise bit-level and byte-level fields.
///
/// For structs, this macro generates a `#[repr(C)]` struct
/// backed by a tightly packed `[u8; N]` array,
/// along with constant-time getter methods for extracting
/// sub-byte, unaligned, or standard fields.
///
/// For enums, it generates a `#[repr(uN)]` enum (up to 128 bits)
/// with strongly typed variants, safely parsing underlying bit patters
/// and ensuring exhaustive coverage of all possible states.
///
/// # Syntax
///
/// The macro uses a custom syntax to define
/// the total size and the exact placement of each field
/// or enum variants:
///
/// ### Structs
///
/// ```rust
/// use bitx::bits;
///
/// bits! {
///     /// Optional documentation and attributes for the struct
///     pub struct Header: 4.4 { // Total size = 4.4 = 4 bytes + 4 bits
///         /// Flag indicating active status
///         0.0 pub is_active: u1, // 1-bit fiels return `bool`
///         
///         /// A 3-bit status code
///         0.1 pub status: u3, // Custom bit-widths are supported
///         
///         /// Standard aligned field
///         1 pub payload: u16, // Bit offset defaults to 0
///         
///         /// Unaligned cross-byte field
///         3.4 checksum: u8,
///     }
/// }
/// ```
///
/// ### Enums
///
/// Enums map specific bit patterns to variants.
/// You must define the bit size,
/// and the macro ensures the enum is not less-covered/overstuffed.
///
/// ```rust
/// use bitx::bits;
///
/// bits! {
///     /// A 2-bit state enumeration
///     pub enum State: 0.2 {
///         0 Inactive,
///         1 Active,
///         2 Error,
///         _ Unknown, // Default fallback for unmapped bit patterns
///     }
/// }
/// ```
///
/// # Offsets
///
/// Offsets for the total struct size and
/// individual fields use a `<byte>.<bit>` format:
///
/// - `byte`: The byte offset.
/// - `bit`: The bit offset within the byte. Must be between 0 and 7.
///
/// If a field starts precisely on a byte boundary,
/// the `.0` suffix is optional
/// (e.g., `4` is equivalent to `4.0`).
///
/// # Types
///
/// Fields can be defined using standard or
/// custom bit-width primitives:
///
/// - `u1`: Treated as a boolean flag.
/// - `u2` to `u128`: Custom bit-width integers.
/// - `T`: Custom types are supported if created with `bits!` macro.
///   Unaligned reads for nested types are supported up to 128 bits.
///
/// # Generated API
///
/// For both structs and enums, the macro generates:
///
/// - `pub const fn from_array(value: [u8; SIZE]) -> Self`
///
/// When reading from a slice, the return type differs
/// to prevent unaligned read of multibyte integer:
///
/// - Struct: `pub const fn from_slice(value: &[u8]) -> Option<&Self>`
/// - Enum: `pub const fn from_slice(value: &[u8]) -> Option<Self>`
///
/// Structs also receive generated constant-time field getters.
///
pub use bitx_macros::bits;

/// A trait representing bit-manipulatability of struct.
///
/// Since macro automatically implements and manages this trait,
/// It's highly discouraged that manually implementing this trait.
pub trait Bits {
    /// A mask type to extract data from byte stream.
    ///
    /// Unit type will be used for structs larger than 128-bit.
    type Mask;

    /// A declared size of struct, in bits.
    const BITS: u32;
}