bitcraft 0.9.4

A zero-cost, hardware-aligned bitfield and enumeration generator.
Documentation
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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
/// A declarative macro for generating zero-cost, strictly packed bitfields.
///
/// This macro generates a `#[repr(transparent)]` struct wrapping a base integer type
/// (e.g. `u8`, `u16`, `u32`, `u64`). It automatically generates `const fn` getters,
/// mutable setters (`set_xyz`), and immutable builder methods (`with_xyz`) for each field.
///
/// # Examples
///
/// ### Basic Unsigned & Enum Packing
/// ```rust
/// use bitcraft::{bitstruct, bitenum};
///
/// bitenum! {
///     pub enum EngineState(2) {
///         OFF = 0,
///         IDLE = 1,
///         ACTIVE = 2,
///     }
/// }
///
/// bitstruct! {
///     pub struct VehicleState(u16) {
///         pub is_running: bool = 1,         // Bit 0
///         pub gear: u8 = 3,                 // Bits 1-3
///         pub speed: u16 = 8,               // Bits 4-11
///         pub state: EngineState = 4,       // Bits 12-15
///     }
/// }
///
/// let mut state = VehicleState::default()
///     .with_is_running(true)
///     .with_gear(3)
///     .with_state(EngineState::ACTIVE);
///
/// assert!(state.is_running());
/// assert_eq!(state.gear(), 3);
/// assert_eq!(state.state(), EngineState::ACTIVE);
/// ```
///
/// ### Advanced: Signed Fields and Strict Boundaries
/// `bitstruct!` natively supports Two's Complement signed integers. It automatically handles
/// correct sign-extension on reads and limits-checking on writes.
/// ```rust
/// use bitcraft::{bitstruct, BitstructError};
///
/// bitstruct! {
///     pub struct SensorData(u32) {
///         pub id: u8 = 4,
///         pub temperature: i16 = 12, // 12-bit signed integer (-2048 to 2047)
///         pub humidity: u16 = 10,
///     }
/// }
///
/// let mut data = SensorData::default();
/// data.set_temperature(-500); // Perfectly valid, natively handled
/// assert_eq!(data.temperature(), -500);
///
/// // Strict validation utilizing `try_set_`
/// let res = data.try_set_temperature(3000);
/// assert!(matches!(res, Err(BitstructError::Overflow { .. })));
/// ```
///
/// # Implementation Details
///
/// The `bitstruct!` macro utilizes a functional "Token-Tree Muncher" to incrementally track
/// bit-offsets at compile-time (`$shift`). For each field, it generates a perfect bitmask
/// shifted appropriately. Because all masks and shifts are strictly resolved at compile time,
/// the resulting getters and setters are perfectly optimizable by LLVM into zero-cost single instructions.
///
/// The macro supports signed field definitions (`i8` through `i128`), generating dynamic arithmetic
/// right-shifts for automatic sign-extension without branching.
#[macro_export]
macro_rules! bitstruct {
    (
        $(#[$meta:meta])*
        $vis:vis struct $struct_name:ident ($base_type:ty) {
            $(
                $field_vis:vis $field_name:ident: $field_type:tt = $bits:tt
            ),* $(,)?
        }
    ) => {
        $(#[$meta])*
        #[derive(Copy, Clone, PartialEq, Eq, Default)]
        #[derive($crate::bytemuck::Pod, $crate::bytemuck::Zeroable)]
        #[repr(transparent)]
        $vis struct $struct_name(pub $base_type);

        impl core::fmt::Debug for $struct_name {
            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
                f.debug_struct(stringify!($struct_name))
                    .field("raw", &self.0)
                    $(
                        .field(stringify!($field_name), &self.$field_name())
                    )*
                    .finish()
            }
        }

        const _: () = {
            // Compile-time check: Ensure the base storage is a valid primitive.
            let _ = <$base_type as $crate::IsValidBaseInt>::ASSERT_VALID;

            // Compile-time check: Ensure each field type is valid.
            $crate::bitstruct!(@check_fields $($field_type)*);

            #[allow(dead_code)]
            const TOTAL_BITS: usize = 0 $( + $bits )*;
            assert!(TOTAL_BITS <= <$base_type as $crate::IsValidBaseInt>::MAX_BITS, "Sum of field bits exceeds base type max bits");
        };

        impl $struct_name {
            #[allow(dead_code)]
            pub const BITS: usize = <$base_type as $crate::BitLength>::BITS;

            // Start the TT (Token-Tree) muncher recursion to generate field-specific methods.
            $crate::bitstruct!(@impl_getters_setters $base_type, 0, $($field_vis $field_name $field_type $bits)*);

            /// Returns the raw interior integer value.
            ///
            /// This is useful for serializing the struct or passing it to external APIs.
            #[inline(always)]
            #[allow(dead_code)]
            pub const fn to_bits(self) -> $base_type { self.0 }

            /// Creates a new instance from a raw integer value.
            ///
            /// # Safety
            /// While this method is safe, providing values with bits set outside
            /// the defined field ranges may result in those bits being preserved
            /// (padded) or ignored depending on the getters used.
            #[inline(always)]
            #[allow(dead_code)]
            pub const fn from_bits(val: $base_type) -> Self { Self(val) }
        }
    };

    // --- INTERNAL MACRO IMPLEMENTATION ---
    // The following branches use the "Token-Tree (TT) Muncher" pattern.
    // They recursively consume field definitions, incrementing the bit `$shift` offset with each pass.

    // Base Case: No more fields left to process, recursion terminates.
    (@impl_getters_setters $base_type:ty, $shift:expr, ) => {};

    // TT Muncher: Check each field type is valid
    (@check_fields ) => {};
    (@check_fields $field_type:tt $($rest:tt)*) => {
        let _ = <$field_type as $crate::ValidField>::ASSERT_VALID;
        $crate::bitstruct!(@check_fields $($rest)*);
    };

    // TT Muncher: Specialized traversal arm for `bool` type fields.
    // Bools are handled specifically to return Rust native `true`/`false` rather than `1`/`0`.
    (@impl_getters_setters $base_type:ty, $shift:expr, $field_vis:vis $field_name:ident bool $bits:tt $($rest:tt)*) => {
        $crate::paste::paste! {
            /// The bit-offset of the `$field_name` property within the underlying storage.
            pub const [<$field_name:upper _OFFSET>]: usize = $shift;
            /// The number of bits allocated for the `$field_name` property.
            pub const [<$field_name:upper _BITS>]: usize = $bits;

            #[doc(hidden)]
            const [<$field_name:upper _MASK>]: $base_type = ((!0 as <$base_type as $crate::IsValidBaseInt>::Unsigned) >> (<$base_type as $crate::BitLength>::BITS - Self::[<$field_name:upper _BITS>])) as $base_type;

            #[allow(dead_code)]
            #[inline]
            #[doc = concat!("Returns the boolean value mapping to the `", stringify!($field_name), "` flag.")]
            $field_vis const fn $field_name(self) -> bool {
                ((self.0 >> Self::[<$field_name:upper _OFFSET>]) & Self::[<$field_name:upper _MASK>]) != 0
            }

            #[allow(dead_code)]
            #[inline]
            #[doc = concat!("Inline mutation to set the `", stringify!($field_name), "` flag.")]
            $field_vis fn [<set_ $field_name>](&mut self, val: bool) {
                // bool inherently cannot overflow its bit requirement.
                let val_masked = val as $base_type;
                self.0 = (self.0 & !(Self::[<$field_name:upper _MASK>] << Self::[<$field_name:upper _OFFSET>])) | (val_masked << Self::[<$field_name:upper _OFFSET>]);
            }

            #[allow(dead_code)]
            #[doc = concat!("Returns a cloned copy of the bitfield with the `", stringify!($field_name), "` flag specified.")]
            $field_vis const fn [<with_ $field_name>](self, val: bool) -> Self {
                let val_masked = val as $base_type;
                // Clear the target bits using the inverted mask, then OR with the new value.
                Self((self.0 & !(Self::[<$field_name:upper _MASK>] << Self::[<$field_name:upper _OFFSET>])) | (val_masked << Self::[<$field_name:upper _OFFSET>]))
            }

            #[allow(dead_code)]
            #[doc = concat!("Inline mutation to set the `", stringify!($field_name), "` flag. Returns `Ok(())` since booleans cannot overflow.")]
            $field_vis fn [<try_set_ $field_name>](&mut self, val: bool) -> Result<(), $crate::BitstructError> {
                self.[<set_ $field_name>](val);
                Ok(())
            }

            #[allow(dead_code)]
            #[doc = concat!("Returns a cloned copy of the bitfield with the `", stringify!($field_name), "` flag specified. Returns `Ok(Self)` since booleans cannot overflow.")]
            $field_vis const fn [<try_with_ $field_name>](self, val: bool) -> Result<Self, $crate::BitstructError> {
                Ok(self.[<with_ $field_name>](val))
            }
        }

        $crate::bitstruct!(@impl_getters_setters $base_type, $shift + $bits, $($rest)*);
    };

    // Specialized routing for primitives (to allow them to work without trait impls)
    (@impl_getters_setters $base_type:ty, $shift:expr, $field_vis:vis $field_name:ident u8 $bits:tt $($rest:tt)*) => { $crate::bitstruct!(@impl_int $base_type, $shift, $field_vis $field_name u8 $bits $($rest)*); };
    (@impl_getters_setters $base_type:ty, $shift:expr, $field_vis:vis $field_name:ident u16 $bits:tt $($rest:tt)*) => { $crate::bitstruct!(@impl_int $base_type, $shift, $field_vis $field_name u16 $bits $($rest)*); };
    (@impl_getters_setters $base_type:ty, $shift:expr, $field_vis:vis $field_name:ident u32 $bits:tt $($rest:tt)*) => { $crate::bitstruct!(@impl_int $base_type, $shift, $field_vis $field_name u32 $bits $($rest)*); };
    (@impl_getters_setters $base_type:ty, $shift:expr, $field_vis:vis $field_name:ident u64 $bits:tt $($rest:tt)*) => { $crate::bitstruct!(@impl_int $base_type, $shift, $field_vis $field_name u64 $bits $($rest)*); };
    (@impl_getters_setters $base_type:ty, $shift:expr, $field_vis:vis $field_name:ident u128 $bits:tt $($rest:tt)*) => { $crate::bitstruct!(@impl_int $base_type, $shift, $field_vis $field_name u128 $bits $($rest)*); };
    (@impl_getters_setters $base_type:ty, $shift:expr, $field_vis:vis $field_name:ident i8 $bits:tt $($rest:tt)*) => { $crate::bitstruct!(@impl_signed_int $base_type, $shift, $field_vis $field_name i8 $bits $($rest)*); };
    (@impl_getters_setters $base_type:ty, $shift:expr, $field_vis:vis $field_name:ident i16 $bits:tt $($rest:tt)*) => { $crate::bitstruct!(@impl_signed_int $base_type, $shift, $field_vis $field_name i16 $bits $($rest)*); };
    (@impl_getters_setters $base_type:ty, $shift:expr, $field_vis:vis $field_name:ident i32 $bits:tt $($rest:tt)*) => { $crate::bitstruct!(@impl_signed_int $base_type, $shift, $field_vis $field_name i32 $bits $($rest)*); };
    (@impl_getters_setters $base_type:ty, $shift:expr, $field_vis:vis $field_name:ident i64 $bits:tt $($rest:tt)*) => { $crate::bitstruct!(@impl_signed_int $base_type, $shift, $field_vis $field_name i64 $bits $($rest)*); };
    (@impl_getters_setters $base_type:ty, $shift:expr, $field_vis:vis $field_name:ident i128 $bits:tt $($rest:tt)*) => { $crate::bitstruct!(@impl_signed_int $base_type, $shift, $field_vis $field_name i128 $bits $($rest)*); };

    // Standard integer implementation: Extracts the requested bit width, shifting by the accumulated offset.
    (@impl_int $base_type:ty, $shift:expr, $field_vis:vis $field_name:ident $field_type:tt $bits:tt $($rest:tt)*) => {
        $crate::paste::paste! {
            /// The bit-offset of the `$field_name` property within the underlying storage.
            pub const [<$field_name:upper _OFFSET>]: usize = $shift;
            /// The number of bits allocated for the `$field_name` property.
            pub const [<$field_name:upper _BITS>]: usize = $bits;

            #[doc(hidden)]
            const [<$field_name:upper _MASK>]: $base_type = ((!0 as <$base_type as $crate::IsValidBaseInt>::Unsigned) >> (<$base_type as $crate::BitLength>::BITS - Self::[<$field_name:upper _BITS>])) as $base_type;

            #[allow(dead_code)]
            #[inline]
            #[doc = concat!("Returns the `", stringify!($field_name), "` property as a `", stringify!($field_type), "`.")]
            $field_vis const fn $field_name(self) -> $field_type {
                ((self.0 >> Self::[<$field_name:upper _OFFSET>]) & Self::[<$field_name:upper _MASK>]) as $field_type
            }

            #[allow(dead_code)]
            #[inline]
            #[doc = concat!("Inline mutation to apply the `", stringify!($field_name), "` property. Masks inputs over ", stringify!($bits), " bits.")]
            $field_vis fn [<set_ $field_name>](&mut self, val: $field_type) {
                debug_assert!((val as $base_type) <= Self::[<$field_name:upper _MASK>], "Value {} overflows allocated {} bits", val, $bits);
                let val_masked = (val as $base_type) & Self::[<$field_name:upper _MASK>];
                self.0 = (self.0 & !(Self::[<$field_name:upper _MASK>] << Self::[<$field_name:upper _OFFSET>])) | (val_masked << Self::[<$field_name:upper _OFFSET>]);
            }

            #[allow(dead_code)]
            #[doc = concat!("Returns a cloned copy of the bitfield with the `", stringify!($field_name), "` property mapped. Masks inputs over ", stringify!($bits), " bits.")]
            $field_vis const fn [<with_ $field_name>](self, val: $field_type) -> Self {
                debug_assert!((val as $base_type) <= Self::[<$field_name:upper _MASK>], "Value overflows allocated bits");
                let val_masked = (val as $base_type) & Self::[<$field_name:upper _MASK>];
                Self((self.0 & !(Self::[<$field_name:upper _MASK>] << Self::[<$field_name:upper _OFFSET>])) | (val_masked << Self::[<$field_name:upper _OFFSET>]))
            }

            #[allow(dead_code)]
            #[doc = concat!("Strict inline mutation to apply the `", stringify!($field_name), "` property. Returns a `BitstructError` if the value overflows ", stringify!($bits), " bits.")]
            $field_vis fn [<try_set_ $field_name>](&mut self, val: $field_type) -> Result<(), $crate::BitstructError> {
                if (val as $base_type) > Self::[<$field_name:upper _MASK>] {
                    return Err($crate::BitstructError::Overflow { value: (val as $base_type) as u128, allocated_bits: $bits });
                }
                let val_masked = (val as $base_type) & Self::[<$field_name:upper _MASK>];
                self.0 = (self.0 & !(Self::[<$field_name:upper _MASK>] << Self::[<$field_name:upper _OFFSET>])) | (val_masked << Self::[<$field_name:upper _OFFSET>]);
                Ok(())
            }

            #[allow(dead_code)]
            #[doc = concat!("Strict cloned evaluation to apply the `", stringify!($field_name), "` property. Returns a `BitstructError` if the value overflows ", stringify!($bits), " bits.")]
            $field_vis const fn [<try_with_ $field_name>](self, val: $field_type) -> Result<Self, $crate::BitstructError> {
                if (val as $base_type) > Self::[<$field_name:upper _MASK>] {
                    return Err($crate::BitstructError::Overflow { value: (val as $base_type) as u128, allocated_bits: $bits });
                }
                let val_masked = (val as $base_type) & Self::[<$field_name:upper _MASK>];
                Ok(Self((self.0 & !(Self::[<$field_name:upper _MASK>] << Self::[<$field_name:upper _OFFSET>])) | (val_masked << Self::[<$field_name:upper _OFFSET>])))
            }
        }

        $crate::bitstruct!(@impl_getters_setters $base_type, $shift + $bits, $($rest)*);
    };

    // Signed integer implementation: Handles sign extension on read and bounds-checked writing for two's complement fields.
    //
    // This macro arm intercepts explicit signed field specifications (`i8` through `i128`).
    // Read operations perform a zero-cost "shift trick":
    // 1. Mask the underlying base integer down to the requested bits.
    // 2. Cast into the signed target primitive.
    // 3. Shift the isolated bits up so the target's sign bit aligns with the Most Significant Bit of the field length.
    // 4. Arithmetic right-shift down to naturally propagate the sign bit across the full integer span.
    //
    // Write operations dynamically calculate MIN and MAX limits using an overflow-safe `(!0 << (bits - 1))` shift,
    // ensuring data integrity across partial boundaries.
    (@impl_signed_int $base_type:ty, $shift:expr, $field_vis:vis $field_name:ident $field_type:tt $bits:tt $($rest:tt)*) => {
        $crate::paste::paste! {
            /// The bit-offset of the `$field_name` property within the underlying storage.
            pub const [<$field_name:upper _OFFSET>]: usize = $shift;
            /// The number of bits allocated for the `$field_name` property.
            pub const [<$field_name:upper _BITS>]: usize = $bits;

            #[doc(hidden)]
            const [<$field_name:upper _MASK>]: $base_type = ((!0 as <$base_type as $crate::IsValidBaseInt>::Unsigned) >> (<$base_type as $crate::BitLength>::BITS - Self::[<$field_name:upper _BITS>])) as $base_type;

            #[doc(hidden)]
            pub const [<$field_name:upper _MIN>]: $field_type = (!0 as $field_type) << (Self::[<$field_name:upper _BITS>] - 1);
            #[doc(hidden)]
            pub const [<$field_name:upper _MAX>]: $field_type = !Self::[<$field_name:upper _MIN>];
            #[doc(hidden)]
            const [<$field_name:upper _SHIFT_UP>]: usize = <$field_type as $crate::BitLength>::BITS - Self::[<$field_name:upper _BITS>];

            #[allow(dead_code)]
            #[inline]
            #[doc = concat!("Returns the `", stringify!($field_name), "` property as a signed `", stringify!($field_type), "`.")]
            $field_vis const fn $field_name(self) -> $field_type {
                let raw = ((self.0 >> Self::[<$field_name:upper _OFFSET>]) & Self::[<$field_name:upper _MASK>]) as $field_type;
                (raw << Self::[<$field_name:upper _SHIFT_UP>]) >> Self::[<$field_name:upper _SHIFT_UP>]
            }

            #[allow(dead_code)]
            #[inline]
            #[doc = concat!("Inline mutation to apply the `", stringify!($field_name), "` signed property. Ensures bounds checking.")]
            $field_vis fn [<set_ $field_name>](&mut self, val: $field_type) {
                debug_assert!(val >= Self::[<$field_name:upper _MIN>] && val <= Self::[<$field_name:upper _MAX>], "Value {} out of bounds for {} bits", val, $bits);
                let val_masked = (val as $base_type) & Self::[<$field_name:upper _MASK>];
                self.0 = (self.0 & !(Self::[<$field_name:upper _MASK>] << Self::[<$field_name:upper _OFFSET>])) | (val_masked << Self::[<$field_name:upper _OFFSET>]);
            }

            #[allow(dead_code)]
            #[doc = concat!("Returns a cloned copy of the bitfield with the `", stringify!($field_name), "` signed property mapped.")]
            $field_vis const fn [<with_ $field_name>](self, val: $field_type) -> Self {
                debug_assert!(val >= Self::[<$field_name:upper _MIN>] && val <= Self::[<$field_name:upper _MAX>], "Value overflows allocated bits");
                let val_masked = (val as $base_type) & Self::[<$field_name:upper _MASK>];
                Self((self.0 & !(Self::[<$field_name:upper _MASK>] << Self::[<$field_name:upper _OFFSET>])) | (val_masked << Self::[<$field_name:upper _OFFSET>]))
            }

            #[allow(dead_code)]
            #[doc = concat!("Strict inline mutation to apply the `", stringify!($field_name), "` signed property. Returns a `BitstructError` if out of bounds.")]
            $field_vis fn [<try_set_ $field_name>](&mut self, val: $field_type) -> Result<(), $crate::BitstructError> {
                if val < Self::[<$field_name:upper _MIN>] || val > Self::[<$field_name:upper _MAX>] {
                    return Err($crate::BitstructError::Overflow { value: val as i128 as u128, allocated_bits: $bits });
                }
                let val_masked = (val as $base_type) & Self::[<$field_name:upper _MASK>];
                self.0 = (self.0 & !(Self::[<$field_name:upper _MASK>] << Self::[<$field_name:upper _OFFSET>])) | (val_masked << Self::[<$field_name:upper _OFFSET>]);
                Ok(())
            }

            #[allow(dead_code)]
            #[doc = concat!("Strict cloned evaluation to apply the `", stringify!($field_name), "` signed property. Returns a `BitstructError` if out of bounds.")]
            $field_vis const fn [<try_with_ $field_name>](self, val: $field_type) -> Result<Self, $crate::BitstructError> {
                if val < Self::[<$field_name:upper _MIN>] || val > Self::[<$field_name:upper _MAX>] {
                    return Err($crate::BitstructError::Overflow { value: val as i128 as u128, allocated_bits: $bits });
                }
                let val_masked = (val as $base_type) & Self::[<$field_name:upper _MASK>];
                Ok(Self((self.0 & !(Self::[<$field_name:upper _MASK>] << Self::[<$field_name:upper _OFFSET>])) | (val_masked << Self::[<$field_name:upper _OFFSET>])))
            }
        }

        $crate::bitstruct!(@impl_getters_setters $base_type, $shift + $bits, $($rest)*);
    };


    // Wrapped Type arm: Similar to impl_int, but handles types passed in parentheses (like from byteval! expansion)
    // or trait-associated types. Since these are expected to be primitives, we use `as` casting.
    (@impl_getters_setters $base_type:ty, $shift:expr, $field_vis:vis $field_name:ident ($field_type:ty) $bits:tt $($rest:tt)*) => {
        $crate::paste::paste! {
            /// The bit-offset of the `$field_name` property within the underlying storage.
            pub const [<$field_name:upper _OFFSET>]: usize = $shift;
            /// The number of bits allocated for the `$field_name` property.
            pub const [<$field_name:upper _BITS>]: usize = $bits;

            #[doc(hidden)]
            const [<$field_name:upper _MASK>]: $base_type = ((!0 as <$base_type as $crate::IsValidBaseInt>::Unsigned) >> (<$base_type as $crate::BitLength>::BITS - Self::[<$field_name:upper _BITS>])) as $base_type;

            #[allow(dead_code)]
            #[inline]
            $field_vis const fn $field_name(self) -> $field_type {
                ((self.0 >> Self::[<$field_name:upper _OFFSET>]) & Self::[<$field_name:upper _MASK>]) as $field_type
            }

            #[allow(dead_code)]
            #[inline]
            $field_vis fn [<set_ $field_name>](&mut self, val: $field_type) {
                debug_assert!((val as $base_type) <= Self::[<$field_name:upper _MASK>], "Value {} overflows allocated {} bits", val, $bits);
                let val_masked = (val as $base_type) & Self::[<$field_name:upper _MASK>];
                self.0 = (self.0 & !(Self::[<$field_name:upper _MASK>] << Self::[<$field_name:upper _OFFSET>])) | (val_masked << Self::[<$field_name:upper _OFFSET>]);
            }

            #[allow(dead_code)]
            $field_vis const fn [<with_ $field_name>](self, val: $field_type) -> Self {
                debug_assert!((val as $base_type) <= Self::[<$field_name:upper _MASK>], "Value overflows allocated bits");
                let val_masked = (val as $base_type) & Self::[<$field_name:upper _MASK>];
                Self((self.0 & !(Self::[<$field_name:upper _MASK>] << Self::[<$field_name:upper _OFFSET>])) | (val_masked << Self::[<$field_name:upper _OFFSET>]))
            }

            #[allow(dead_code)]
            $field_vis fn [<try_set_ $field_name>](&mut self, val: $field_type) -> Result<(), $crate::BitstructError> {
                if (val as $base_type) > Self::[<$field_name:upper _MASK>] {
                    return Err($crate::BitstructError::Overflow { value: (val as $base_type) as u128, allocated_bits: $bits });
                }
                self.[<set_ $field_name>](val);
                Ok(())
            }

            #[allow(dead_code)]
            $field_vis const fn [<try_with_ $field_name>](self, val: $field_type) -> Result<Self, $crate::BitstructError> {
                if (val as $base_type) > Self::[<$field_name:upper _MASK>] {
                    return Err($crate::BitstructError::Overflow { value: (val as $base_type) as u128, allocated_bits: $bits });
                }
                Ok(self.[<with_ $field_name>](val))
            }
        }

        $crate::bitstruct!(@impl_getters_setters $base_type, $shift + $bits, $($rest)*);
    };

    // TT Muncher Fallback
    // Uses `from_bits` to upcast/downcast the extracted integer bits back into the Enum variant safely.
    (@impl_getters_setters $base_type:ty, $shift:expr, $field_vis:vis $field_name:ident $field_type:tt $bits:tt $($rest:tt)*) => {
        $crate::paste::paste! {
            /// The bit-offset of the `$field_name` property within the underlying storage.
            pub const [<$field_name:upper _OFFSET>]: usize = $shift;
            /// The number of bits allocated for the `$field_name` property.
            pub const [<$field_name:upper _BITS>]: usize = $bits;

            #[doc(hidden)]
            const [<$field_name:upper _MASK>]: $base_type = ((!0 as <$base_type as $crate::IsValidBaseInt>::Unsigned) >> (<$base_type as $crate::BitLength>::BITS - Self::[<$field_name:upper _BITS>])) as $base_type;

            #[allow(dead_code)]
            #[doc = concat!("Returns the `", stringify!($field_name), "` variant strictly typed to the `", stringify!($field_type), "` enumeration.")]
            $field_vis const fn $field_name(self) -> $field_type {
                // Extract the bits, then cast them into the Enum's base primitive via `_` inference.
                // This relies on the bitenum! macro providing a `from_bits` method.
                $field_type::from_bits(((self.0 >> Self::[<$field_name:upper _OFFSET>]) & Self::[<$field_name:upper _MASK>]) as _)
            }

            #[allow(dead_code)]
            #[doc = concat!("Inline mutation to apply the bounded `", stringify!($field_type), "` enumeration to the `", stringify!($field_name), "` property.")]
            $field_vis fn [<set_ $field_name>](&mut self, val: $field_type) {
                const _: () = assert!(<$field_type>::BITS <= $bits, "Enum bit width exceeds allocated field width");
                // Cast the enum's inner value up to the bitfield's base storage type before shifting
                let val_masked = (val.to_bits() as $base_type) & Self::[<$field_name:upper _MASK>];
                self.0 = (self.0 & !(Self::[<$field_name:upper _MASK>] << Self::[<$field_name:upper _OFFSET>])) | (val_masked << Self::[<$field_name:upper _OFFSET>]);
            }

            #[allow(dead_code)]
            #[doc = concat!("Returns a cloned copy of the bitfield bounded by the `", stringify!($field_type), "` enumeration supplied to `", stringify!($field_name), "`.")]
            $field_vis const fn [<with_ $field_name>](self, val: $field_type) -> Self {
                const _: () = assert!(<$field_type>::BITS <= $bits, "Enum bit width exceeds allocated field width");
                // Cast the enum's inner value up to the bitfield's base storage type before shifting
                let val_masked = (val.to_bits() as $base_type) & Self::[<$field_name:upper _MASK>];
                Self((self.0 & !(Self::[<$field_name:upper _MASK>] << Self::[<$field_name:upper _OFFSET>])) | (val_masked << Self::[<$field_name:upper _OFFSET>]))
            }

            #[allow(dead_code)]
            #[doc = concat!("Strict inline mutation to apply the bounded `", stringify!($field_type), "` enumeration to the `", stringify!($field_name), "` property. Returns a `BitstructError` if the value overflows ", stringify!($bits), " bits.")]
            $field_vis fn [<try_set_ $field_name>](&mut self, val: $field_type) -> Result<(), $crate::BitstructError> {
                self.[<set_ $field_name>](val);
                Ok(())
            }

            #[allow(dead_code)]
            #[doc = concat!("Strict cloned evaluation to apply the bounded `", stringify!($field_type), "` enumeration to the `", stringify!($field_name), "` property. Returns a `BitstructError` if the value overflows ", stringify!($bits), " bits.")]
            $field_vis const fn [<try_with_ $field_name>](self, val: $field_type) -> Result<Self, $crate::BitstructError> {
                Ok(self.[<with_ $field_name>](val))
            }
        }

        $crate::bitstruct!(@impl_getters_setters $base_type, $shift + $bits, $($rest)*);
    };
}