fixed/
traits_bits.rs

1// Copyright © 2018–2025 Trevor Spiteri
2
3// This library is free software: you can redistribute it and/or
4// modify it under the terms of either
5//
6//   * the Apache License, Version 2.0 or
7//   * the MIT License
8//
9// at your option.
10//
11// You should have recieved copies of the Apache License and the MIT
12// License along with the library. If not, see
13// <https://www.apache.org/licenses/LICENSE-2.0> and
14// <https://opensource.org/licenses/MIT>.
15
16use crate::traits::FixedEquiv;
17#[cfg(feature = "arbitrary")]
18use arbitrary::Arbitrary;
19use az::{
20    Cast, CastFrom, CheckedCast, CheckedCastFrom, OverflowingCast, OverflowingCastFrom,
21    SaturatingCast, SaturatingCastFrom, UnwrappedCast, UnwrappedCastFrom, WrappingCast,
22    WrappingCastFrom,
23};
24#[cfg(feature = "borsh")]
25use borsh::{BorshDeserialize, BorshSerialize};
26use bytemuck::{Contiguous, Pod};
27use core::fmt::{Binary, Debug, Display, LowerExp, LowerHex, Octal, UpperExp, UpperHex};
28use core::hash::Hash;
29use core::iter::{Product, Sum};
30use core::num::ParseIntError;
31use core::ops::{
32    Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
33    Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
34};
35use core::str::FromStr;
36#[cfg(feature = "num-traits")]
37use num_traits::{
38    Num, NumAssignRef, NumRef,
39    cast::{AsPrimitive, FromPrimitive},
40    int::PrimInt,
41    ops::{
42        checked::{CheckedNeg, CheckedRem, CheckedShl, CheckedShr},
43        euclid::{CheckedEuclid, Euclid},
44        mul_add::{MulAdd, MulAddAssign},
45        overflowing::{OverflowingAdd, OverflowingMul, OverflowingSub},
46        saturating::{SaturatingAdd, SaturatingMul, SaturatingSub},
47        wrapping::{WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr, WrappingSub},
48    },
49};
50#[cfg(feature = "serde")]
51use serde::{de::Deserialize, ser::Serialize};
52
53macro_rules! impl_bits {
54    ($Bits:ident) => {
55        impl FixedBits for $Bits {
56            const MIN: $Bits = $Bits::MIN;
57            const MAX: $Bits = $Bits::MAX;
58            const IS_SIGNED: bool = $Bits::MIN != 0;
59            const BITS: u32 = $Bits::BITS;
60        }
61        impl Sealed for $Bits {}
62        impl FixedBitsCast<i8> for $Bits {}
63        impl FixedBitsCast<i16> for $Bits {}
64        impl FixedBitsCast<i32> for $Bits {}
65        impl FixedBitsCast<i64> for $Bits {}
66        impl FixedBitsCast<i128> for $Bits {}
67        impl FixedBitsCast<isize> for $Bits {}
68        impl FixedBitsCast<u8> for $Bits {}
69        impl FixedBitsCast<u16> for $Bits {}
70        impl FixedBitsCast<u32> for $Bits {}
71        impl FixedBitsCast<u64> for $Bits {}
72        impl FixedBitsCast<u128> for $Bits {}
73        impl FixedBitsCast<usize> for $Bits {}
74        impl FixedBitsOptionalArbitrary for $Bits {}
75        impl FixedBitsOptionalBorsh for $Bits {}
76        impl FixedBitsOptionalNum for $Bits {}
77        impl FixedBitsOptionalSerde for $Bits {}
78    };
79}
80
81/// This trait is implemented for <code>[Fixed]::[Bits]</code> for all
82/// fixed-point numbers.
83///
84/// This provides some facilities to manipulate bits in generic functions.
85///
86/// This trait is sealed and cannot be implemented for more types; it is
87/// implemented for [`i8`], [`i16`], [`i32`], [`i64`], [`i128`], [`u8`],
88/// [`u16`], [`u32`], [`u64`], and [`u128`].
89///
90/// # Examples
91///
92/// ```rust
93/// use az::OverflowingAs;
94/// use fixed::traits::Fixed;
95/// use fixed::types::*;
96/// fn limited_positive_bits<F: Fixed>(fixed: F) -> Option<u32> {
97///     let bits = fixed.to_bits();
98///     match bits.overflowing_as::<u32>() {
99///         (wrapped, false) => Some(wrapped),
100///         (_, true) => None,
101///     }
102/// }
103/// assert_eq!(limited_positive_bits(I16F16::from_bits(100)), Some(100));
104/// assert_eq!(limited_positive_bits(I16F16::from_bits(-100)), None);
105/// ```
106///
107/// [Bits]: crate::traits::Fixed::Bits
108/// [Fixed]: crate::traits::Fixed
109pub trait FixedBits
110where
111    Self: Default + Hash + Ord,
112    Self: Contiguous + Pod,
113    Self: Debug + Display + LowerExp + UpperExp,
114    Self: Binary + Octal + LowerHex + UpperHex,
115    Self: FromStr<Err = ParseIntError>,
116    Self: Add<Output = Self> + AddAssign,
117    Self: Sub<Output = Self> + SubAssign,
118    Self: Mul<Output = Self> + MulAssign,
119    Self: Div<Output = Self> + DivAssign,
120    Self: Rem<Output = Self> + RemAssign,
121    Self: Not<Output = Self>,
122    Self: BitAnd<Output = Self> + BitAndAssign,
123    Self: BitOr<Output = Self> + BitOrAssign,
124    Self: BitXor<Output = Self> + BitXorAssign,
125    Self: Shl<u32, Output = Self> + ShlAssign<u32>,
126    Self: Shr<u32, Output = Self> + ShrAssign<u32>,
127    Self: Sum + Product,
128    Self: FixedEquiv,
129    Self: FixedBitsCast<i8> + FixedBitsCast<i16> + FixedBitsCast<i32>,
130    Self: FixedBitsCast<i64> + FixedBitsCast<i128> + FixedBitsCast<isize>,
131    Self: FixedBitsCast<u8> + FixedBitsCast<u16> + FixedBitsCast<u32>,
132    Self: FixedBitsCast<u64> + FixedBitsCast<u128> + FixedBitsCast<usize>,
133    Self: FixedBitsOptionalArbitrary,
134    Self: FixedBitsOptionalBorsh,
135    Self: FixedBitsOptionalNum,
136    Self: FixedBitsOptionalSerde,
137    Self: Sealed,
138{
139    /// The smallest value that can be represented by this integer type.
140    const MIN: Self;
141
142    /// The largest value that can be represented by this integer type.
143    const MAX: Self;
144
145    /// [`true`] if this integer type is signed.
146    const IS_SIGNED: bool;
147
148    /// The size of this integer type in bits.
149    const BITS: u32;
150}
151
152/// This trait is used to provide supertraits to the [`FixedBits`] trait, and
153/// should not be used directly.
154pub trait FixedBitsCast<Prim>
155where
156    Self: TryInto<Prim> + TryFrom<Prim>,
157    Self: Cast<Prim> + CastFrom<Prim>,
158    Self: CheckedCast<Prim> + CheckedCastFrom<Prim>,
159    Self: SaturatingCast<Prim> + SaturatingCastFrom<Prim>,
160    Self: WrappingCast<Prim> + WrappingCastFrom<Prim>,
161    Self: UnwrappedCast<Prim> + UnwrappedCastFrom<Prim>,
162    Self: OverflowingCast<Prim> + OverflowingCastFrom<Prim>,
163    Self: Sealed,
164{
165}
166
167pub trait Sealed {}
168
169impl_bits! { i8 }
170impl_bits! { i16 }
171impl_bits! { i32 }
172impl_bits! { i64 }
173impl_bits! { i128 }
174impl_bits! { u8 }
175impl_bits! { u16 }
176impl_bits! { u32 }
177impl_bits! { u64 }
178impl_bits! { u128 }
179
180#[cfg(not(feature = "arbitrary"))]
181/// This trait is used to provide supertrait to the [`FixedBits`] trait
182/// depending on the crates’s [optional features], and should not be used
183/// directly.
184///
185/// If the `arbitrary` feature is enabled, [`Arbitrary`] is a supertrait of
186/// [`FixedBits`].
187///
188/// [optional features]: crate#optional-features
189pub trait FixedBitsOptionalArbitrary: Sealed {}
190
191#[cfg(feature = "arbitrary")]
192/// This trait is used to provide supertrait to the [`FixedBits`] trait
193/// depending on the crates’s [optional features], and should not be used
194/// directly.
195///
196/// If the `arbitrary` feature is enabled, [`Arbitrary`] is a supertrait of
197/// [`FixedBits`].
198///
199/// [optional features]: crate#optional-features
200pub trait FixedBitsOptionalArbitrary: Sealed
201where
202    Self: for<'a> Arbitrary<'a>,
203{
204}
205
206#[cfg(not(feature = "borsh"))]
207/// This trait is used to provide supertraits to the [`FixedBits`] trait
208/// depending on the crates’s [optional features], and should not be used
209/// directly.
210///
211/// If the `borsh` experimental feature is enabled, [`BorshSerialize`] and
212/// [`BorshDeserialize`] are supertraits of [`FixedBits`].
213///
214/// [optional features]: crate#optional-features
215pub trait FixedBitsOptionalBorsh: Sealed {}
216
217#[cfg(feature = "borsh")]
218/// This trait is used to provide supertraits to the [`FixedBits`] trait
219/// depending on the crates’s [optional features], and should not be used
220/// directly.
221///
222/// If the `borsh` experimental feature is enabled, [`BorshSerialize`] and
223/// [`BorshDeserialize`] are supertraits of [`FixedBits`].
224///
225/// [optional features]: crate#optional-features
226pub trait FixedBitsOptionalBorsh: Sealed
227where
228    Self: BorshSerialize + BorshDeserialize,
229{
230}
231
232#[cfg(not(feature = "num-traits"))]
233/// This trait is used to provide supertraits to the [`FixedBits`] trait
234/// depending on the crates’s [optional features], and should not be used
235/// directly.
236///
237/// If the [`num-traits` experimental feature][experimental features] is
238/// enabled, the following are supertraits of [`FixedBits`]:
239///
240///   * [`PrimInt`], [`FromPrimitive`]
241///   * <code>[AsPrimitive][`AsPrimitive`]&lt;T></code> where `T` can be [`i8`],
242///     [`i16`], [`i32`], [`i64`], [`i128`], [`isize`], [`u8`], [`u16`],
243///     [`u32`], [`u64`], [`u128`], [`usize`], [`f32`] or [`f64`]
244///   * [`CheckedNeg`], [`CheckedRem`], [`CheckedShl`], [`CheckedShr`]
245///   * [`SaturatingAdd`], [`SaturatingSub`], [`SaturatingMul`]
246///   * [`WrappingAdd`], [`WrappingSub`], [`WrappingNeg`], [`WrappingMul`],
247///     [`WrappingShl`], [`WrappingShr`]
248///   * [`OverflowingAdd`], [`OverflowingSub`], [`OverflowingMul`]
249///   * [`Euclid`], [`CheckedEuclid`]
250///   * [`MulAdd`], [`MulAddAssign`]
251///
252/// [experimental features]: crate#experimental-optional-features
253/// [optional features]: crate#optional-features
254pub trait FixedBitsOptionalNum: Sealed {}
255
256#[cfg(feature = "num-traits")]
257/// This trait is used to provide supertraits to the [`FixedBits`] trait
258/// depending on the crates’s [optional features], and should not be used
259/// directly.
260///
261/// If the [`num-traits` experimental feature][experimental features] is
262/// enabled, the following are supertraits of [`FixedBits`]:
263///
264///   * [`Num`], [`NumRef`], [`NumAssignRef`]
265///   * [`PrimInt`], [`FromPrimitive`]
266///   * <code>[AsPrimitive][`AsPrimitive`]&lt;T></code> where `T` can be [`i8`],
267///     [`i16`], [`i32`], [`i64`], [`i128`], [`isize`], [`u8`], [`u16`],
268///     [`u32`], [`u64`], [`u128`], [`usize`], [`f32`] or [`f64`]
269///   * [`CheckedNeg`], [`CheckedRem`], [`CheckedShl`], [`CheckedShr`]
270///   * [`SaturatingAdd`], [`SaturatingSub`], [`SaturatingMul`]
271///   * [`WrappingAdd`], [`WrappingSub`], [`WrappingNeg`], [`WrappingMul`],
272///     [`WrappingShl`], [`WrappingShr`]
273///   * [`OverflowingAdd`], [`OverflowingSub`], [`OverflowingMul`]
274///   * [`Euclid`], [`CheckedEuclid`]
275///   * [`MulAdd`], [`MulAddAssign`]
276///
277/// [experimental features]: crate#experimental-optional-features
278/// [optional features]: crate#optional-features
279pub trait FixedBitsOptionalNum: Sealed
280where
281    Self: Num<FromStrRadixErr = ParseIntError> + NumRef + NumAssignRef,
282    Self: PrimInt + FromPrimitive,
283    Self: AsPrimitive<i8> + AsPrimitive<i16> + AsPrimitive<i32>,
284    Self: AsPrimitive<i64> + AsPrimitive<i128> + AsPrimitive<isize>,
285    Self: AsPrimitive<u8> + AsPrimitive<u16> + AsPrimitive<u32>,
286    Self: AsPrimitive<u64> + AsPrimitive<u128> + AsPrimitive<usize>,
287    Self: AsPrimitive<f32> + AsPrimitive<f64>,
288    Self: CheckedNeg + CheckedRem + CheckedShl + CheckedShr,
289    Self: SaturatingAdd + SaturatingSub + SaturatingMul,
290    Self: WrappingAdd + WrappingSub + WrappingNeg + WrappingMul,
291    Self: WrappingShl + WrappingShr,
292    Self: OverflowingAdd + OverflowingSub + OverflowingMul,
293    Self: Euclid + CheckedEuclid,
294    Self: MulAdd + MulAddAssign,
295{
296}
297
298#[cfg(not(feature = "serde"))]
299/// This trait is used to provide supertraits to the [`FixedBits`] trait
300/// depending on the crates’s [optional features], and should not be used
301/// directly.
302///
303/// If the `serde` feature is enabled, [`Serialize`] and [`Deserialize`] are
304/// supertraits of [`FixedBits`].
305///
306/// [optional features]: crate#optional-features
307pub trait FixedBitsOptionalSerde: Sealed {}
308
309#[cfg(feature = "serde")]
310/// This trait is used to provide supertraits to the [`FixedBits`] trait
311/// depending on the crates’s [optional features], and should not be used
312/// directly.
313///
314/// If the `serde` feature is enabled, [`Serialize`] and [`Deserialize`] are
315/// supertraits of [`FixedBits`].
316///
317/// [optional features]: crate#optional-features
318pub trait FixedBitsOptionalSerde: Sealed
319where
320    Self: Serialize + for<'de> Deserialize<'de>,
321{
322}