tartan_bitfield/
lib.rs

1//! This crate can be used to define structures with accessors for particular bits or
2//! bit ranges. Useful for dealing with registers and protocols.
3//!
4//! # Features
5//!
6//!   * **Performance**: Generated code is nearly identical to hand-rolled bit twiddling.
7//!   * **Safety**: Absolutely no unsafe code in the implementation or usage.
8//!   * **Portability**:
9//!     * `#![no_std]`-compatible out of the box.
10//!     * Unlike bit fields in C, the layout is predictable. See the section about
11//!       endianness below.
12//!     * Unlike Rust's `#[repr(packed, C)]`, each field has explicit bit ranges, rather
13//!       than relying on the ordering and size of other fields within the struct. While
14//!       specifying bit numbers may seem tedious, it can eliminate surprises, and it
15//!       usually corresponds directly to the way registers and protocols are defined in
16//!       datasheets.
17//!   * **Convenience**:
18//!     * Single-bit flags and multi-bit fields can be defined in the same structure.
19//!     * Bit ranges can be accessed as non-primitive, non-integer types (including other
20//!       bitfield structs) using appropriate [`Into`] and [`From`] implementations.
21//!     * The structs implement all the traits you would expect. See the documentation
22//!       for [`bitfield`]. A [`bitfield_without_debug`] macro is also available if you
23//!       want to provide your own debugging output.
24//!     * Accessors can be defined in a trait, which is useful for registers where where
25//!       some fields are common, but others are only defined in certain states. See
26//!       [`bitfield_accessors`].
27//!
28//! # Example
29//!
30//! ```
31//! # use tartan_bitfield::bitfield;
32//! bitfield! {
33//!     // The structure will be a wrapper for a u32 value.
34//!     pub struct Example(u32) {
35//!         // Accessors for field `a` will refer to the first four least significant
36//!         // bits of the wrapped value, bits 0, 1, 2, and 3.
37//!         //
38//!         // Note that like normal Rust ranges:
39//!         //   * `[0..4]` does not include bit 4
40//!         //   * `[0..=4]` includes bit 4
41//!         //
42//!         // The accessors will be public, and will take/return the four bits as a `u8`.
43//!         [0..4] pub a: u8,
44//!
45//!         // No accessors cover bits `4..6`. This is legal and can be used for reserved
46//!         // bits. However, these bits will still affect equality for the struct as a
47//!         // whole.
48//!
49//!         // Accessors for field `b` will refer to the twelve bits starting at bit 6,
50//!         // but they will not be public. They will take/return the 12 bits as a `u16`.
51//!         [6..=17] b: u16,
52//!
53//!         // Note that this bit range overlaps with `b`. This is allowed.
54//!         [16..20] pub c: u8,
55//!
56//!         // Accessors for field `d` will take/return a boolean and refer to a single
57//!         // bit. Note that the `bool` is implied and not specified after the name.
58//!         [25] pub d,
59//!
60//!         // This will cover the 6 most significant bits of the wrapped value, but
61//!         // the getters will take/return a `SubFields` struct instead of `u8`. This is
62//!         // useful for nested bitfields, but the `A as B` syntax works for any `B`
63//!         // which implements `Into<A>` and `From<A>`.
64//!         [26..32] pub e: u8 as SubFields,
65//!     }
66//! }
67//!
68//! bitfield! {
69//!     // All accessors on this field use booleans and refer to single bits
70//!     pub struct SubFields(u8) {
71//!         [0] pub zero,
72//!         [1] pub one,
73//!         [2] pub two,
74//!         [3] pub three,
75//!         [4] pub four,
76//!         [5] pub five,
77//!     }
78//! }
79//!
80//!
81//! // The struct can be initialized with a u32 value
82//! let x = Example(0xfa84_9e1b);
83//! assert_eq!(x.a(), 0xb_u8);
84//! assert_eq!(x.b(), 0x278_u16);  // Private, but still can be used within the module
85//! assert_eq!(x.c(), 0x4_u8);
86//! assert_eq!(x.d(), true);
87//! assert_eq!(x.e(), SubFields(0x3e_u8));
88//! assert_eq!(x.e().zero(), false);
89//! assert_eq!(x.e().five(), true);
90//!
91//! // It can also be converted Into and From its underlying representation
92//! let n: u32 = x.into();
93//! let y: Example = n.into();
94//! assert_eq!(n, 0xfa84_9e1b);
95//! assert_eq!(x, y);
96//!
97//! // Setters are all prefixed with `set_`. They have the same visibility as the getters.
98//! let mut z = Example::default();
99//! z.set_a(0xb);
100//! z.set_b(0x278);
101//! z.set_c(0x4);
102//! z.set_d(true);
103//! z.set_e(SubFields(0x3e));
104//! assert_eq!(z, Example(0xfa04_9e0b));
105//!
106//! // Reserved ranges influence equality, and they are all zero on `z`.
107//! assert_ne!(z, x);
108//!
109//! // Alternatively, you can use the `with_` methods, which return a new value instead
110//! // of mutating in place.
111//! let mut w = x
112//!     .with_a(0x6)
113//!     .with_b(0x9f3)
114//!     .with_c(0xd)
115//!     .with_d(false)
116//!     .with_e(SubFields(0x2b));
117//! assert_eq!(w, Example(0xac8d_7cd6));
118//! assert_eq!(x, Example(0xfa84_9e1b));
119//! ```
120//!
121//! For lots more examples, see the [Tartan OS](https://github.com/cimbul/tartan-os)
122//! project that this crate was spun off from.
123//!
124//! # Endiannness and Bit Numbering
125//!
126//! Each bitfield wraps an underlying integer type. In the example above, `Example(u32)`
127//! wraps a `u32`. Bit numbers within the macro refer to the bits of the logical _value_,
128//! starting from the least significant bit = 0. They are not dependent on the order of
129//! the bytes of the `u32` representation in memory, a.k.a. endianness.
130//!
131//! The endianness of the underlying value is platform dependent. This is no different
132//! than any other integer value, and the context determines whether you need to worry
133//! about it.
134//!   * If the underlying representation is a `u8`, then byte order is irrelevant.
135//!   * If you are reading from a register, it's likely you want native byte order and
136//!     don't need to do anything special.
137//!   * If you are working with a network or bus protocol, it's likely you are serializing
138//!     or deserializing from a byte array. To convert using a specific endianness
139//!     regardless of platform, use the normal methods: for example, the builtins
140//!     [`u32::from_be_bytes`] and [`u64::to_le_bytes`], or a crate like
141//!     [byteorder](https://docs.rs/byteorder/latest/byteorder/).
142//!
143//! # Alternatives
144//!
145//! I have been using this in my personal OS project for a while, and it meets my needs
146//! better than other options. But you may be interested in a few other crates:
147//!   * [bitfield](https://github.com/dzamlo/rust-bitfield): Similar approach for
148//!     accessors and bit ranges, but a less obvious syntax.
149//!   * [bitflags](https://docs.rs/bitflags/latest/bitflags/): Works well for single-bit
150//!     flags that can be viewed as a collection.
151//!   * [bitvec](https://docs.rs/bitvec/latest/bitvec/): Another collection type to view
152//!     memory as a sequence of bits. Less focused on defining domain-specific structs.
153//!   * [modular-bitfield](https://docs.rs/modular-bitfield/latest/modular_bitfield/):
154//!     Field ordering and widths determine bit ranges. Structs can only be converted to
155//!     byte arrays, and only in little-endian order, regardless of platform endianness.
156//!     This can be undesirable when working with registers.
157//!   * [packed_struct](https://docs.rs/packed_struct/0.10.0/packed_struct/): Lots of
158//!     options, including bit numbering and endianness conversions. Structs are held
159//!     in unpacked form in memory, and only converted to packed form for serialization.
160//!     Depending on your access patterns, this may be better or worse (or it may not
161//!     matter at all).
162//!       * For an analogue to `pack_struct`'s `PrimitiveEnum`, see the
163//!         [`tartan-c-enum`](https://github.com/cimbul/tartan-c-enum) crate.
164
165#![no_std]
166#![warn(missing_docs)]
167#![warn(clippy::pedantic)]
168#![allow(clippy::doc_markdown)]
169#![allow(clippy::inline_always)]
170#![allow(clippy::must_use_candidate)]
171#![allow(clippy::similar_names)]
172#![allow(clippy::upper_case_acronyms)]
173
174use core::convert::From;
175use core::default::Default;
176use core::ops;
177
178// Must be re-exported so that crates that use these macros will be able to resolve it
179#[doc(hidden)]
180pub use paste::paste;
181
182/// Marker trait implemented by types defined with the [`bitfield`] macro.
183///
184/// This mainly exists to allow type inference in the [`bitfield_accessors`] macro, but it
185/// also aids documentation and may be useful in user code.
186pub trait Bitfield<T>
187where
188    Self: core::fmt::Debug + Default + Copy + Eq + From<T> + Into<T>,
189{
190    /// Construct a new bitfield type from its underlying representation
191    #[inline(always)]
192    fn new(value: T) -> Self {
193        value.into()
194    }
195
196    /// Unwrap the bitfield into its underlying representation
197    #[inline(always)]
198    fn value(self) -> T {
199        self.into()
200    }
201}
202
203/// Define a structure that wraps a number with accessors for certain bit ranges.
204///
205/// See the crate documentation for an example.
206///
207/// The structure will implement these traits, where `T` is the underlying type defined
208/// in parentheses immediately after the struct name.
209///   * [`Bitfield<T>`](Bitfield)
210///   * [`Debug`]
211///   * [`Default`]
212///   * [`Copy`]
213///   * [`Eq`]
214///   * [`Into<T>`](Into)
215///   * [`From<T>`](From)
216#[macro_export]
217macro_rules! bitfield {
218    [
219        $( #[$meta:meta] )*
220        $vis:vis struct $struct:ident($underlying_type:ty) {
221            $($body:tt)*
222        }
223    ] => {
224        $crate::bitfield_without_debug! {
225            $(#[$meta])*
226            $vis struct $struct($underlying_type) {
227                $($body)*
228            }
229        }
230
231        impl ::core::fmt::Debug for $struct {
232            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
233                let mut struct_out = f.debug_struct(stringify!($struct));
234                struct_out.field("<value>", &self.0);
235                self.fmt_fields(&mut struct_out);
236                struct_out.finish()
237            }
238        }
239    }
240}
241
242/// Same as the [`bitfield`] macro without a [`Debug`] implementation provided.
243///
244/// Since Debug is required by the [`Bitfield`] trait, the caller must provide their own
245/// implementation.
246#[macro_export]
247macro_rules! bitfield_without_debug {
248    [
249        $( #[$meta:meta] )*
250        $vis:vis struct $struct:ident($underlying_type:ty) {
251            $($body:tt)*
252        }
253    ] => {
254        $( #[$meta] )*
255        #[repr(transparent)]
256        #[derive(Default, Clone, Copy, PartialEq, Eq)]
257        $vis struct $struct($underlying_type);
258
259        impl $struct {
260            $crate::bitfield_accessors! { $($body)* }
261        }
262
263        impl $crate::Bitfield<$underlying_type> for $struct {}
264
265        impl ::core::convert::From<$underlying_type> for $struct {
266            #[inline(always)]
267            fn from(val: $underlying_type) -> Self { Self(val) }
268        }
269
270        impl ::core::convert::From<$struct> for $underlying_type {
271            #[inline(always)]
272            fn from(val: $struct) -> Self { val.0 }
273        }
274    };
275}
276
277/// Define getters and setters for certain bit ranges. The containing type must
278/// implement the [`Bitfield`] trait.
279///
280/// This is most commonly invoked by the [`bitfield`] macro, but it can be used on its own
281/// to define common accessors as part of a trait, as in the example below:
282///
283/// ```
284/// # use tartan_bitfield::{Bitfield, bitfield, bitfield_accessors};
285/// #
286/// trait CommonFields: Bitfield<u32> {
287///     bitfield_accessors! {
288///         // Since these are part of a trait, the `pub` keyword must be omitted.
289///         [ 0.. 6] a: u8,
290///         [14]     b,
291///         [18..32] c: u16,
292///     }
293/// }
294///
295/// bitfield! {
296///     struct SomeFields(u32) {
297///         [ 7] pub x,
298///         [16] pub y,
299///     }
300/// }
301///
302/// bitfield! {
303///     struct OtherFields(u32) {
304///         [10] pub z,
305///         [12] pub q,
306///     }
307/// }
308///
309/// impl CommonFields for SomeFields {}
310/// impl CommonFields for OtherFields {}
311///
312/// let f = SomeFields(0xabcd_1234);
313/// assert_eq!(f.a(), 0x34); // has accessors from CommonFields
314/// assert_eq!(f.y(), true); // has accessors from SomeFields
315/// //assert_eq!(f.z(), false); // COMPILE ERROR: no accessors from OtherFields
316///
317/// let g = OtherFields(0xabcd_1234);
318/// assert_eq!(g.a(), 0x34); // has accessors from CommonFields
319/// //assert_eq!(g.y(), true); // COMPILE ERROR: no accessors from SomeFields
320/// assert_eq!(g.z(), false); // has accessors from OtherFields
321/// ```
322#[macro_export]
323macro_rules! bitfield_accessors {
324    [
325        $(
326            $( #[$meta:meta] )*
327            [ $( $range:tt )* ]
328            $vis:vis $field:ident
329            $( : $underlying_type:ty $( as $interface_type:ty )? )?
330        ),*
331        $(,)?
332    ] => {
333        $(
334            $crate::bitfield_accessors! {
335                @field getter
336                $( #[$meta] )*
337                [ $( $range )* ]
338                $vis $field
339                $( : $underlying_type $( as $interface_type )? )?
340            }
341        )*
342
343        $(
344            $crate::bitfield_accessors! {
345                @field setter
346                $( #[$meta] )*
347                [ $( $range )* ]
348                $vis $field
349                $( : $underlying_type $( as $interface_type )? )?
350            }
351        )*
352
353        /// Print this object's bitfield values. Helper method for `Debug`
354        /// implementations.
355        fn fmt_fields(&self, f: &mut ::core::fmt::DebugStruct) {
356            $(
357                $(#[$meta])*
358                f.field(stringify!($field), &self.$field());
359            )*
360        }
361    };
362
363    // Special case for single-bit boolean fields
364    [
365        @field getter
366        $( #[$meta:meta] )*
367        [ $bit:literal ]
368        $vis:vis $field:ident
369    ] => {
370        $crate::paste! {
371            $( #[$meta] )*
372            $vis fn $field(&self) -> bool {
373                $crate::get_bit(<Self as $crate::Bitfield<_>>::value(*self), $bit)
374            }
375        }
376    };
377
378    // Special case for single-bit boolean fields
379    [
380        @field setter
381        $( #[$meta:meta] )*
382        [ $bit:literal ]
383        $vis:vis $field:ident
384    ] => {
385        $crate::paste! {
386            $( #[$meta] )*
387            #[inline(always)]
388            $vis fn [< set_ $field >](&mut self, value: bool) {
389                *self = self.[< with_ $field >](value);
390            }
391
392            $( #[$meta] )*
393            $vis fn [< with_ $field >](&mut self, value: bool) -> Self {
394                let packed = <Self as $crate::Bitfield<_>>::value(*self);
395                <Self as $crate::Bitfield<_>>::new(
396                    $crate::set_bit(packed, $bit, value))
397            }
398        }
399    };
400
401    // A field type and both range bounds are required in all other cases.
402    // When no explicit interface type is given, use the underlying type.
403    [
404        @field $accessor_type:tt
405        $( #[$meta:meta] )*
406        [ $lsb:literal .. $msb:literal ]
407        $vis:vis $field:ident
408        : $field_type:ty
409    ] => {
410        $crate::bitfield_accessors! {
411            @field $accessor_type
412            $( #[$meta] )*
413            [$lsb..$msb] $vis $field: $field_type as $field_type
414        }
415    };
416
417    [
418        @field $accessor_type:tt
419        $( #[$meta:meta] )*
420        [ $lsb:literal ..= $msb:literal ]
421        $vis:vis $field:ident
422        : $field_type:ty
423    ] => {
424        $crate::bitfield_accessors! {
425            @field $accessor_type
426            $( #[$meta] )*
427            [$lsb..=$msb] $vis $field: $field_type as $field_type
428        }
429    };
430
431    [
432        @field getter
433        $( #[$meta:meta] )*
434        [ $lsb:literal .. $msb:literal ]
435        $vis:vis $field:ident
436        : $underlying_type:ty as $interface_type:ty
437    ] => {
438        $crate::paste! {
439            $( #[$meta] )*
440            $vis fn $field(&self) -> $interface_type {
441                use $crate::TruncateInto;
442                let packed = <Self as $crate::Bitfield<_>>::value(*self);
443                let underlying: $underlying_type =
444                    $crate::get_bits(packed, $lsb, $msb).truncate_into();
445                underlying.into()
446            }
447        }
448    };
449
450    [
451        @field getter
452        $( #[$meta:meta] )*
453        [ $lsb:literal ..= $msb:literal ]
454        $vis:vis $field:ident
455        : $underlying_type:ty as $interface_type:ty
456    ] => {
457        $crate::paste! {
458            $( #[$meta] )*
459            $vis fn $field(&self) -> $interface_type {
460                use $crate::TruncateInto;
461                let packed = <Self as $crate::Bitfield<_>>::value(*self);
462                let underlying: $underlying_type =
463                    $crate::get_bits(packed, $lsb, $msb + 1).truncate_into();
464                underlying.into()
465            }
466        }
467    };
468
469    [
470        @field setter
471        $( #[$meta:meta] )*
472        [ $lsb:literal .. $msb:literal ]
473        $vis:vis $field:ident
474        : $underlying_type:ty as $interface_type:ty
475    ] => {
476        $crate::paste! {
477            $( #[$meta] )*
478            #[inline(always)]
479            $vis fn [< set_ $field >](&mut self, value: $interface_type) {
480                *self = self.[< with_ $field >](value);
481            }
482
483            $( #[$meta] )*
484            $vis fn [< with_ $field >](&self, value: $interface_type) -> Self {
485                let underlying: $underlying_type = value.into();
486                let packed = <Self as $crate::Bitfield<_>>::value(*self);
487                <Self as $crate::Bitfield<_>>::new(
488                    $crate::set_bits(packed, $lsb, $msb, underlying.into()))
489            }
490        }
491    };
492
493    [
494        @field setter
495        $( #[$meta:meta] )*
496        [ $lsb:literal ..= $msb:literal ]
497        $vis:vis $field:ident
498        : $underlying_type:ty as $interface_type:ty
499    ] => {
500        $crate::paste! {
501            $( #[$meta] )*
502            #[inline(always)]
503            $vis fn [< set_ $field >](&mut self, value: $interface_type) {
504                *self = self.[< with_ $field >](value);
505            }
506
507            $( #[$meta] )*
508            $vis fn [< with_ $field >](&self, value: $interface_type) -> Self {
509                let underlying: $underlying_type = value.into();
510                let packed = <Self as $crate::Bitfield<_>>::value(*self);
511                <Self as $crate::Bitfield<_>>::new(
512                    $crate::set_bits(packed, $lsb, $msb + 1, underlying.into()))
513            }
514        }
515    };
516}
517
518/// Get a boolean reflecting a single bit of the value.
519///
520/// `bit_num` starts as zero for the least significant bit.
521///
522/// ```
523/// # use tartan_bitfield::get_bit;
524/// assert_eq!(get_bit(0b0000_0100_u8, 2), true);
525/// assert_eq!(get_bit(0b0000_0100_u8, 3), false);
526/// ```
527#[must_use]
528pub fn get_bit<T>(val: T, bit_num: u8) -> bool
529where
530    T: Default
531        + PartialEq
532        + From<bool>
533        + ops::BitAnd<T, Output = T>
534        + ops::Shl<u8, Output = T>,
535{
536    let position_mask = T::from(true) << bit_num;
537    (val & position_mask) != T::default()
538}
539
540/// Create a copy of the value with a single bit modified.
541///
542/// `bit_num` starts as zero for the least significant bit.
543///
544/// ```
545/// # use tartan_bitfield::set_bit;
546/// assert_eq!(set_bit(0b0000_0000_u8, 5, true), 0b0010_0000);
547/// assert_eq!(set_bit(0b1111_1111_u8, 0, false), 0b1111_1110);
548/// ```
549#[must_use]
550pub fn set_bit<T>(val: T, bit_num: u8, bit_val: bool) -> T
551where
552    T: From<bool>
553        + ops::BitAnd<Output = T>
554        + ops::BitOr<Output = T>
555        + ops::Shl<u8, Output = T>
556        + ops::Not<Output = T>,
557{
558    let value_mask = T::from(bit_val) << bit_num;
559    let position_mask = T::from(true) << bit_num;
560    val & position_mask.not() | value_mask
561}
562
563/// Extract a range of bits from the value, shifted so the first bit of the subset is the
564/// least significant bit of the result.
565///
566/// Bits are numbered starting with zero for the least significant bit. The range of bits
567/// in the result is `lsb..msb`, **exclusive** of `msb`.
568///
569/// ```
570/// # use tartan_bitfield::get_bits;
571/// assert_eq!(get_bits(0b1100_1110_u8, 3, 7), 0b1001);
572/// assert_eq!(get_bits(0b1010_0101_u8, 6, 8), 0b10);
573/// ```
574#[must_use]
575pub fn get_bits<T>(packed_val: T, lsb: u8, msb: u8) -> T
576where
577    T: Default
578        + OverflowingShl
579        + OverflowingShr
580        + ops::Not<Output = T>
581        + ops::BitAnd<T, Output = T>,
582{
583    let field_width = msb - lsb;
584    // e.g., 0b0000_0111 for U with a width 3 bits from its MSB to LSB
585    let field_width_mask = T::default().not().saturating_shl(field_width.into()).not();
586    packed_val.saturating_shr(lsb.into()) & field_width_mask
587}
588
589/// Create a copy of the value with a subset of bits updated based on the passed value.
590///
591/// Bits are numbered starting with zero for the least significant bit. The range of
592/// updated bits is `lsb..msb`, **exclusive** of `msb`. `field_val` is shifted left `lsb`
593/// bits before being combined with `packed_val`.
594///
595/// ```
596/// # use tartan_bitfield::set_bits;
597/// assert_eq!(set_bits(0b0000_0000_u8, 6, 8, 0b11), 0b1100_0000);
598/// assert_eq!(set_bits(0b1111_1111_u8, 1, 5, 0b0000), 0b1110_0001);
599/// assert_eq!(set_bits(0b1010_0110_u8, 2, 6, 0b1110), 0b1011_1010);
600/// ```
601#[must_use]
602pub fn set_bits<T>(packed_val: T, lsb: u8, msb: u8, field_val: T) -> T
603where
604    T: Default
605        + Copy
606        + OverflowingShl
607        + ops::Shl<u8, Output = T>
608        + ops::Not<Output = T>
609        + ops::BitAnd<T, Output = T>
610        + ops::BitOr<T, Output = T>,
611{
612    // e.g., 0b1110_0000 for MSB = 5 (exclusive)
613    let msb_mask = T::default().not().saturating_shl(msb.into());
614    // e.g., 0b0000_0011 for LSB = 2
615    let lsb_mask = T::default().not().saturating_shl(lsb.into()).not();
616    // e.g., 0b1110_0011 for MSB = 5, LSB = 2
617    let position_mask = msb_mask | lsb_mask;
618    let value_mask = field_val.saturating_shl(lsb.into()) & position_mask.not();
619    packed_val & position_mask | value_mask
620}
621
622/// A type whose values can be truncated into another type. This is more explicit than
623/// `x as T`.
624pub trait TruncateInto<T> {
625    /// Truncate the value to fit in the destination type
626    fn truncate_into(self) -> T;
627}
628
629macro_rules! truncate_into_impl {
630    ($source:ty, $dest:ty) => {
631        impl TruncateInto<$dest> for $source {
632            #[inline(always)]
633            #[allow(clippy::cast_possible_truncation)]
634            fn truncate_into(self) -> $dest {
635                self as $dest
636            }
637        }
638    };
639}
640
641truncate_into_impl!(u128, u128);
642truncate_into_impl!(u128, u64);
643truncate_into_impl!(u128, u32);
644truncate_into_impl!(u128, u16);
645truncate_into_impl!(u128, u8);
646
647truncate_into_impl!(u64, u64);
648truncate_into_impl!(u64, u32);
649truncate_into_impl!(u64, u16);
650truncate_into_impl!(u64, u8);
651
652truncate_into_impl!(u32, u32);
653truncate_into_impl!(u32, u16);
654truncate_into_impl!(u32, u8);
655
656truncate_into_impl!(u16, u16);
657truncate_into_impl!(u16, u8);
658
659truncate_into_impl!(u8, u8);
660
661truncate_into_impl!(usize, usize);
662#[cfg(target_pointer_width = "64")]
663truncate_into_impl!(usize, u64);
664#[cfg(any(target_pointer_width = "64", target_pointer_width = "32"))]
665truncate_into_impl!(usize, u32);
666#[cfg(any(target_pointer_width = "64", target_pointer_width = "32"))]
667truncate_into_impl!(usize, u16);
668#[cfg(any(target_pointer_width = "64", target_pointer_width = "32"))]
669truncate_into_impl!(usize, u8);
670
671/// A type with an overflowing left shift operation. Also adds a saturating version.
672///
673/// All basic numeric types have this operation, but there is no corresponding trait in
674/// [`core::ops`].
675pub trait OverflowingShl
676where
677    Self: Sized + Default,
678{
679    /// Shift the value left by `n mod m` bits, where `m` is the number of bits in the
680    /// type. Return the shifted value along with a boolean indicating whether the shift
681    /// count was wrapped.
682    ///
683    /// Since this behavior is counterintuitive and practically useless, see
684    /// [`saturating_shl`](Self::saturating_shl) for an alternative that behaves the way
685    /// you probably expect.
686    fn overflowing_shl(self, n: u32) -> (Self, bool);
687
688    /// Shift the value left by `n` bits. If `n` is greater than or equal to the number
689    /// of bits in this type, the result will be zero.
690    #[inline(always)]
691    #[must_use]
692    fn saturating_shl(self, n: u32) -> Self {
693        match self.overflowing_shl(n) {
694            (_, true) => Self::default(),
695            (x, _) => x,
696        }
697    }
698}
699
700macro_rules! overflowing_shl_impl {
701    ($type:ty) => {
702        impl OverflowingShl for $type {
703            #[inline(always)]
704            fn overflowing_shl(self, n: u32) -> (Self, bool) {
705                self.overflowing_shl(n)
706            }
707        }
708    };
709}
710
711overflowing_shl_impl!(u8);
712overflowing_shl_impl!(u16);
713overflowing_shl_impl!(u32);
714overflowing_shl_impl!(u64);
715overflowing_shl_impl!(u128);
716overflowing_shl_impl!(usize);
717
718/// A type with an overflowing right shift operation. Also adds a saturating version.
719///
720/// All basic numeric types have this operation, but there is no corresponding trait in
721/// [`core::ops`].
722pub trait OverflowingShr
723where
724    Self: Sized + Default,
725{
726    /// Shift the value right by `n mod m` bits, where `m` is the number of bits in the
727    /// type. Return the shifted value along with a boolean indicating whether the shift
728    /// count was wrapped.
729    ///
730    /// Since this behavior is counterintuitive and practically useless, see
731    /// [`saturating_shr`](Self::saturating_shr) for an alternative that behaves the way
732    /// you probably expect.
733    fn overflowing_shr(self, n: u32) -> (Self, bool);
734
735    /// Shift the value right by `n` bits. If `n` is greater than or equal to the number
736    /// of bits in this type, the result will be zero.
737    #[inline(always)]
738    #[must_use]
739    fn saturating_shr(self, n: u32) -> Self {
740        match self.overflowing_shr(n) {
741            (_, true) => Self::default(),
742            (x, _) => x,
743        }
744    }
745}
746
747macro_rules! overflowing_shr_impl {
748    ($type:ty) => {
749        impl OverflowingShr for $type {
750            #[inline(always)]
751            fn overflowing_shr(self, n: u32) -> (Self, bool) {
752                self.overflowing_shr(n)
753            }
754        }
755    };
756}
757
758overflowing_shr_impl!(u8);
759overflowing_shr_impl!(u16);
760overflowing_shr_impl!(u32);
761overflowing_shr_impl!(u64);
762overflowing_shr_impl!(u128);
763overflowing_shr_impl!(usize);