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//! [](https://crates.io/crates/bitpiece)
8//! [](https://docs.rs/bitpiece)
9//! [](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}