devela/data/codec/bit/field/
bitfield.rs

1// devela::data::codec::bit::field::bit_field
2//
3//! the bitfield! macro.
4//
5// IMPROVE DESIGN
6// - modularize, make arms to generate parts (could be public) (hierarchical dsl)
7//   this also makes it able to pass a composed identifier.
8//   e.g. ...
9// [ ] simplify Errors (and error message).
10//
11// - Add the possibility of having masks that are not ranged (discontinuous)
12//   maybe start implementing them manually and see how far I get
13//
14// MAYBE add checked get/set
15
16#![allow(
17    clippy::eq_op,
18    clippy::identity_op,
19    unused_comparisons,
20    reason = "fixes lints for fields assertions"
21)]
22
23/// Creates a custom bit field struct.
24///
25/// The inner type must be an integer primitive.
26///
27/// The new struct already derives
28/// `Clone`, `Copy`, `Debug`, `Default`, `PartialEq`, `Eq` and `Hash`.
29///
30/// # Features
31/// This macro depends on enabling any of the `_bit_*` features. E.g. `_bit_u8`.
32///
33/// # Examples
34/// See also the [bitfield][crate::_info::examples::bitfield] example.
35///
36/// ```
37/// # use devela::bitfield;
38/// bitfield! {
39///     /// My custom bit field struct.
40///     struct MyBf(u8) {
41///         // single bit fields:
42///         FIRST_BIT: 0;
43///         SECOND_BIT: 1;
44///         THIRD_BIT: 2;
45///         // multi-bit fields:
46///         MASK1: 0, 2;
47///         MASK2: 3, 6;
48///     }
49/// }
50/// let b = MyBf::new_zeroed();
51/// assert![b.is_empty()];
52/// ```
53///
54/// See also the [`enumset!`][crate::code::enumset] macro.
55#[doc(hidden)]
56#[macro_export]
57macro_rules! _bitfield {
58    {
59        /* full syntax */
60
61        ( // visibility qualifiers:
62          custom:$vis_custom:vis,   // custom fields
63          extra:$vis_extra:vis      // extra functionality
64        )
65        // $vis:  the visibility of the struct.
66        // $name: the name of the new struct.
67        // $T: the inner integer primitive type (u8, i32, …).
68        $(#[$struct_attributes:meta])*
69        $vis:vis struct $name:ident($T:ty) {
70            // Custom fields (panics if $f_start > $f_end || field_end >= $T::BITS):
71            // $f: the name of the field
72            // $f_start: the starting bit index.
73            // $f_end: the ending bit index (optional).
74            $(
75                $(#[$f_attrs:meta])*
76                $f:ident: $f_start:expr, $f_end:expr; // NAME: from_bit, to_bit;
77            )*
78        }
79    } => { $crate::paste! {
80
81        $( #[$struct_attributes] )*
82        #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
83        $vis struct $name { bits: $T }
84
85        /* core impls */
86
87        impl Default for $name {
88            fn default() -> Self { $name { bits: Default::default() } }
89        }
90        $crate::impl_trait![fmt::Display for $name |self, f|
91            ::core::fmt::Display::fmt(&self.bits, f)];
92        $crate::impl_trait![fmt::Binary for $name |self, f|
93            ::core::fmt::Binary::fmt(&self.bits, f)];
94        $crate::impl_trait![fmt::Octal for $name |self, f|
95            ::core::fmt::Octal::fmt(&self.bits, f)];
96        $crate::impl_trait![fmt::LowerHex for $name |self, f|
97            ::core::fmt::LowerHex::fmt(&self.bits, f)];
98        $crate::impl_trait![fmt::UpperHex for $name |self, f|
99            ::core::fmt::UpperHex::fmt(&self.bits, f)];
100        $crate::impl_trait![fmt::LowerExp for $name |self, f|
101            ::core::fmt::LowerExp::fmt(&self.bits, f)];
102        $crate::impl_trait![fmt::UpperExp for $name |self, f|
103            ::core::fmt::UpperExp::fmt(&self.bits, f)];
104
105        // /// # Custom fields constants
106        #[allow(dead_code)]
107        impl $name {
108            $(
109                // The field bit mask
110                $( #[$f_attrs] )*
111                $vis_custom const $f: Self = {
112                    assert![$f_start <= $f_end,
113                        "The field_start bit is bigger than the field_end bit."];
114                    assert![$f_end < <$T>::BITS,
115                        "There are more fields than available bits in the inner primitive type."];
116                    Self {
117                        bits: $crate::Bitwise::<$T>::mask_range($f_start, $f_end).0
118                    }
119                };
120            )*
121        }
122
123        /// # Custom fields operations
124        #[allow(dead_code)]
125        impl $name {
126            #[doc = "Returns a new `" $name "` with none of the fields set."]
127            #[must_use]
128            $vis_custom const fn without_fields() -> Self {
129                Self { bits: 0 }
130            }
131
132            #[doc = "Returns a new `" $name "` with all the fields set."]
133            #[must_use]
134            $vis_custom const fn with_all_fields() -> Self {
135                Self {
136                    bits: 0 $(| $crate::Bitwise::<$T>::mask_range($f_start, $f_end).0)*
137                }
138            }
139
140            /// Returns `true` if it all the fields are set.
141            #[must_use]
142            $vis_custom const fn are_all_fields(self) -> bool {
143                self.bits == Self::with_all_fields().bits
144            }
145        }
146
147        $(
148            #[doc = "# `" $f "` single field operations"]
149            #[allow(dead_code)]
150            impl $name {
151                #[must_use]
152                #[doc = "Returns a new `" $name "` with [`" $f "`][Self::" $f "] field set."]
153                $vis_custom const fn [<with_field_ $f:lower>]() -> Self {
154                    Self::$f
155                }
156
157                #[must_use]
158                #[doc = "Whether the [`" $f "`][Self::" $f "] field is set."]
159                $vis_custom const fn [<is_field_ $f:lower>](self) -> bool {
160                    Self::contains_mask(self, Self::$f.bits)
161                }
162                #[must_use]
163                #[doc = "The size in bits of the [`" $f "`][Self::" $f "] field."]
164                $vis_custom const fn [<bits_field_ $f:lower>](self) -> u32 {
165                    $f_end - $f_start + 1
166                }
167
168                // get|set|mut_field
169                #[must_use]
170                #[doc = "A copy of `self` with only the bits of [`" $f "`][Self::" $f "] field."]
171                $vis_custom const fn [<get_field_ $f:lower>](self) -> Self {
172                    Self::intersect_mask(self, Self::$f.bits)
173                }
174                #[must_use]
175                #[doc = "A copy of `self` with the [`" $f "`][Self::" $f "] field set."]
176                $vis_custom const fn [<set_field_ $f:lower>](self) -> Self {
177                    Self::set_mask(self, Self::$f.bits)
178                }
179                #[doc = "Sets the [`" $f "`][Self::" $f "] field."]
180                $vis_custom fn [<mut_set_field_ $f:lower>](&mut self) {
181                    Self::mut_set_mask(self, Self::$f.bits);
182                }
183
184                // get|set_field_value
185                #[must_use]
186                #[doc = "The value at the bit range of [`" $f "`][Self::" $f "] field."]
187                $vis_custom const fn [<get_field_value_ $f:lower>](self) -> Self {
188                    Self::get_value_range(self, $f_start, $f_end)
189                }
190                #[doc = "Sets the `value` into the bitrange of [`" $f "`][Self::" $f "] field."]
191                $vis_custom const fn [<set_field_value_ $f:lower>](self, value: $T) -> Self {
192                    Self::set_value_range(self, value, $f_start, $f_end)
193                }
194
195                // [mut_]unset_field
196                #[must_use]
197                #[doc = "A copy of `self` with the [`" $f "`][Self::" $f "] field set."]
198                $vis_custom const fn [<unset_field_ $f:lower>](self) -> Self {
199                    Self::unset_mask(self, Self::$f.bits)
200                }
201                #[doc = "Unsets the [`" $f "`][Self::" $f "] field."]
202                $vis_custom fn [<mut_unset_field_ $f:lower>](&mut self) {
203                    Self::mut_unset_mask(self, Self::$f.bits);
204                }
205
206                /* flip */
207
208                #[must_use]
209                #[doc = "Returns a copy of `self` with the [`" $f "`][Self::" $f "] field flipped."]
210                $vis_custom const fn [<flip_field_ $f:lower>](self) -> Self {
211                    Self::flip_mask(self, Self::$f.bits)
212                }
213                #[doc = "Flips the [`" $f "`][Self::" $f "] field."]
214                $vis_custom fn [<mut_flip_field_ $f:lower>](&mut self) {
215                    Self::mut_flip_mask(self, Self::$f.bits);
216                }
217            }
218        )*
219
220        /// # General bits manipulation functionality
221        #[allow(dead_code)]
222        impl $name {
223            /// the maximum valid bit index.
224            $vis_extra const MAX_BIT: u32 = $T::BITS - 1;
225
226            /* constructors & deconstructors */
227
228            #[must_use] #[doc = "Returns self with the given inner `bits`."]
229            $vis_extra const fn with_bits(bits: $T) -> Self { Self { bits } }
230
231            #[must_use] /// Returns self with all bits set to 0.
232            $vis_extra const fn new_zeroed() -> Self { $name { bits: 0 } }
233            #[must_use] /// Returns self with all bits set to 1.
234            $vis_extra const fn new_oned() -> Self { Self::new_zeroed().flip() }
235            #[must_use] /// Returns the inner bits.
236            $vis_extra const fn bits(self) -> $T { self.bits }
237
238            #[must_use] /// The number of bits set (number of ones).
239            $vis_extra const fn count_ones(&self) -> u32 { self.bits.count_ones() }
240            #[must_use] /// The number of bits unset (number of zeros).
241            $vis_extra const fn count_zeros(&self) -> u32 { self.bits.count_zeros() }
242
243            #[must_use] /// Wether all bits are set to 0.
244            $vis_extra const fn is_empty(self) -> bool { self.bits == 0 }
245            #[must_use] /// Whether all bits are set to 1.
246            $vis_extra const fn is_full(self) -> bool { self.bits == Self::new_oned().bits }
247
248            /* get */
249
250            #[must_use] /// Whether the bit at `index` is set.
251            /// # Panics
252            /// Panics in debug if `index > MAX_BIT`.
253            $vis_extra const fn is_bit_set(self, index: u32) -> bool {
254                (self.bits & (1 << index)) != 0
255            }
256            /// Whether the bit at `index` is set, checked version.
257            /// # Errors
258            /// - If `index > MAX_BIT` Returns
259            ///
260            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
261            $vis_extra const fn is_checked_bit_set(self, index: u32)
262                -> $crate::Result<bool, $crate::MismatchedBounds> {
263                if let Some(shl) = [<1 $T>].checked_shl(index) {
264                    Ok((self.bits & shl) != 0)
265                } else {
266                    Err($crate::MismatchedBounds::IndexOutOfBounds(Some(index as usize)))
267                }
268            }
269            #[must_use]
270            /// Returns a copy of `self` with only the value of the bit at `index`.
271            /// # Panics
272            /// Panics in debug if `index > MAX_BIT`.
273            $vis_extra const fn get_bit(self, index: u32) -> Self {
274                Self { bits: self.bits & (1 << index) }
275            }
276
277            /// Returns a copy of `self` with only the value of the bit at `index`, checked.
278            /// # Errors
279            /// Returns [`IndexOutOfBounds`] if `index > MAX_BIT`.
280            ///
281            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
282            $vis_extra const fn get_checked_bit(self, index: u32)
283                -> $crate::Result<Self, $crate::MismatchedBounds> {
284                if let Some(shl) = [<1 $T>].checked_shl(index) {
285                    Ok(Self { bits: self.bits & shl })
286                } else {
287                    Err($crate::MismatchedBounds::IndexOutOfBounds(Some(index as usize)))
288                }
289            }
290
291            /// Returns a copy of `self` with only the value of the bit at `index` shifted.
292            /// # Panics
293            /// Panics in debug if `index > MAX_BIT`.
294            #[must_use]
295            $vis_extra const fn get_shifted_bit(self, index: u32) -> Self {
296                Self { bits: (self.bits >> index) & 1 }
297            }
298            /// Returns a copy of `self` with only the value of the bit at `index` shifted, checked.
299            /// # Errors
300            /// Returns [`IndexOutOfBounds`] if `index > MAX_BIT`.
301            ///
302            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
303            $vis_extra const fn get_shifted_checked_bit(self, index: u32)
304                -> $crate::Result<Self, $crate::MismatchedBounds> {
305                if let Some(shl) = self.bits.checked_shr(index) {
306                    Ok(Self { bits: shl & 1 })
307                } else {
308                    Err($crate::MismatchedBounds::IndexOutOfBounds(Some(index as usize)))
309                }
310            }
311
312            /* set*/
313
314            /// Returns a copy of `self` setting the bit at `index`.
315            ///
316            /// # Panics
317            /// Panics in debug if `index > MAX_BIT`.
318            #[must_use]
319            $vis_extra fn set_bit(self, index: u32) -> Self {
320                Self { bits: self.bits | 1 << index }
321            }
322            /// Returns a copy of `self` setting the bit at `index`, checked.
323            ///
324            /// # Errors
325            /// Returns [`IndexOutOfBounds`] if `index > MAX_BIT`.
326            ///
327            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
328            $vis_extra const fn set_checked_bit(self, index: u32)
329                -> $crate::Result<Self, $crate::MismatchedBounds> {
330                if let Some(shl) = [<1 $T>].checked_shl(index) {
331                    Ok(Self { bits: self.bits | shl })
332                } else {
333                    Err($crate::MismatchedBounds::IndexOutOfBounds(Some(index as usize)))
334                }
335            }
336
337            /// Sets the bit at `index`.
338            ///
339            /// # Panics
340            /// Panics in debug if `index > MAX_BIT`.
341            #[allow(arithmetic_overflow)]
342            $vis_extra fn mut_set_bit(&mut self, index: u32) {
343                self.bits |= 1 << index;
344            }
345            /// Sets the bit at `index`, checked.
346            ///
347            /// # Errors
348            /// Returns [`IndexOutOfBounds`] if `index > MAX_BIT`.
349            ///
350            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
351            $vis_extra fn mut_set_checked_bit(&mut self, index: u32)
352                -> $crate::Result<(), $crate::MismatchedBounds> {
353                if let Some(shl) = [<1 $T>].checked_shl(index) {
354                    self.bits |= shl;
355                    Ok(())
356                } else {
357                    Err($crate::MismatchedBounds::IndexOutOfBounds(Some(index as usize)))
358                }
359            }
360
361            /* unset */
362
363            /// Returns a copy of `self` setting the bit at `index`.
364            ///
365            /// # Panics
366            /// Panics in debug if `index > MAX_BIT`.
367            #[must_use]
368            $vis_extra fn unset_bit(self, index: u32) -> Self {
369                Self { bits: self.bits & !(1 << index) }
370            }
371            /// Returns a copy of `self` unsetting the bit at `index`, checked.
372            ///
373            /// # Errors
374            /// Returns [`IndexOutOfBounds`] if `index > MAX_BIT`.
375            ///
376            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
377            $vis_extra const fn unset_checked_bit(self, index: u32)
378                -> $crate::Result<Self, $crate::MismatchedBounds> {
379                if let Some(shl) = [<1 $T>].checked_shl(index) {
380                    Ok(Self { bits: self.bits & !shl })
381                } else {
382                    Err($crate::MismatchedBounds::IndexOutOfBounds(Some(index as usize)))
383                }
384            }
385
386            /// Unsets the bit at `index`.
387            ///
388            /// # Panics
389            /// Panics in debug if `index > MAX_BIT`.
390            $vis_extra fn mut_unset_bit(&mut self, index: u32) {
391                self.bits &= !(1 << index);
392            }
393            /// Unsets the bit at `index`, checked.
394            ///
395            /// # Errors
396            /// Returns [`IndexOutOfBounds`] if `index > MAX_BIT`.
397            ///
398            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
399            $vis_extra fn mut_unset_checked_bit(&mut self, index: u32)
400                -> $crate::Result<(), $crate::MismatchedBounds> {
401                if let Some(shl) = [<1 $T>].checked_shl(index) {
402                    self.bits &= !shl;
403                    Ok(())
404                } else {
405                    Err($crate::MismatchedBounds::IndexOutOfBounds(Some(index as usize)))
406                }
407            }
408
409            /* flip */
410
411            /// Returns a copy of `self` with all its bits flipped.
412            #[must_use]
413            $vis_extra const fn flip(self) -> Self {
414                Self { bits: !self.bits }
415            }
416            /// Flips all the bits of `self`.
417            $vis_extra fn mut_flip(&mut self) {
418                self.bits = !self.bits;
419            }
420
421            /// Returns a copy of `self` flipping the bit at `index`.
422            ///
423            /// # Panics
424            /// Panics in debug if `index > MAX_BIT`.
425            #[must_use]
426            $vis_extra fn flip_bit(self, index: u32) -> Self {
427                Self { bits: self.bits ^ 1 << index }
428            }
429            /// Returns a copy of `self` flipping the bit at `index`, checked.
430            ///
431            /// # Errors
432            /// Returns [`IndexOutOfBounds`] if `index > MAX_BIT`.
433            ///
434            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
435            $vis_extra const fn flip_checked_bit(self, index: u32)
436                -> $crate::Result<Self, $crate::MismatchedBounds> {
437                if let Some(shl) = [<1 $T>].checked_shl(index) {
438                    Ok(Self { bits: self.bits ^ shl })
439                } else {
440                    Err($crate::MismatchedBounds::IndexOutOfBounds(Some(index as usize)))
441                }
442            }
443
444            /// Flips the bit at `index`, unchecked version.
445            ///
446            /// # Panics
447            /// Panics in debug if `index > MAX_BIT`.
448            $vis_extra fn mut_flip_bit(&mut self, index: u32) {
449                self.bits ^= 1 << index;
450            }
451            /// Flips the bit at `index`, checked.
452            $vis_extra fn mut_flip_checked_bit(&mut self, index: u32)
453                -> $crate::Result<(), $crate::MismatchedBounds> {
454                if let Some(shl) = [<1 $T>].checked_shl(index) {
455                    self.bits ^= shl;
456                    Ok(())
457                } else {
458                    Err($crate::MismatchedBounds::IndexOutOfBounds(Some(index as usize)))
459                }
460            }
461        }
462
463        /// # Bit ranges
464        #[allow(dead_code)]
465        impl $name {
466            /* new mask */
467
468            /// Returns a new bitmask of 1s from the `[start..=end]` range.
469            ///
470            /// Sets the rest of the bits to 0.
471            ///
472            /// # Panics
473            /// Panics if `start >= BITS || end >= BITS || start > end`.
474            #[must_use]
475            $vis_extra const fn mask_range(start: u32, end: u32) -> Self {
476                Self { bits: $crate::Bitwise::<$T>::mask_range(start, end).0 }
477            }
478            /// Returns a new bitmask of ones from the `[start..=end]` checked range.
479            ///
480            /// Sets the rest of the bits to 0.
481            ///
482            /// # Errors
483            /// Returns [`IndexOutOfBounds`] if `start > MAX_BIT || end > MAX_BIT`,
484            /// or [`MismatchedIndices`] if `start > end`.
485            ///
486            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
487            /// [`MismatchedIndices`]: crate::MismatchedBounds::MismatchedIndices
488            $vis_extra const fn mask_checked_range(start: u32, end: u32)
489                -> $crate::Result<Self, $crate::MismatchedBounds> {
490                match $crate::Bitwise::<$T>::mask_checked_range(start, end) {
491                    Ok(bits) => Ok(Self { bits: bits.0 } ),
492                    Err(e) => Err(e),
493                }
494            }
495
496            /* get */
497
498            /// Gets a copy of `self` with only the bits from the `[start..=end]` range.
499            /// # Panics
500            /// Panics in debug if `start > MAX_BIT || end > MAX_BIT` or if `start > end`.
501            #[must_use]
502            $vis_extra const fn get_range(self, start: u32, end: u32) -> Self {
503                Self { bits: $crate::Bitwise(self.bits).get_range(start, end).0 }
504            }
505            /// Gets a copy of `self` with only the bits from the `[start..=end]` checked range.
506            /// # Errors
507            /// Returns [`IndexOutOfBounds`] if `start > MAX_BIT || end > MAX_BIT`,
508            /// or [`MismatchedIndices`] if `start > end`.
509            ///
510            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
511            /// [`MismatchedIndices`]: crate::MismatchedBounds::MismatchedIndices
512            $vis_extra const fn get_checked_range(self, start: u32, end: u32)
513                -> $crate::Result<Self, $crate::MismatchedBounds> {
514                match $crate::Bitwise(self.bits).get_checked_range(start, end) {
515                    Ok(bits) => Ok(Self { bits: bits.0 } ),
516                    Err(e) => Err(e),
517                }
518            }
519
520            /* get value */
521
522            /// Gets the value of the bits in from the `[start..=end]` range.
523            ///
524            /// # Panics
525            /// Panics if `start >= BITS || end >= BITS || start > end`.
526            #[must_use]
527            $vis_extra const fn get_value_range(self, start: u32, end: u32) -> Self {
528                Self { bits: $crate::Bitwise(self.bits).get_value_range(start, end).0 }
529            }
530
531            /// Gets the value of the bits from the `[start..=end]` checked range.
532            ///
533            /// Sets the rest of the bits to 0.
534            ///
535            /// The bits in the specified range are shifted rightwards so that the least
536            /// significant bit (LSB) aligns with the units place, forming the integer value.
537            /// # Errors
538            /// Returns [`IndexOutOfBounds`] if `start >= BITS || end >= BITS`,
539            /// [`MismatchedIndices`] if `start > end`, and
540            /// [`DataOverflow`] if `value` does not fit within the specified bit range.
541            ///
542            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
543            /// [`MismatchedIndices`]: crate::MismatchedBounds::MismatchedIndices
544            /// [`DataOverflow`]: crate::MismatchedBounds::DataOverflow
545            $vis_extra const fn get_value_checked_range(self, start: u32, end: u32)
546                -> $crate::Result<Self, $crate::MismatchedBounds> {
547                match $crate::Bitwise(self.bits).get_value_checked_range(start, end) {
548                    Ok(bits) => Ok(Self { bits: bits.0 } ),
549                    Err(e) => Err(e),
550                }
551            }
552
553            /* set */
554
555            /// Get a copy of `self` with bits set to 1 from the `[start..=end]` range.
556            ///
557            /// # Panics
558            /// Panics in debug if `start > MAX_BIT || end > MAX_BIT` or if `start > end`.
559            #[must_use]
560            $vis_extra const fn set_range(self, start: u32, end: u32) -> Self {
561                Self { bits: $crate::Bitwise(self.bits).set_range(start, end).0 }
562            }
563            /// Get a copy of `self` with bits set to 1 from the `[start..=end]` checked range.
564            /// # Errors
565            /// Returns [`IndexOutOfBounds`] if `start > MAX_BIT || end > MAX_BIT`,
566            /// or [`MismatchedIndices`] if `start > end`.
567            ///
568            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
569            /// [`MismatchedIndices`]: crate::MismatchedBounds::MismatchedIndices
570            $vis_extra const fn set_checked_range(self, start: u32, end: u32)
571                -> $crate::Result<Self, $crate::MismatchedBounds> {
572                match $crate::Bitwise(self.bits).set_checked_range(start, end) {
573                    Ok(bits) => Ok(Self { bits: bits.0 } ),
574                    Err(e) => Err(e),
575                }
576            }
577
578            /// Sets the bits from the `[start..=end]` range.
579            /// # Panics
580            /// Panics in debug if `start > MAX_BIT || end > MAX_BIT` or if `start > end`.
581            $vis_extra fn mut_set_range(&mut self, start: u32, end: u32) {
582                self.bits = $crate::Bitwise(self.bits).set_range(start, end).0;
583            }
584            /// Sets the bits from the `[start..=end]` checked range.
585            /// # Errors
586            /// Returns [`IndexOutOfBounds`] if `start > MAX_BIT || end > MAX_BIT`,
587            /// or [`MismatchedIndices`] if `start > end`.
588            ///
589            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
590            /// [`MismatchedIndices`]: crate::MismatchedBounds::MismatchedIndices
591            $vis_extra fn mut_set_checked_range(&mut self, start: u32, end: u32)
592                -> $crate::Result<(), $crate::MismatchedBounds> {
593                match $crate::Bitwise(self.bits).set_checked_range(start, end) {
594                    Ok(bits) => { self.bits = bits.0; Ok(()) },
595                    Err(e) => Err(e),
596                }
597            }
598
599            /* set value */
600
601            /// Gets a copy of `self` with the given `value` set into the `[start..=end]` range.
602            ///
603            /// Leaves the rest of the bits unchanged.
604            ///
605            /// The value is first masked to fit the size of the range, and then
606            /// it is inserted into the specified bit range of `self`, replacing
607            /// the existing bits in that range. The rest of the bits in `self` remain unchanged.
608            /// # Panics
609            /// Panics if `start >= BITS || end >= BITS || start > end`.
610            #[must_use]
611            $vis_extra const fn set_value_range(self, value: $T, start: u32, end: u32) -> Self {
612                Self { bits: $crate::Bitwise(self.bits).set_value_range(value, start, end).0 }
613            }
614
615            /// Gets a copy of `self` with the given `value` set into the `[start..=end]`
616            /// checked range.
617            ///
618            /// Leaves the rest of the bits unchanged.
619            /// # Errors
620            /// Returns [`IndexOutOfBounds`] if `start >= BITS || end >= BITS`
621            /// and [`MismatchedIndices`] if `start > end`.
622            ///
623            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
624            /// [`MismatchedIndices`]: crate::MismatchedBounds::MismatchedIndices
625            $vis_extra const fn set_value_checked_range(self, value: $T, start: u32, end: u32)
626                -> $crate::Result<Self, $crate::MismatchedBounds> {
627                match $crate::Bitwise(self.bits).set_value_checked_range(value, start, end) {
628                    Ok(bits) => Ok(Self { bits: bits.0 } ),
629                    Err(e) => Err(e),
630                }
631            }
632
633            /// Gets a copy of `self` with the given checked `value` set into the `[start..=end]`
634            /// checked range.
635            ///
636            /// Leaves the rest of the bits unchanged.
637            /// # Errors
638            /// Returns [`IndexOutOfBounds`] if `start >= BITS || end >= BITS`,
639            /// [`MismatchedIndices`] if `start > end`, and
640            /// [`DataOverflow`] if `value` does not fit within the specified bit range.
641            ///
642            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
643            /// [`MismatchedIndices`]: crate::MismatchedBounds::MismatchedIndices
644            /// [`DataOverflow`]: crate::MismatchedBounds::DataOverflow
645            $vis_extra const fn set_checked_value_checked_range(self,
646                value: $T, start: u32, end: u32) -> $crate::Result<Self, $crate::MismatchedBounds> {
647                match $crate::Bitwise(self.bits)
648                    .set_checked_value_checked_range(value, start, end) {
649                    Ok(bits) => Ok(Self { bits: bits.0 } ),
650                    Err(e) => Err(e),
651                }
652            }
653
654            /// Sets the given `value` into the `[start..=end]` range.
655            /// Sets the bits from the `[start..=end]` range.
656            /// # Panics
657            /// Panics in debug if `start > MAX_BIT || end > MAX_BIT` or if `start > end`.
658            $vis_extra fn mut_set_value_range(&mut self, value: $T, start: u32, end: u32) {
659                self.bits = $crate::Bitwise(self.bits).set_value_range(value, start, end).0;
660            }
661            /// Sets the given `value` into the `[start..=end]` checked range.
662            /// # Errors
663            /// Returns [`IndexOutOfBounds`] if `start > MAX_BIT || end > MAX_BIT` and
664            /// [`MismatchedIndices`] if `start > end`.
665            ///
666            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
667            /// [`MismatchedIndices`]: crate::MismatchedBounds::MismatchedIndices
668            $vis_extra fn mut_set_value_checked_range(&mut self,
669                value: $T, start: u32, end: u32) -> $crate::Result<(), $crate::MismatchedBounds> {
670                match $crate::Bitwise(self.bits).set_value_checked_range(value, start, end) {
671                    Ok(bits) => { self.bits = bits.0; Ok(()) },
672                    Err(e) => Err(e),
673                }
674            }
675            /// Sets the given checked `value` into the `[start..=end]` checked range.
676            /// # Errors
677            /// Returns [`IndexOutOfBounds`] if `start > MAX_BIT || end > MAX_BIT`,
678            /// [`MismatchedIndices`] if `start > end`, and
679            /// [`DataOverflow`] if `value` does not fit within the specified bit range.
680            ///
681            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
682            /// [`MismatchedIndices`]: crate::MismatchedBounds::MismatchedIndices
683            /// [`DataOverflow`]: crate::MismatchedBounds::DataOverflow
684            $vis_extra fn mut_set_checked_value_checked_range(&mut self,
685                value: $T, start: u32, end: u32) -> $crate::Result<(), $crate::MismatchedBounds> {
686                match $crate::Bitwise(self.bits)
687                    .set_checked_value_checked_range(value, start, end) {
688                    Ok(bits) => { self.bits = bits.0; Ok(()) },
689                    Err(e) => Err(e),
690                }
691            }
692
693            /* unset */
694
695            /// Returns a copy of `self` with unset bits to 0 from the `[start..=end]` range.
696            /// # Panics
697            /// Panics in debug if `start > MAX_BIT || end > MAX_BIT` or if `start > end`.
698            #[must_use]
699            $vis_extra const fn unset_range(self, start: u32, end: u32) -> Self {
700                Self { bits: $crate::Bitwise(self.bits).unset_range(start, end).0 }
701            }
702            /// Returns a copy of `self` with unset bits to 0 from the `[start..=end]`
703            /// checked range.
704            /// # Errors
705            /// Returns [`IndexOutOfBounds`] if `start > MAX_BIT || end > MAX_BIT`,
706            /// or [`MismatchedIndices`] if `start > end`.
707            ///
708            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
709            /// [`MismatchedIndices`]: crate::MismatchedBounds::MismatchedIndices
710            $vis_extra const fn unset_checked_range(self, start: u32, end: u32)
711                -> $crate::Result<Self, $crate::MismatchedBounds> {
712                match $crate::Bitwise(self.bits).unset_checked_range(start, end) {
713                    Ok(bits) => Ok(Self { bits: bits.0 } ),
714                    Err(e) => Err(e),
715                }
716            }
717
718            /// Unsets the bits from the `[start..=end]` range.
719            /// # Panics
720            /// Panics in debug if `start > MAX_BIT || end > MAX_BIT` or if `start > end`.
721            $vis_extra fn mut_unset_range(&mut self, start: u32, end: u32) {
722                self.bits = $crate::Bitwise(self.bits).unset_range(start, end).0;
723            }
724            /// Unsets the bits from the `[start..=end]` checked range.
725            /// # Errors
726            /// Returns [`IndexOutOfBounds`] if `start > MAX_BIT || end > MAX_BIT`,
727            /// or [`MismatchedIndices`] if `start > end`.
728            ///
729            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
730            /// [`MismatchedIndices`]: crate::MismatchedBounds::MismatchedIndices
731            $vis_extra fn mut_unset_checked_range(&mut self, start: u32, end: u32)
732                -> $crate::Result<(), $crate::MismatchedBounds> {
733                match $crate::Bitwise(self.bits).unset_checked_range(start, end) {
734                    Ok(bits) => { self.bits = bits.0; Ok(()) },
735                    Err(e) => Err(e),
736                }
737            }
738
739            /* flip */
740
741            /// Returns a copy of `self` with flipped bits from the `[start..=end]` range.
742            /// # Panics
743            /// Panics in debug if `start > MAX_BIT || end > MAX_BIT` or if `start > end`.
744            #[must_use]
745            $vis_extra const fn flip_range(self, start: u32, end: u32) -> Self {
746                Self { bits: $crate::Bitwise(self.bits).flip_range(start, end).0 }
747            }
748            /// Returns a copy of `self` with flipped bits from the `[start..=end]` checked range.
749            /// # Errors
750            /// Returns [`IndexOutOfBounds`] if `start > MAX_BIT || end > MAX_BIT`,
751            /// or [`MismatchedIndices`] if `start > end`.
752            ///
753            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
754            /// [`MismatchedIndices`]: crate::MismatchedBounds::MismatchedIndices
755            $vis_extra const fn flip_checked_range(self, start: u32, end: u32)
756                -> $crate::Result<Self, $crate::MismatchedBounds> {
757                match $crate::Bitwise(self.bits).flip_checked_range(start, end) {
758                    Ok(bits) => Ok(Self { bits: bits.0 } ),
759                    Err(e) => Err(e),
760                }
761            }
762
763            /// Flips the bits from the `[start..=end]` range.
764            /// # Panics
765            /// Panics in debug if `start > MAX_BIT || end > MAX_BIT` or if `start > end`.
766            $vis_extra fn mut_flip_range(&mut self, start: u32, end: u32) {
767                self.bits = $crate::Bitwise(self.bits).flip_range(start, end).0;
768            }
769            /// Flips the bits from the `[start..=end]` checked range.
770            /// # Errors
771            /// Returns [`IndexOutOfBounds`] if `start > MAX_BIT || end > MAX_BIT`,
772            /// or [`MismatchedIndices`] if `start > end`.
773            ///
774            /// [`IndexOutOfBounds`]: crate::MismatchedBounds::IndexOutOfBounds
775            /// [`MismatchedIndices`]: crate::MismatchedBounds::MismatchedIndices
776            $vis_extra fn mut_flip_checked_range(&mut self, start: u32, end: u32)
777                -> $crate::Result<(), $crate::MismatchedBounds> {
778                match $crate::Bitwise(self.bits).flip_checked_range(start, end) {
779                    Ok(bits) => { self.bits = bits.0; Ok(()) },
780                    Err(e) => Err(e),
781                }
782            }
783        }
784
785        /// # Bit masks
786        #[allow(dead_code)]
787        impl $name {
788            #[must_use]
789            /// Whether `self` contains all the same set bits that are set in `mask`.
790            $vis_extra const fn contains_mask(self, mask: $T) -> bool {
791                (self.bits & mask) == mask }
792            #[must_use]
793            /// Whether `self` contains all the same set bits that are set in `other`.
794            $vis_extra const fn contains_other(self, other: Self) -> bool {
795                (self.bits & other.bits) == other.bits }
796
797            #[must_use]
798            /// Whether there's at least one set bit in common between `self` and `mask`.
799            $vis_extra const fn overlaps_mask(&self, mask: $T) -> bool {
800                (self.bits & mask) != 0 }
801            #[must_use]
802            /// Whether there's at least one set bit in common between `self` and `other`.
803            $vis_extra const fn overlaps_other(&self, other: Self) -> bool {
804                (self.bits & other.bits) != 0 }
805
806            /* intersect */
807
808            // [mut]_ intersect _[mask|other]
809            #[must_use] /// A copy of `self` with only the bits both in `self` and `mask`.
810            $vis_extra const fn intersect_mask(self, mask: $T) -> Self {
811                Self { bits: self.bits & mask } }
812            #[must_use] /// A copy of `self` with only the bits both in `self` and `other`.
813            $vis_extra const fn intersect_other(self, other: Self) -> Self {
814                Self { bits: self.bits & other.bits } }
815            /// Only leaves the bits both in `self` and `mask`.
816            $vis_extra fn mut_intersect_mask(&mut self, mask: $T) { self.bits &= mask; }
817            /// Only leaves the bits both in `self` and `other`.
818            $vis_extra fn mut_intersect_other(&mut self, other: Self) { self.bits &= other.bits; }
819
820            // [mut]_ set _[mask|other]
821            #[must_use] /// A copy of `self` setting the bits that are set in `mask`.
822            $vis_extra const fn set_mask(self, mask: $T) -> Self {
823                Self { bits: self.bits | mask } }
824            #[must_use] /// A copy of `self` setting the bits that are set in `other`.
825            $vis_extra const fn set_other(self, other: Self) -> Self {
826                Self { bits: self.bits | other.bits } }
827            /// Sets the bits that are set in `mask`.
828            $vis_extra fn mut_set_mask(&mut self, mask: $T) { self.bits |= mask; }
829            /// Sets the bits that are set in `other`.
830            $vis_extra fn mut_set_other(&mut self, other: Self) { self.bits |= other.bits; }
831
832            /* unset */
833
834            #[must_use] /// A copy of `self` unsetting the bits that are set in `mask`.
835            $vis_extra const fn unset_mask(self, mask: $T) -> Self {
836                Self { bits: self.bits & !mask }
837            }
838            #[must_use] /// A copy of `self` unsetting the bits that are set in `other`.
839            $vis_extra const fn unset_other(self, other: Self) -> Self {
840                Self { bits: self.bits & !other.bits }
841            }
842            /// Unsets the bits that are set in `mask`.
843            $vis_extra fn mut_unset_mask(&mut self, mask: $T) {
844                self.bits &= !mask; }
845            /// Unsets the bits that are set in `other`.
846            $vis_extra fn mut_unset_other(&mut self, other: Self) {
847                self.bits &= !other.bits; }
848
849            /* flip */
850
851            /// A copy of `self` flipping the bits that are set in `mask`.
852            #[must_use]
853            $vis_extra const fn flip_mask(self, mask: $T) -> Self {
854                Self { bits: self.bits ^ mask }
855            }
856            /// Returns a copy of `self` flipping the bits that are set in `other`.
857            #[must_use]
858            $vis_extra const fn flip_other(self, other: Self) -> Self {
859                Self { bits: self.bits ^ other.bits }
860            }
861            /// Flips the bits that are set in `mask`.
862            $vis_extra fn mut_flip_mask(&mut self, mask: $T) {
863                self.bits ^= mask;
864            }
865            /// Flips the bits that are set in `other`.
866            $vis_extra fn mut_flip_other(&mut self, other: Self) {
867                self.bits ^= other.bits;
868            }
869        }
870    }};
871    // TODO: improve make more choices, combinable, show a set of menus
872    {
873        /* optional syntax */
874
875        (custom:$vis_custom:vis, extra:$vis_extra:vis $(,)?) // optional trailing comma
876        $(#[$struct_attributes:meta])*
877        $vis:vis struct $name:ident($T:ty) {
878            $(
879                $(#[$f_attrs:meta])*
880                $f:ident: $f_start:expr $(,$f_end:expr)?; // NAME: bit;
881            )*
882        }
883    } => {
884        $crate::bitfield! {
885            (custom: $vis_custom, extra: $vis_extra)
886            $( #[$struct_attributes] )*
887            $vis struct $name($T) {
888                $(
889                    $( #[$f_attrs] )*
890                    $f: $f_start, $crate::coalesce![$($f_end)?, $f_start];
891                )*
892            }
893        }
894    };
895
896    { (custom) // only public custom fields
897        $($tt:tt)+ } => { $crate::bitfield![ (custom:pub, extra:pub(crate)) $($tt)+ ]; };
898    { (extra) // only public extra methods
899        $($tt:tt)+ } => { $crate::bitfield![ (custom:pub(crate), extra:pub) $($tt)+ ]; };
900    { // everything public
901        $($tt:tt)+ } => { $crate::bitfield![ (custom:pub, extra:pub) $($tt)+ ]; };
902}
903#[doc(inline)]
904#[cfg_attr(feature = "nightly_doc", doc(cfg(_bit··)))]
905pub use _bitfield as bitfield; // see crate::code::utils::mod.rs
906
907/* utility macros */
908
909// TODO
910// which type of argument?
911// /// Generate the intra-doc link of a enum variants in a separate line
912// macro_rules doc_enum_links! {
913//     ($enum_path:path, $($variant_name:ident),+) => { paste! {
914//         $( doc_enum_links![@$enum_path, $variant]; )+
915//     }};
916//     (@$enum_path:path, $variant_name:ident) => { paste! {
917//         #[doc = "[`" $variant_name " `]: " $enum_path "::" $variant_naem]
918//     }};
919//     // TODO: give multiple
920// }
921// use _doc;