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;