Skip to main content

bitpiece/
lib.rs

1#![no_std]
2
3//! # bitpiece
4//!
5//! A powerful Rust crate for working with bitfields. Define compact, type-safe bitfield structures with automatic bit packing and extraction.
6//!
7//! [![Crates.io](https://img.shields.io/crates/v/bitpiece.svg)](https://crates.io/crates/bitpiece)
8//! [![Documentation](https://docs.rs/bitpiece/badge.svg)](https://docs.rs/bitpiece)
9//! [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
10//!
11//! ## Features
12//!
13//! - **Const-compatible**: All operations work in `const` contexts
14//! - **`no_std` compatible**: Works in embedded and bare-metal environments
15//! - **Type-safe**: Strong typing prevents mixing up different bitfield types
16//! - **Flexible bit widths**: Support for arbitrary bit widths from 1 to 64 bits
17//! - **Signed and unsigned**: Both signed (`SB*`) and unsigned (`B*`) arbitrary-width types
18//! - **Nested bitfields**: Compose complex structures from simpler bitfield types
19//! - **Enum support**: Use enums as bitfield members with automatic bit width calculation
20//! - **Zero-cost abstractions**: Compiles down to efficient bit manipulation operations
21//!
22//! ## Quick Start
23//!
24//! ```rust
25//! use bitpiece::*;
26//!
27//! // Define a 2-bit enum
28//! #[bitpiece(2, all)]
29//! #[derive(Debug, PartialEq, Eq)]
30//! enum Priority {
31//!     Low = 0,
32//!     Medium = 1,
33//!     High = 2,
34//!     Critical = 3,
35//! }
36//!
37//! // Define an 8-bit struct containing multiple fields
38//! #[bitpiece(8, all)]
39//! #[derive(Debug, PartialEq, Eq)]
40//! struct StatusByte {
41//!     enabled: bool,      // 1 bit
42//!     priority: Priority, // 2 bits
43//!     count: B5,          // 5 bits (unsigned, 0-31)
44//! }
45//!
46//! fn main() {
47//!     // Create from raw bits
48//!     let status = StatusByte::from_bits(0b10101_01_1);
49//!     
50//!     assert_eq!(status.enabled(), true);
51//!     assert_eq!(status.priority(), Priority::Medium);
52//!     assert_eq!(status.count(), B5::new(21));
53//!     
54//!     // Modify fields
55//!     let updated = status
56//!         .with_priority(Priority::Critical)
57//!         .with_count(B5::new(7));
58//!     
59//!     assert_eq!(updated.to_bits(), 0b00111_11_1);
60//! }
61//! ```
62//!
63//! ## Table of Contents
64//!
65//! - [The `#[bitpiece]` Attribute](#the-bitpiece-attribute)
66//! - [Built-in Types](#built-in-types)
67//! - [Defining Bitfield Structs](#defining-bitfield-structs)
68//! - [Defining Bitfield Enums](#defining-bitfield-enums)
69//! - [Generated Methods and Types](#generated-methods-and-types)
70//! - [Opt-in Features](#opt-in-features)
71//! - [Attributes and Derives](#attributes-and-derives)
72//! - [Working with Fields](#working-with-fields)
73//! - [Nested Bitfields](#nested-bitfields)
74//! - [Signed Types](#signed-types)
75//! - [Const Context Usage](#const-context-usage)
76//! - [The BitPiece Trait](#the-bitpiece-trait)
77//! - [Error Handling](#error-handling)
78//!
79//! ## The `#[bitpiece]` Attribute
80//!
81//! The `#[bitpiece]` attribute macro is the main entry point for defining bitfield types. It can be applied to structs and enums.
82//!
83//! ### Syntax
84//!
85//! ```rust,ignore
86//! #[bitpiece]                    // Auto-calculate bit length, basic features
87//! #[bitpiece(all)]               // Auto-calculate bit length, all features
88//! #[bitpiece(32)]                // Explicit 32-bit length, basic features
89//! #[bitpiece(32, all)]           // Explicit 32-bit length, all features
90//! #[bitpiece(get, set)]          // Auto-calculate, specific features only
91//! #[bitpiece(16, get, set, with)] // Explicit length with specific features
92//! ```
93//!
94//! ### Arguments
95//!
96//! 1. **Bit length** (optional): An integer specifying the exact bit length. If omitted, the bit length is calculated automatically from the fields (for structs) or variant values (for enums).
97//!
98//! 2. **Feature flags** (optional): Control which methods and types are generated. See [Opt-in Features](#opt-in-features) for details.
99//!
100//! ## Built-in Types
101//!
102//! ### Unsigned Arbitrary-Width Types (`B1` - `B64`)
103//!
104//! Types for unsigned integers of specific bit widths:
105//!
106//! ```rust
107//! # use bitpiece::*;
108//! let three_bits: B3 = B3::new(0b101);  // 3-bit value (0-7)
109//! let five_bits: B5 = B5::new(31);       // 5-bit value (0-31)
110//!
111//! assert_eq!(three_bits.get(), 5);
112//! assert_eq!(B3::MAX.get(), 7);
113//!
114//! // Validation
115//! assert!(B3::try_new(7).is_some());   // Valid: fits in 3 bits
116//! assert!(B3::try_new(8).is_none());   // Invalid: requires 4 bits
117//! ```
118//!
119//! ### Signed Arbitrary-Width Types (`SB1` - `SB64`)
120//!
121//! Types for signed integers of specific bit widths using two's complement:
122//!
123//! ```rust
124//! # use bitpiece::*;
125//! let signed: SB5 = SB5::new(-10);  // 5-bit signed value (-16 to 15)
126//!
127//! assert_eq!(signed.get(), -10);
128//! assert_eq!(SB5::MIN.get(), -16);
129//! assert_eq!(SB5::MAX.get(), 15);
130//!
131//! // Validation
132//! assert!(SB3::try_new(3).is_some());   // Valid: fits in 3 bits
133//! assert!(SB3::try_new(-4).is_some());  // Valid: minimum for SB3
134//! assert!(SB3::try_new(4).is_none());   // Invalid: too large
135//! assert!(SB3::try_new(-5).is_none());  // Invalid: too small
136//! ```
137//!
138//! ### Standard Integer Types
139//!
140//! All standard Rust integer types implement `BitPiece`:
141//!
142//! - Unsigned: `u8`, `u16`, `u32`, `u64`
143//! - Signed: `i8`, `i16`, `i32`, `i64`
144//!
145//! ```rust
146//! # use bitpiece::*;
147//! #[bitpiece(48, all)]
148//! struct MixedTypes {
149//!     byte: u8,      // 8 bits
150//!     word: u16,     // 16 bits
151//!     flags: B8,     // 8 bits
152//!     signed: i16,   // 16 bits
153//! }
154//! ```
155//!
156//! ### Boolean Type
157//!
158//! `bool` is a 1-bit type:
159//!
160//! ```rust
161//! # use bitpiece::*;
162//! #[bitpiece(3, all)]
163//! struct Flags {
164//!     read: bool,    // 1 bit
165//!     write: bool,   // 1 bit
166//!     execute: bool, // 1 bit
167//! }
168//! ```
169//!
170//! ## Defining Bitfield Structs
171//!
172//! Structs are the primary way to define composite bitfields. Fields are packed in order from least significant bit (LSB) to most significant bit (MSB).
173//!
174//! ```rust
175//! # use bitpiece::*;
176//! #[bitpiece(16, all)]
177//! #[derive(Debug, PartialEq, Eq)]
178//! struct Instruction {
179//!     opcode: B4,    // Bits 0-3 (LSB)
180//!     reg_a: B3,     // Bits 4-6
181//!     reg_b: B3,     // Bits 7-9
182//!     immediate: B6, // Bits 10-15 (MSB)
183//! }
184//!
185//! // Bit layout:
186//! // [immediate: 6 bits][reg_b: 3 bits][reg_a: 3 bits][opcode: 4 bits]
187//! // MSB                                                          LSB
188//! ```
189//!
190//! ### Field Ordering
191//!
192//! Fields are packed starting from bit 0:
193//!
194//! ```rust
195//! # use bitpiece::*;
196//! #[bitpiece(8, all)]
197//! struct Example {
198//!     a: B2,  // Bits 0-1
199//!     b: B3,  // Bits 2-4
200//!     c: B3,  // Bits 5-7
201//! }
202//!
203//! let val = Example::from_bits(0b111_010_01);
204//! assert_eq!(val.a(), B2::new(0b01));
205//! assert_eq!(val.b(), B3::new(0b010));
206//! assert_eq!(val.c(), B3::new(0b111));
207//! ```
208//!
209//! ## Defining Bitfield Enums
210//!
211//! Enums can be used as bitfield types. The bit width is automatically calculated from the variant values, or can be specified explicitly.
212//!
213//! ### Exhaustive Enums
214//!
215//! When all possible bit patterns map to valid variants:
216//!
217//! ```rust
218//! # use bitpiece::*;
219//! #[bitpiece(2, all)]  // 2 bits = 4 possible values
220//! #[derive(Debug, PartialEq, Eq)]
221//! enum Direction {
222//!     North = 0,
223//!     East = 1,
224//!     South = 2,
225//!     West = 3,
226//! }
227//!
228//! // All 2-bit values (0-3) are valid
229//! let dir = Direction::from_bits(2);
230//! assert_eq!(dir, Direction::South);
231//! ```
232//!
233//! ### Non-Exhaustive Enums
234//!
235//! When not all bit patterns are valid variants:
236//!
237//! ```rust
238//! # use bitpiece::*;
239//! #[bitpiece(all)]  // Auto-calculated: 7 bits needed for value 100
240//! #[derive(Debug, PartialEq, Eq)]
241//! enum ErrorCode {
242//!     Success = 0,
243//!     NotFound = 10,
244//!     PermissionDenied = 50,
245//!     InternalError = 100,
246//! }
247//!
248//! // Valid variant
249//! assert_eq!(ErrorCode::from_bits(10), ErrorCode::NotFound);
250//!
251//! // Invalid bit pattern panics in from_bits
252//! // Use try_from_bits for safe conversion
253//! assert!(ErrorCode::try_from_bits(25).is_none());
254//! assert!(ErrorCode::try_from_bits(50).is_some());
255//! ```
256//!
257//! ### Explicit Bit Length for Enums
258//!
259//! You can specify a larger bit length than required:
260//!
261//! ```rust
262//! # use bitpiece::*;
263//! #[bitpiece(16, all)]  // Use 16 bits even though values fit in fewer
264//! #[derive(Debug, PartialEq, Eq)]
265//! enum Command {
266//!     Nop = 0,
267//!     Load = 1,
268//!     Store = 2,
269//! }
270//!
271//! // Can accept 16-bit values
272//! assert!(Command::try_from_bits(1000).is_none());
273//! ```
274//!
275//! ## Generated Methods and Types
276//!
277//! When you apply `#[bitpiece]` to a struct, several methods and types are generated.
278//!
279//! ### Generated Constants
280//!
281//! ```rust,ignore
282//! #[bitpiece(16, all)]
283//! struct MyStruct { /* ... */ }
284//!
285//! // Generated constants:
286//! const MY_STRUCT_BIT_LEN: usize = 16;
287//! type MyStructStorageTy = u16;  // Smallest type that fits
288//! ```
289//!
290//! ### Field Constants
291//!
292//! For each field, offset and length constants are generated:
293//!
294//! ```rust
295//! # use bitpiece::*;
296//! #[bitpiece(8, all)]
297//! struct Example {
298//!     a: B3,
299//!     b: B5,
300//! }
301//!
302//! // Generated:
303//! // Example::A_OFFSET = 0
304//! // Example::A_LEN = 3
305//! // Example::B_OFFSET = 3
306//! // Example::B_LEN = 5
307//! ```
308//!
309//! ### Core Methods
310//!
311//! ```rust, ignore
312//! impl MyStruct {
313//!     // Create from raw bits (panics if invalid for non-exhaustive types)
314//!     pub const fn from_bits(bits: StorageTy) -> Self;
315//!     
316//!     // Try to create from raw bits (returns None if invalid)
317//!     pub const fn try_from_bits(bits: StorageTy) -> Option<Self>;
318//!     
319//!     // Convert to raw bits
320//!     pub const fn to_bits(self) -> StorageTy;
321//! }
322//! ```
323//!
324//! ### Associated Constants
325//!
326//! ```rust,ignore
327//! impl BitPiece for MyStruct {
328//!     const BITS: usize;   // Total bit length
329//!     const ZEROES: Self;  // All bits set to 0 (for structs: each field's ZEROES)
330//!     const ONES: Self;    // All bits set to 1 (for structs: each field's ONES)
331//!     const MIN: Self;     // The minimum value (for structs: each field's MIN)
332//!     const MAX: Self;     // The maximum value (for structs: each field's MAX)
333//! }
334//! ```
335//!
336//! **Important distinction between `ONES`/`ZEROES` and `MAX`/`MIN`:**
337//!
338//! - `ZEROES`: All bits are 0. For unsigned types, this equals `MIN`. For signed types, this is 0 (not the minimum).
339//! - `ONES`: All bits are 1. For unsigned types, this equals `MAX`. For signed types like `i8`, this represents `-1` (not the maximum).
340//! - `MIN`: The minimum representable value. For `i8`, this is `-128`.
341//! - `MAX`: The maximum representable value. For `i8`, this is `127`.
342//!
343//! ```rust
344//! # use bitpiece::*;
345//! // For unsigned types: ZEROES == MIN, ONES == MAX
346//! assert_eq!(B8::ZEROES.get(), 0);
347//! assert_eq!(B8::ONES.get(), 255);
348//! assert_eq!(B8::MIN.get(), 0);
349//! assert_eq!(B8::MAX.get(), 255);
350//!
351//! // For signed types: ONES != MAX, ZEROES != MIN
352//! assert_eq!(SB8::ZEROES.get(), 0);    // All bits 0 = 0
353//! assert_eq!(SB8::ONES.get(), -1);     // All bits 1 = -1 in two's complement
354//! assert_eq!(SB8::MIN.get(), -128);    // Minimum value
355//! assert_eq!(SB8::MAX.get(), 127);     // Maximum value
356//! ```
357//!
358//! **Non-exhaustive enums:** For enums where not all bit patterns are valid variants, `ZEROES` and `ONES` represent the closest valid variant to the all-zeros or all-ones bit pattern (i.e., `MIN` and `MAX` respectively). If an enum has no variant with value 0, `ZEROES` will be the variant with the smallest value, not a value with all bits set to zero.
359//!
360//! ```rust
361//! # use bitpiece::*;
362//! #[bitpiece(all)]
363//! #[derive(Debug, PartialEq, Eq)]
364//! enum Sparse {
365//!     A = 10,
366//!     B = 50,
367//!     C = 100,
368//! }
369//!
370//! // No variant has value 0, so ZEROES is the minimum variant
371//! assert_eq!(Sparse::ZEROES, Sparse::A);  // Value 10, not 0
372//! assert_eq!(Sparse::MIN, Sparse::A);
373//! assert_eq!(Sparse::ONES, Sparse::C);    // Maximum variant
374//! assert_eq!(Sparse::MAX, Sparse::C);
375//! ```
376//!
377//! ## Opt-in Features
378//!
379//! Control which methods and types are generated using feature flags.
380//!
381//! ### Feature Flags
382//!
383//! | Flag | Description |
384//! |------|-------------|
385//! | `get` | Field getter methods: `field_name()` |
386//! | `set` | Field setter methods: `set_field_name(value)` |
387//! | `with` | Builder-style methods: `with_field_name(value)` |
388//! | `get_noshift` | Raw bit access: `field_name_noshift()` |
389//! | `get_mut` | Mutable field references: `field_name_mut()` |
390//! | `const_eq` | Const equality comparison |
391//! | `fields_struct` | Generate `TypeNameFields` struct |
392//! | `mut_struct` | Generate `TypeNameMutRef` type |
393//! | `mut_struct_field_get` | Getter methods on MutRef |
394//! | `mut_struct_field_set` | Setter methods on MutRef |
395//! | `mut_struct_field_get_noshift` | Noshift getters on MutRef |
396//! | `mut_struct_field_mut` | Nested mutable references on MutRef |
397//!
398//! ### Presets
399//!
400//! | Preset | Includes |
401//! |--------|----------|
402//! | `basic` | `get`, `set`, `with` (default if no flags specified) |
403//! | `all` | All features |
404//! | `mut_struct_all` | All `mut_struct*` features |
405//!
406//! ### Examples
407//!
408//! ```rust,ignore
409//! # use bitpiece::*;
410//! // Only getters
411//! #[bitpiece(8, get)]
412//! struct ReadOnly { /* ... */ }
413//!
414//! // Getters and setters, no builder pattern
415//! #[bitpiece(8, get, set)]
416//! struct Mutable { /* ... */ }
417//!
418//! // Everything
419//! #[bitpiece(8, all)]
420//! struct Full { /* ... */ }
421//!
422//! // Custom combination
423//! #[bitpiece(8, get, with, fields_struct)]
424//! struct Custom { /* ... */ }
425//! ```
426//!
427//! ## Attributes and Derives
428//!
429//! When you apply `#[bitpiece]` to a type, any attributes you place on the type (such as `#[derive(...)]`) are applied to both the main generated type and the generated fields struct (if `fields_struct` is enabled).
430//!
431//! ### Automatic Clone and Copy
432//!
433//! The `Clone` and `Copy` traits are **automatically derived** on all bitpiece types. You do not need to (and should not) manually derive these traits:
434//!
435//! ```rust
436//! # use bitpiece::*;
437//! // Clone and Copy are automatically derived - don't include them!
438//! #[bitpiece(8, all)]
439//! #[derive(Debug, PartialEq, Eq)]  // No Clone, Copy needed
440//! struct MyStruct {
441//!     a: B4,
442//!     b: B4,
443//! }
444//!
445//! // Same for enums
446//! #[bitpiece(2, all)]
447//! #[derive(Debug, PartialEq, Eq)]  // No Clone, Copy needed
448//! enum MyEnum {
449//!     A = 0,
450//!     B = 1,
451//!     C = 2,
452//!     D = 3,
453//! }
454//! ```
455//!
456//! This automatic derivation ensures that all bitpiece types satisfy the `Copy` bound required by the `BitPiece` trait.
457//!
458//! ### Deriving Additional Traits
459//!
460//! You can derive additional traits like `Debug`, `PartialEq`, `Eq`, `Hash`, or even third-party traits like `serde::Serialize` and `serde::Deserialize`:
461//!
462//! ```rust
463//! # use bitpiece::*;
464//! #[bitpiece(16, all)]
465//! #[derive(Debug, PartialEq, Eq, Hash)]
466//! struct Packet {
467//!     version: B4,
468//!     flags: B4,
469//!     length: u8,
470//! }
471//!
472//! // With serde (requires serde feature/dependency)
473//! // #[bitpiece(8, all)]
474//! // #[derive(Debug, serde::Serialize, serde::Deserialize)]
475//! // struct Config {
476//! //     mode: B4,
477//! //     level: B4,
478//! // }
479//! ```
480//!
481//! These attributes are applied to both the main `Packet` type and the `PacketFields` struct, allowing you to serialize/deserialize both types consistently.
482//!
483//! ## Working with Fields
484//!
485//! ### Getting Field Values
486//!
487//! ```rust
488//! # use bitpiece::*;
489//! #[bitpiece(8, all)]
490//! struct Packet {
491//!     version: B2,
492//!     flags: B3,
493//!     length: B3,
494//! }
495//!
496//! let packet = Packet::from_bits(0b101_110_01);
497//!
498//! // Get individual fields
499//! let version = packet.version();  // B2
500//! let flags = packet.flags();      // B3
501//! let length = packet.length();    // B3
502//!
503//! assert_eq!(version.get(), 1);
504//! assert_eq!(flags.get(), 6);
505//! assert_eq!(length.get(), 5);
506//! ```
507//!
508//! ### Setting Field Values (Immutable)
509//!
510//! The `with_*` methods return a new instance with the field modified:
511//!
512//! ```rust
513//! # use bitpiece::*;
514//! # #[bitpiece(8, all)]
515//! # struct Packet {
516//! #     version: B2,
517//! #     flags: B3,
518//! #     length: B3,
519//! # }
520//! let packet = Packet::ZEROES;
521//!
522//! // Chain modifications
523//! let updated = packet
524//!     .with_version(B2::new(2))
525//!     .with_flags(B3::new(7))
526//!     .with_length(B3::new(4));
527//!
528//! // Original unchanged
529//! assert_eq!(packet.to_bits(), 0);
530//! ```
531//!
532//! ### Setting Field Values (Mutable)
533//!
534//! The `set_*` methods modify the instance in place:
535//!
536//! ```rust
537//! # use bitpiece::*;
538//! # #[bitpiece(8, all)]
539//! # struct Packet {
540//! #     version: B2,
541//! #     flags: B3,
542//! #     length: B3,
543//! # }
544//! let mut packet = Packet::ZEROES;
545//!
546//! packet.set_version(B2::new(2));
547//! packet.set_flags(B3::new(7));
548//! packet.set_length(B3::new(4));
549//! ```
550//!
551//! ### Raw Bit Access (Noshift)
552//!
553//! Get field bits at their original position without shifting:
554//!
555//! ```rust
556//! # use bitpiece::*;
557//! #[bitpiece(8, all)]
558//! struct Example {
559//!     a: B3,  // Bits 0-2
560//!     b: B5,  // Bits 3-7
561//! }
562//!
563//! let val = Example::from_bits(0b11111_010);
564//!
565//! // Normal getter: shifts to bit 0
566//! assert_eq!(val.b().get(), 0b11111);
567//!
568//! // Noshift: keeps original position
569//! assert_eq!(val.b_noshift(), 0b11111_000);
570//! ```
571//!
572//! ### Mutable References
573//!
574//! Get a mutable reference to a field within the bitfield:
575//!
576//! ```rust
577//! # use bitpiece::*;
578//! #[bitpiece(8, all)]
579//! struct Container {
580//!     inner: B4,
581//!     outer: B4,
582//! }
583//!
584//! let mut container = Container::ZEROES;
585//! {
586//!     let mut inner_ref = container.inner_mut();
587//!     inner_ref.set(B4::new(15));
588//! }
589//! assert_eq!(container.inner().get(), 15);
590//! ```
591//!
592//! ## Nested Bitfields
593//!
594//! Bitfield types can be nested within other bitfields:
595//!
596//! ```rust
597//! # use bitpiece::*;
598//! #[bitpiece(4, all)]
599//! #[derive(Debug, PartialEq, Eq)]
600//! struct Inner {
601//!     x: B2,
602//!     y: B2,
603//! }
604//!
605//! #[bitpiece(12, all)]
606//! #[derive(Debug, PartialEq, Eq)]
607//! struct Outer {
608//!     a: Inner,    // 4 bits
609//!     b: Inner,    // 4 bits
610//!     c: B4,       // 4 bits
611//! }
612//!
613//! let outer = Outer::from_bits(0b1010_0110_0011);
614//!
615//! // Access nested fields
616//! assert_eq!(outer.a().x(), B2::new(3));
617//! assert_eq!(outer.a().y(), B2::new(0));
618//! assert_eq!(outer.b().x(), B2::new(2));
619//! assert_eq!(outer.b().y(), B2::new(1));
620//! assert_eq!(outer.c(), B4::new(10));
621//! ```
622//!
623//! ### Deep Nesting
624//!
625//! ```rust
626//! # use bitpiece::*;
627//! #[bitpiece(8, all)]
628//! struct Level1 {
629//!     data: B4,
630//!     flags: B4,
631//! }
632//!
633//! #[bitpiece(16, all)]
634//! struct Level2 {
635//!     l1_a: Level1,
636//!     l1_b: Level1,
637//! }
638//!
639//! #[bitpiece(32, all)]
640//! struct Level3 {
641//!     l2: Level2,
642//!     extra: u16,
643//! }
644//!
645//! let l3 = Level3::from_bits(0x12345678);
646//! let nested_data = l3.l2().l1_a().data();
647//! ```
648//!
649//! ## Signed Types
650//!
651//! ### Using Standard Signed Integers
652//!
653//! ```rust
654//! # use bitpiece::*;
655//! #[bitpiece(24, all)]
656//! struct SignedExample {
657//!     small: i8,   // 8-bit signed
658//!     large: i16,  // 16-bit signed
659//! }
660//!
661//! let val = SignedExample::from_fields(SignedExampleFields {
662//!     small: -50,
663//!     large: -1000,
664//! });
665//!
666//! assert_eq!(val.small(), -50i8);
667//! assert_eq!(val.large(), -1000i16);
668//! ```
669//!
670//! ### Using Arbitrary-Width Signed Types
671//!
672//! ```rust
673//! # use bitpiece::*;
674//! #[bitpiece(16, all)]
675//! struct CustomSigned {
676//!     a: SB5,   // 5-bit signed (-16 to 15)
677//!     b: bool,
678//!     c: SB7,   // 7-bit signed (-64 to 63)
679//!     d: B3,
680//! }
681//!
682//! let val = CustomSigned::from_bits(0b101_0101010_1_11111);
683//!
684//! assert_eq!(val.a(), SB5::new(-1));
685//! assert_eq!(val.b(), true);
686//! assert_eq!(val.c(), SB7::new(42));
687//! assert_eq!(val.d(), B3::new(5));
688//! ```
689//!
690//! ## Const Context Usage
691//!
692//! All operations work in `const` contexts:
693//!
694//! ```rust
695//! # use bitpiece::*;
696//! #[bitpiece(8, all)]
697//! struct Config {
698//!     mode: B2,
699//!     speed: B3,
700//!     enabled: bool,
701//!     reserved: B2,
702//! }
703//!
704//! // Const construction
705//! const DEFAULT_CONFIG: Config = Config::from_bits(0b00_1_101_01);
706//!
707//! // Const field access
708//! const DEFAULT_MODE: B2 = DEFAULT_CONFIG.mode();
709//! const DEFAULT_SPEED: B3 = DEFAULT_CONFIG.speed();
710//! const IS_ENABLED: bool = DEFAULT_CONFIG.enabled();
711//!
712//! // Const modification
713//! const DISABLED_CONFIG: Config = DEFAULT_CONFIG.with_enabled(false);
714//!
715//! // Const assertions
716//! const _: () = assert!(DEFAULT_MODE.get() == 1);
717//! const _: () = assert!(DEFAULT_SPEED.get() == 5);
718//! const _: () = assert!(IS_ENABLED == true);
719//! ```
720//!
721//! ### Const Functions
722//!
723//! ```rust
724//! # use bitpiece::*;
725//! # #[bitpiece(8, all)]
726//! # struct Packet {
727//! #     version: B2,
728//! #     flags: B3,
729//! #     length: B3,
730//! # }
731//! const fn create_packet(version: u8, flags: u8) -> Packet {
732//!     Packet::ZEROES
733//!         .with_version(B2::new(version))
734//!         .with_flags(B3::new(flags))
735//! }
736//!
737//! const PACKET: Packet = create_packet(2, 5);
738//! ```
739//!
740//! ## The BitPiece Trait
741//!
742//! All bitfield types implement the `BitPiece` trait:
743//!
744//! ```rust
745//! # use bitpiece::BitStorage;
746//! pub trait BitPiece: Copy {
747//!     /// The length in bits of this type
748//!     const BITS: usize;
749//!     
750//!     /// A value with all bits set to 0 (see note below for enums)
751//!     const ZEROES: Self;
752//!     
753//!     /// A value with all bits set to 1 (see note below for enums)
754//!     const ONES: Self;
755//!     
756//!     /// The minimum representable value
757//!     const MIN: Self;
758//!     
759//!     /// The maximum representable value
760//!     const MAX: Self;
761//!     
762//!     /// The storage type used internally
763//!     type Bits: BitStorage;
764//!     
765//!     /// Try to create from raw bits
766//!     fn try_from_bits(bits: Self::Bits) -> Option<Self>;
767//!     
768//!     /// Create from raw bits (may panic)
769//!     fn from_bits(bits: Self::Bits) -> Self;
770//!     
771//!     /// Convert to raw bits
772//!     fn to_bits(self) -> Self::Bits;
773//! }
774//! ```
775//!
776//! ### Using the Trait Generically
777//!
778//! ```rust
779//! # use bitpiece::*;
780//! fn print_bitpiece_info<T: BitPiece + core::fmt::Debug>(value: T)
781//! {
782//!     println!("Bits: {}", T::BITS);
783//!     println!("Value: {:?}", value);
784//! }
785//! ```
786//!
787//! ## Error Handling
788//!
789//! ### Safe Conversion with `try_from_bits`
790//!
791//! ```rust
792//! # use bitpiece::*;
793//! #[bitpiece(all)]
794//! #[derive(Debug, PartialEq, Eq)]
795//! enum Status {
796//!     Ok = 0,
797//!     Error = 1,
798//!     Pending = 2,
799//! }
800//!
801//! // Safe conversion
802//! match Status::try_from_bits(1) {
803//!     Some(status) => println!("Status: {:?}", status),
804//!     None => println!("Invalid status code"),
805//! }
806//!
807//! // For exhaustive enums, try_from_bits still validates range
808//! assert!(Status::try_from_bits(3).is_none());
809//! ```
810//!
811//! ### Validation for B* and SB* Types
812//!
813//! ```rust
814//! # use bitpiece::*;
815//! // B types validate that value fits in bit width
816//! assert!(B4::try_new(15).is_some());  // Max for 4 bits
817//! assert!(B4::try_new(16).is_none());  // Too large
818//!
819//! // SB types validate signed range
820//! assert!(SB4::try_new(7).is_some());   // Max for 4-bit signed
821//! assert!(SB4::try_new(-8).is_some());  // Min for 4-bit signed
822//! assert!(SB4::try_new(8).is_none());   // Too large
823//! assert!(SB4::try_new(-9).is_none());  // Too small
824//! ```
825//!
826//! ### Panicking Constructors
827//!
828//! The `new` and `from_bits` methods panic on invalid input:
829//!
830//! ```rust,should_panic
831//! # use bitpiece::*;
832//! # #[bitpiece(all)]
833//! # #[derive(Debug, PartialEq, Eq)]
834//! # enum Status {
835//! #     Ok = 0,
836//! #     Error = 1,
837//! #     Pending = 2,
838//! # }
839//! // These will panic:
840//! let _ = B3::new(8);           // Value doesn't fit
841//! let _ = Status::from_bits(5); // Invalid variant
842//! ```
843//!
844//! ## Fields Struct
845//!
846//! When `fields_struct` is enabled, a companion struct is generated for convenient construction:
847//!
848//! ```rust
849//! # use bitpiece::*;
850//! #[bitpiece(8, all)]
851//! #[derive(Debug, PartialEq, Eq)]
852//! struct Packet {
853//!     version: B2,
854//!     flags: B3,
855//!     length: B3,
856//! }
857//!
858//! // Generated: PacketFields struct
859//! let fields = PacketFields {
860//!     version: B2::new(1),
861//!     flags: B3::new(5),
862//!     length: B3::new(7),
863//! };
864//!
865//! let packet = Packet::from_fields(fields);
866//!
867//! // Convert back to fields
868//! let extracted: PacketFields = packet.to_fields();
869//! assert_eq!(fields, extracted);
870//!
871//! // From/Into implementations
872//! let packet2: Packet = fields.into();
873//! let fields2: PacketFields = packet2.into();
874//! ```
875//!
876//! ### Nested Fields
877//!
878//! For nested bitfields, the fields struct uses the direct bitfield type (not its `*Fields` type):
879//!
880//! ```rust
881//! # use bitpiece::*;
882//! #[bitpiece(4, all)]
883//! struct Inner {
884//!     x: B2,
885//!     y: B2,
886//! }
887//!
888//! #[bitpiece(8, all)]
889//! struct Outer {
890//!     a: Inner,
891//!     b: B4,
892//! }
893//!
894//! // OuterFields uses Inner directly for field 'a'
895//! let fields = OuterFields {
896//!     a: Inner::from_bits(0b1001),  // or use InnerFields and convert
897//!     b: B4::new(15),
898//! };
899//!
900//! let outer = Outer::from_fields(fields);
901//!
902//! // You can also construct the inner type from its fields and convert:
903//! let fields2 = OuterFields {
904//!     a: InnerFields {
905//!         x: B2::new(1),
906//!         y: B2::new(2),
907//!     }.into(),  // Convert InnerFields to Inner
908//!     b: B4::new(15),
909//! };
910//! ```
911//!
912//! ## Storage Types
913//!
914//! The crate automatically selects the smallest storage type that fits the bit length:
915//!
916//! | Bit Length | Storage Type |
917//! |------------|--------------|
918//! | 1-8        | `u8`         |
919//! | 9-16       | `u16`        |
920//! | 17-32      | `u32`        |
921//! | 33-64      | `u64`        |
922//!
923//! Access the storage directly:
924//!
925//! ```rust
926//! # use bitpiece::*;
927//! #[bitpiece(12, all)]
928//! struct Example {
929//!     a: B6,
930//!     b: B6,
931//! }
932//!
933//! let val = Example::from_bits(0xABC);
934//!
935//! // Direct storage access
936//! assert_eq!(val.storage, 0xABC);
937//!
938//! // Storage type is u16 for 12 bits
939//! let storage: u16 = val.storage;
940//! ```
941
942mod check;
943mod impls;
944mod mut_ref;
945mod storage;
946mod utils;
947pub use impls::*;
948pub use mut_ref::*;
949pub use storage::*;
950pub use utils::*;
951
952pub use bitpiece_macros::bitpiece;
953pub use const_for::const_for;
954pub use paste::paste;
955
956pub trait BitPiece: Copy {
957    /// the length in bits of this type.
958    const BITS: usize;
959
960    /// a value with all zero bits.
961    const ZEROES: Self;
962
963    /// a value with all one bits.
964    const ONES: Self;
965
966    /// the minimum value.
967    const MIN: Self;
968
969    /// the maximum value.
970    const MAX: Self;
971
972    /// the storage type used internally to store the bits of this bitpiece.
973    type Bits: BitStorage;
974
975    /// a converter types which implements all const conversion functions (e.g `from_bits`).
976    ///
977    /// traits do not support const functions, so const function must be implemented directly on some type, without using a trait.
978    /// but, we can't implement methods directly on foreign types such as `u32` or `bool`, so we must implement them on another type.
979    /// this type is the converter type.
980    ///
981    /// for non-foreign types, this will point to the trait's `Self` type.
982    /// for foreign types, this will point to a type-specific converter type.
983    type Converter;
984
985    fn try_from_bits(bits: Self::Bits) -> Option<Self>;
986    fn from_bits(bits: Self::Bits) -> Self;
987    fn to_bits(self) -> Self::Bits;
988}
989
990pub trait BitPieceHasMutRef: BitPiece {
991    /// the type used to represent a mutable reference to this type inside another bitpiece.
992    type MutRef<'s>: BitPieceMutRef<'s>;
993}
994
995pub trait BitPieceHasFields: BitPiece {
996    /// the type which represents the expanded view of this bitpiece.
997    type Fields;
998    fn from_fields(fields: Self::Fields) -> Self;
999    fn to_fields(self) -> Self::Fields;
1000}