stabby_abi/typenum2/
unsigned.rs

1//
2// Copyright (c) 2023 ZettaScale Technology
3//
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7// which is available at https://www.apache.org/licenses/LICENSE-2.0.
8//
9// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10//
11// Contributors:
12//   Pierre Avital, <pierre.avital@me.com>
13//
14
15/// Name the first great batch of numbers.
16pub mod typenames {
17    use super::{UInt, UTerm, B0, B1};
18    include!(concat!(env!("OUT_DIR"), "/unsigned.rs"));
19}
20use stabby_macros::tyeval;
21use typenames::*;
22
23use crate::{
24    istable::{IBitMask, IForbiddenValues, ISaturatingAdd, ISingleForbiddenValue, Saturator},
25    Array, End, IStable, Tuple,
26};
27/// (unsigned)0
28#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
29pub struct UTerm;
30/// An unsigned number as a list of digits.
31/// Ordering the generics this way makes reading types less painful, as the bits appear
32/// MSB-first in text form.
33#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
34pub struct UInt<Msbs: IUnsignedBase, Bit: IBit>(Msbs, Bit);
35
36/// A type to generate paddings.
37#[repr(transparent)]
38#[derive(Debug, Default, Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
39pub struct PadByte(u8);
40// SAFETY: See fields
41unsafe impl IStable for PadByte {
42    // Trivial
43    type Size = U1;
44    // Trivial
45    type Align = U1;
46    // Trivial
47    type ForbiddenValues = End;
48    // A padding byte uses none of its bits
49    type UnusedBits = Array<U0, UxFF, End>;
50    // Rust doesn't know there's a niche here
51    type HasExactlyOneNiche = B0;
52    type ContainsIndirections = B0;
53    #[cfg(feature = "experimental-ctypes")]
54    type CType = u8;
55    primitive_report!("PadByte");
56}
57
58/// The basis on which [`IBit`] stands.
59pub trait IBitBase {
60    /// Support for [`IBit`]
61    const _BOOL: bool;
62    /// Support for [`IBit`]
63    type _And<T: IBit>: IBit;
64    /// Support for [`IBit`]
65    type _Or<T: IBit>: IBit;
66    /// Support for [`IBit`]
67    type _Not: IBit;
68    /// Support for [`IBit`]
69    type _Ternary<A, B>;
70    /// Support for [`IBit`]
71    type _UTernary<A: IUnsigned, B: IUnsigned>: IUnsigned;
72    /// Support for [`IBit`]
73    type _NzTernary<A: NonZero, B: NonZero>: NonZero;
74    /// Support for [`IBit`]
75    type _BTernary<A: IBit, B: IBit>: IBit;
76    /// Support for [`IBit`]
77    type _BmTernary<A: IBitMask, B: IBitMask>: IBitMask;
78    /// Support for [`IBit`]
79    type _PTernary<A: IPowerOf2, B: IPowerOf2>: IPowerOf2;
80    /// Support for [`IBit`]
81    type _FvTernary<A: IForbiddenValues, B: IForbiddenValues>: IForbiddenValues;
82    /// Support for [`IBit`]
83    type _SfvTernary<A: ISingleForbiddenValue, B: ISingleForbiddenValue>: ISingleForbiddenValue;
84    /// Support for [`IBit`]
85    type _SaddTernary<A: ISaturatingAdd, B: ISaturatingAdd>: ISaturatingAdd;
86    /// Support for [`IBit`]
87    type _StabTernary<A: IStable, B: IStable>: IStable;
88    /// Ternary for Aligments
89    type _ATernary<A: Alignment, B: Alignment>: Alignment;
90    /// Support for [`IBit`]
91    type AsForbiddenValue: ISingleForbiddenValue;
92    /// u8 if B1, () otherwise
93    type _Padding: IStable<Align = U1> + Default + Copy + Unpin;
94}
95/// false
96#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
97pub struct B0;
98impl IBitBase for B0 {
99    const _BOOL: bool = false;
100    type _And<T: IBit> = Self;
101    type _Or<T: IBit> = T;
102    type _Not = B1;
103    type _Ternary<A, B> = B;
104    type _UTernary<A: IUnsigned, B: IUnsigned> = B;
105    type _NzTernary<A: NonZero, B: NonZero> = B;
106    type _BTernary<A: IBit, B: IBit> = B;
107    type _BmTernary<A: IBitMask, B: IBitMask> = B;
108    type _PTernary<A: IPowerOf2, B: IPowerOf2> = B;
109    type _FvTernary<A: IForbiddenValues, B: IForbiddenValues> = B;
110    type _SfvTernary<A: ISingleForbiddenValue, B: ISingleForbiddenValue> = B;
111    type _SaddTernary<A: ISaturatingAdd, B: ISaturatingAdd> = B;
112    type _StabTernary<A: IStable, B: IStable> = B;
113    type _ATernary<A: Alignment, B: Alignment> = B;
114    type _Padding = ();
115    type AsForbiddenValue = Saturator;
116}
117/// true
118#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
119pub struct B1;
120impl IBitBase for B1 {
121    const _BOOL: bool = true;
122    type _And<T: IBit> = T;
123    type _Or<T: IBit> = Self;
124    type _Not = B0;
125    type _Ternary<A, B> = A;
126    type _UTernary<A: IUnsigned, B: IUnsigned> = A;
127    type _NzTernary<A: NonZero, B: NonZero> = A;
128    type _BTernary<A: IBit, B: IBit> = A;
129    type _BmTernary<A: IBitMask, B: IBitMask> = A;
130    type _PTernary<A: IPowerOf2, B: IPowerOf2> = A;
131    type _FvTernary<A: IForbiddenValues, B: IForbiddenValues> = A;
132    type _SfvTernary<A: ISingleForbiddenValue, B: ISingleForbiddenValue> = A;
133    type _SaddTernary<A: ISaturatingAdd, B: ISaturatingAdd> = A;
134    type _StabTernary<A: IStable, B: IStable> = A;
135    type _ATernary<A: Alignment, B: Alignment> = A;
136    type _Padding = PadByte;
137    type AsForbiddenValue = End;
138}
139/// Equivalent to `B0` and `B1`, but can be constructed with a `const` expression.
140#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
141pub struct Bool<const B: bool>;
142macro_rules! same_as_bitbase {
143    ($src: ty) => {
144        const _BOOL: bool = <$src as IBitBase>::_BOOL;
145        type _And<T: IBit> = <$src as IBitBase>::_And<T>;
146        type _Or<T: IBit> = <$src as IBitBase>::_Or<T>;
147        type _Not = <$src as IBitBase>::_Not;
148        type _Ternary<A, B> = <$src as IBitBase>::_Ternary<A, B>;
149        type _UTernary<A: IUnsigned, B: IUnsigned> = <$src as IBitBase>::_UTernary<A, B>;
150        type _NzTernary<A: NonZero, B: NonZero> = <$src as IBitBase>::_NzTernary<A, B>;
151        type _BTernary<A: IBit, B: IBit> = <$src as IBitBase>::_BTernary<A, B>;
152        type _BmTernary<A: IBitMask, B: IBitMask> = <$src as IBitBase>::_BmTernary<A, B>;
153        type _PTernary<A: IPowerOf2, B: IPowerOf2> = <$src as IBitBase>::_PTernary<A, B>;
154        type _FvTernary<A: IForbiddenValues, B: IForbiddenValues> =
155            <$src as IBitBase>::_FvTernary<A, B>;
156        type _SfvTernary<A: ISingleForbiddenValue, B: ISingleForbiddenValue> =
157            <$src as IBitBase>::_SfvTernary<A, B>;
158        type _SaddTernary<A: ISaturatingAdd, B: ISaturatingAdd> =
159            <$src as IBitBase>::_SaddTernary<A, B>;
160        type _StabTernary<A: IStable, B: IStable> = <$src as IBitBase>::_StabTernary<A, B>;
161        type _ATernary<A: Alignment, B: Alignment> = <$src as IBitBase>::_ATernary<A, B>;
162        type _Padding = <$src as IBitBase>::_Padding;
163        type AsForbiddenValue = <$src as IBitBase>::AsForbiddenValue;
164    };
165}
166impl IBitBase for Bool<false> {
167    same_as_bitbase!(B0);
168}
169impl IBitBase for Bool<true> {
170    same_as_bitbase!(B1);
171}
172/// A boolean. [`B0`] and [`B1`] are the canonical members of this type-class
173pub trait IBit: IBitBase {
174    /// Converts from type to value
175    const BOOL: bool;
176    /// Self & T
177    type And<T: IBit>: IBit + Sized;
178    /// Self | T
179    type Or<T: IBit>: IBit + Sized;
180    /// !Self
181    type Not: IBit + Sized;
182    /// Self ? A : B
183    type Ternary<A, B>;
184    /// Self ? A : B, preserving bounds.
185    type UTernary<A: IUnsigned + Sized, B: IUnsigned + Sized>: IUnsigned + Sized;
186    /// Self ? A : B, preserving bounds.
187    type NzTernary<A: NonZero, B: NonZero>: NonZero + Sized;
188    /// Self ? A : B, preserving bounds.
189    type BTernary<A: IBit, B: IBit>: IBit + Sized;
190    /// Self ? A : B, preserving bounds.
191    type BmTernary<A: IBitMask, B: IBitMask>: IBitMask + Sized;
192    /// Self ? A : B, preserving bounds.
193    type PTernary<A: IPowerOf2, B: IPowerOf2>: IPowerOf2 + Sized;
194    /// Self ? A : B, preserving bounds.
195    type FvTernary<A: IForbiddenValues, B: IForbiddenValues>: IForbiddenValues;
196    /// Self ? A : B, preserving bounds.
197    type SaddTernary<A: ISaturatingAdd, B: ISaturatingAdd>: ISaturatingAdd;
198    /// Self ? A : B, preserving bounds.
199    type StabTernary<A: IStable, B: IStable>: IStable;
200    /// !(Self & Other)
201    type Nand<T: IBit>: IBit + Sized;
202    /// Self ^ Other
203    type Xor<T: IBit>: IBit + Sized;
204    /// Self == Other
205    type Equals<T: IBit>: IBit + Sized;
206    /// The sum bit of a full adder.
207    type AdderSum<Rhs: IBit, Carry: IBit>: IBit + Sized;
208    /// The carry bit of a full adder.
209    type AdderCarry<Rhs: IBit, Carry: IBit>: IBit + Sized;
210    /// The sum bit of a substractor.
211    type SuberSum<Rhs: IBit, Carry: IBit>: IBit + Sized;
212    /// The carry bit of a substractor.
213    type SuberCarry<Rhs: IBit, Carry: IBit>: IBit + Sized;
214}
215impl<Bit: IBitBase> IBit for Bit {
216    const BOOL: bool = Self::_BOOL;
217    type And<T: IBit> = Self::_And<T>;
218    type Or<T: IBit> = Self::_Or<T>;
219    type Not = Self::_Not;
220    type Ternary<A, B> = Self::_Ternary<A, B>;
221    type UTernary<A: IUnsigned, B: IUnsigned> = Self::_UTernary<A, B>;
222    type NzTernary<A: NonZero, B: NonZero> = Self::_NzTernary<A, B>;
223    type BTernary<A: IBit, B: IBit> = Self::_BTernary<A, B>;
224    type BmTernary<A: IBitMask, B: IBitMask> = Self::_BmTernary<A, B>;
225    type PTernary<A: IPowerOf2, B: IPowerOf2> = Self::_PTernary<A, B>;
226    type FvTernary<A: IForbiddenValues, B: IForbiddenValues> = Self::_FvTernary<A, B>;
227    type SaddTernary<A: ISaturatingAdd, B: ISaturatingAdd> = Self::_SaddTernary<A, B>;
228    type StabTernary<A: IStable, B: IStable> = Self::_StabTernary<A, B>;
229    type Nand<T: IBit> = <Self::_And<T> as IBitBase>::_Not;
230    type Xor<T: IBit> = <Self::_And<T::_Not> as IBitBase>::_Or<T::_And<Self::_Not>>;
231    type Equals<T: IBit> = <Self::Xor<T> as IBitBase>::_Not;
232    type AdderSum<Rhs: IBit, Carry: IBit> = <Self::Xor<Rhs> as IBit>::Xor<Carry>;
233    type AdderCarry<Rhs: IBit, Carry: IBit> =
234        <Rhs::_And<Carry> as IBitBase>::_Or<Self::_And<Rhs::Xor<Carry>>>;
235    type SuberSum<Rhs: IBit, Carry: IBit> = Self::AdderSum<Rhs, Carry>;
236    type SuberCarry<Rhs: IBit, Carry: IBit> =
237        <<Self::_Not as IBitBase>::_And<Rhs::_Or<Carry>> as IBitBase>::_Or<
238            Self::_And<Rhs::_And<Carry>>,
239        >;
240}
241/// The basis for [`IUnsigned`].
242pub trait IUnsignedBase {
243    /// Support for [`IUnsigned`]
244    const _U128: u128;
245    /// Support for [`IUnsigned`]
246    type Bit: IBitBase;
247    /// Support for [`IUnsigned`]
248    type Msb: IUnsigned;
249    /// Support for [`IUnsigned`]
250    type _BitAndInner<T: IUnsigned>: IUnsigned;
251    /// Support for [`IUnsigned`]
252    type _IsUTerm: IBit;
253    /// Support for [`IUnsigned`]
254    type _BitOrInner<T: IUnsigned>: IUnsigned;
255    /// Support for [`IUnsigned`]
256    type _Simplified: IUnsigned;
257    /// Support for [`IUnsigned`]
258    type _Equals<T: IUnsigned>: IBit;
259    /// Support for [`IUnsigned`]
260    type _Add<T: IUnsigned, Carry: IBit>: IUnsigned;
261    /// Support for [`IUnsigned`]
262    type _Sub<T: IUnsigned, Carry: IBit>: IUnsigned;
263    /// Support for [`IUnsigned`]
264    type _Greater<T: IUnsigned, Hint: IBit>: IBit;
265    /// Support for [`IUnsigned`]
266    type _Truncate<T: IUnsigned>: IUnsigned;
267    /// Support for [`IUnsigned`]
268    type NextPow2: IUnsigned;
269    /// Support for [`IUnsigned`]
270    type Increment: IUnsigned;
271    /// Support for [`IUnsigned`]
272    type _Padding: IStable<Align = U1> + Default + Copy + Unpin;
273    /// Support for [`IUnsigned`]
274    type _SatDecrement: IUnsigned;
275    /// Support for [`IUnsigned`]
276    type _TruncateAtRightmostOne: NonZero;
277    /// Support for [`IUnsigned`]
278    type _NonZero: NonZero;
279    /// Support for [`IUnsigned`]
280    type _Mul<T: IUnsigned>: IUnsigned;
281    /// Generates the bitmask for a Self bytes long padding.
282    type PaddingBitMask: IBitMask;
283    /// Helper for [`IUnsignedBase::Array`]
284    type _AddToArray<LsbArray: IStable, ArrayStack: IStable>: IStable;
285    /// Generates a type that has the same layout as `[T; Self]`
286    type Array<T: IStable>: IStable;
287}
288/// A is smaller than B if `A::Cmp<B>` = Lesser.
289pub struct Lesser;
290/// A equals B if `A::Cmp<B>` = Equal.
291pub struct Equal;
292/// A is greater than B if `A::Cmp<B>` = Greater.
293pub struct Greater;
294
295/// An unsigned number.
296pub trait IUnsigned: IUnsignedBase {
297    /// Convert type to value
298    const U128: u128;
299    /// Convert type to value
300    const USIZE: usize;
301    /// Convert type to value
302    const U64: u64;
303    /// Convert type to value
304    const U32: u32;
305    /// Convert type to value
306    const U16: u16;
307    /// Convert type to value
308    const U8: u8;
309    /// Self & T
310    type BitAnd<T: IUnsigned>: IUnsigned;
311    /// Self | T
312    type BitOr<T: IUnsigned>: IUnsigned;
313    /// Self == T
314    type Equal<T: IUnsigned>: IBit;
315    /// Self != T
316    type NotEqual<T: IUnsigned>: IBit;
317    /// Self > T
318    type Greater<T: IUnsigned>: IBit;
319    /// Self >= T
320    type GreaterOrEq<T: IUnsigned>: IBit;
321    /// Self < T
322    type Smaller<T: IUnsigned>: IBit;
323    /// Self <= T
324    type SmallerOrEq<T: IUnsigned>: IBit;
325    /// Self + T
326    type Add<T: IUnsigned>: IUnsigned;
327    /// |Self - T|
328    type AbsSub<T: IUnsigned>: IUnsigned;
329    /// min(Self, T)
330    type Min<T: IUnsigned>: IUnsigned;
331    /// max(Self, T)
332    type Max<T: IUnsigned>: IUnsigned;
333    /// Support for modular operations.
334    type Truncate<T: IUnsigned>: IUnsigned;
335    /// Self % T
336    type Mod<T: IPowerOf2>: IUnsigned;
337    /// Constructs a type with alignment 1 and size Self.
338    type Padding: IStable<Align = U1> + Sized + Default + Copy + Unpin;
339    /// Coerces Self into [`NonZero`]
340    type NonZero: NonZero;
341    /// Finds the smallest `n` such that `n = T * k` and `n >= Self`
342    type NextMultipleOf<T: IPowerOf2>: IUnsigned;
343    /// Self.cmp(T)
344    type Cmp<T: IUnsigned>;
345    /// Self * T
346    type Mul<T: IUnsigned>: IUnsigned;
347}
348
349/// An unsigned number that's a power of 2
350pub trait IPowerOf2: IUnsigned {
351    /// log2(Self)
352    type Log2: IUnsigned;
353    /// min(Self, T)
354    type Min<T: IPowerOf2>: IPowerOf2;
355    /// max(Self, T)
356    type Max<T: IPowerOf2>: IPowerOf2;
357    /// T % Self
358    type Modulate<T: IUnsigned>: IUnsigned;
359    /// T / Self
360    type Divide<T: IUnsigned>: IUnsigned;
361}
362impl<U: IUnsignedBase> IUnsigned for U {
363    const U128: u128 = Self::_U128;
364    const USIZE: usize = Self::_U128 as usize;
365    const U64: u64 = Self::_U128 as u64;
366    const U32: u32 = Self::_U128 as u32;
367    const U16: u16 = Self::_U128 as u16;
368    const U8: u8 = Self::_U128 as u8;
369    type BitAnd<T: IUnsigned> = <Self::_BitAndInner<T> as IUnsignedBase>::_Simplified;
370    type BitOr<T: IUnsigned> = <Self::_BitOrInner<T> as IUnsignedBase>::_Simplified;
371    type Equal<T: IUnsigned> = Self::_Equals<T>;
372    type NotEqual<T: IUnsigned> = <Self::Equal<T> as IBit>::Not;
373    type Greater<T: IUnsigned> = Self::_Greater<T, B0>;
374    type GreaterOrEq<T: IUnsigned> = <Self::Greater<T> as IBit>::Or<Self::Equal<T>>;
375    type SmallerOrEq<T: IUnsigned> = <Self::Greater<T> as IBit>::Not;
376    type Smaller<T: IUnsigned> = <Self::GreaterOrEq<T> as IBit>::Not;
377    type Add<T: IUnsigned> = Self::_Add<T, B0>;
378    type AbsSub<T: IUnsigned> = <<Self::Greater<T> as IBit>::UTernary<
379        Self::_Sub<T, B0>,
380        T::_Sub<Self, B0>,
381    > as IUnsignedBase>::_Simplified;
382    type Min<T: IUnsigned> = <Self::Greater<T> as IBit>::UTernary<T, Self>;
383    type Max<T: IUnsigned> = <Self::Greater<T> as IBit>::UTernary<Self, T>;
384    type Truncate<T: IUnsigned> = <Self::_Truncate<T> as IUnsignedBase>::_Simplified;
385    type Mod<T: IPowerOf2> = T::Modulate<Self>;
386    type Padding = Self::_Padding;
387    type NonZero = Self::_NonZero;
388    type NextMultipleOf<T: IPowerOf2> =
389        tyeval!(((Self % T) == U0) ? Self : (Self + (T - (Self % T))));
390    type Cmp<T: IUnsigned> = <Self::Equal<T> as IBit>::Ternary<
391        Equal,
392        <Self::Greater<T> as IBit>::Ternary<Greater, Lesser>,
393    >;
394    type Mul<T: IUnsigned> = Self::_Mul<T>;
395}
396impl IUnsignedBase for UTerm {
397    const _U128: u128 = 0;
398    type Bit = B0;
399    type Msb = UTerm;
400    type _IsUTerm = B1;
401    type _BitAndInner<T: IUnsignedBase> = UTerm;
402    type _BitOrInner<T: IUnsigned> = T;
403    type _Simplified = UTerm;
404    type _Equals<T: IUnsigned> = T::_IsUTerm;
405    type Increment = U1;
406    type _Add<T: IUnsigned, Carry: IBit> = Carry::UTernary<T::Increment, T>;
407    type _Greater<T: IUnsigned, Hint: IBit> = Hint::And<T::_IsUTerm>;
408    type _Sub<T: IUnsigned, Carry: IBit> = UTerm;
409    type _Truncate<T: IUnsigned> = UTerm;
410    type _Padding = ();
411    type _SatDecrement = U0;
412    type NextPow2 = U0;
413    type _TruncateAtRightmostOne = Saturator;
414    type _NonZero = Saturator;
415    type _Mul<T: IUnsigned> = UTerm;
416    type PaddingBitMask = End;
417    type _AddToArray<LsbArray: IStable, ArrayStack: IStable> = LsbArray;
418    type Array<T: IStable> = ();
419}
420impl IUnsignedBase for Saturator {
421    #[cfg(not(doc))]
422    const _U128: u128 = { panic!("Attempted to convert Saturator into u128") };
423    #[cfg(doc)]
424    const _U128: u128 = u128::MAX;
425    type Bit = B0;
426    type Msb = Saturator;
427    type _IsUTerm = B1;
428    type _BitAndInner<T: IUnsignedBase> = Saturator;
429    type _BitOrInner<T: IUnsigned> = Saturator;
430    type _Simplified = Saturator;
431    type _Equals<T: IUnsigned> = T::_IsUTerm;
432    type Increment = Saturator;
433    type _Add<T: IUnsigned, Carry: IBit> = Carry::UTernary<T::Increment, T>;
434    type _Greater<T: IUnsigned, Hint: IBit> = Hint::And<T::_IsUTerm>;
435    type _Sub<T: IUnsigned, Carry: IBit> = Saturator;
436    type _Truncate<T: IUnsigned> = Saturator;
437    type _Padding = ();
438    type _SatDecrement = Saturator;
439    type NextPow2 = Saturator;
440    type _TruncateAtRightmostOne = Saturator;
441    type _NonZero = Saturator;
442    type _Mul<T: IUnsigned> = Saturator;
443    type PaddingBitMask = End;
444    type _AddToArray<LsbArray: IStable, ArrayStack: IStable> = ();
445    type Array<T: IStable> = ();
446}
447
448/// A non-zero unsigned number.
449pub trait NonZero: IUnsigned {
450    /// Self--
451    type Decrement: IUnsigned;
452    /// Self >> (Self.trailing_zeros())
453    type TruncateAtRightmostOne: IUnsigned;
454}
455impl NonZero for Saturator {
456    type Decrement = Saturator;
457    type TruncateAtRightmostOne = Saturator;
458}
459/// Adds a byte to a padding `L`
460#[repr(C)]
461#[derive(Default, Clone, Copy)]
462pub struct OneMoreByte<L: IStable<Align = U1> + Copy + Default> {
463    l: L,
464    r: PadByte,
465}
466// SAFETY: See each field
467unsafe impl<L: IStable<Align = U1> + Copy + Default> IStable for OneMoreByte<L> {
468    // L::Align = U1 => adding a single byte increments the size
469    type Size = <L::Size as IUnsignedBase>::Increment;
470    // L::Align = U1, adding a single byte doesn't change that.
471    type Align = U1;
472    // The added byte has no forbidden values, so we only keep L's
473    type ForbiddenValues = L::ForbiddenValues;
474    // The enhtire added byte is unused, since it's padding.
475    type UnusedBits = <L::UnusedBits as IBitMask>::BitOr<Array<L::Size, UxFF, End>>;
476    // Rust doesn't know the padding byte is padding.
477    type HasExactlyOneNiche = L::HasExactlyOneNiche;
478    // The padding byte doesn't contain indirections.
479    type ContainsIndirections = L::ContainsIndirections;
480    #[cfg(feature = "experimental-ctypes")]
481    type CType = Tuple<L, u8>;
482    primitive_report!("OneMoreByte");
483}
484impl<Msb: IUnsigned, Bit: IBit> NonZero for UInt<Msb, Bit> {
485    type Decrement =
486        <Bit::UTernary<UInt<Msb, B0>, UInt<Msb::_SatDecrement, B1>> as IUnsignedBase>::_Simplified;
487    type TruncateAtRightmostOne = Self::_TruncateAtRightmostOne;
488}
489/// A helper to generate padding of appropriate size.
490#[repr(C)]
491pub struct PaddingHelper<Double: IStable<Align = U1>, Bit: IBitBase>(Double, Double, Bit::_Padding);
492impl<Double: IStable<Align = U1> + Default, Bit: IBitBase> Default for PaddingHelper<Double, Bit> {
493    fn default() -> Self {
494        Self(Default::default(), Default::default(), Default::default())
495    }
496}
497impl<Double: IStable<Align = U1> + Copy, Bit: IBitBase> Copy for PaddingHelper<Double, Bit> {}
498impl<Double: IStable<Align = U1> + Copy, Bit: IBitBase> Clone for PaddingHelper<Double, Bit> {
499    fn clone(&self) -> Self {
500        *self
501    }
502}
503unsafe impl<Double: IStable<Align = U1>, Bit: IBitBase> IStable for PaddingHelper<Double, Bit> {
504    type Align = U1;
505    type Size = <<U2 as IUnsigned>::Mul<Double::Size> as IUnsigned>::Add<Bit::_UTernary<U1, U0>>;
506    type ForbiddenValues = End;
507    type ContainsIndirections = B0;
508    type HasExactlyOneNiche = B0;
509    type UnusedBits = <crate::tuple::Tuple3<Double, Double, Bit::_Padding> as IStable>::UnusedBits;
510    #[cfg(feature = "experimental-ctypes")]
511    type CType = crate::tuple::Tuple3<Double, Double, Bit::_Padding>;
512    primitive_report!("Padding");
513}
514impl<Msb: IUnsigned, Bit: IBit> IUnsignedBase for UInt<Msb, Bit> {
515    const _U128: u128 = (Msb::_U128 << 1) | (<Self::Bit as IBit>::BOOL as u128);
516    type Bit = Bit;
517    type Msb = Msb;
518    type _IsUTerm = <Bit::Not as IBit>::And<Msb::_IsUTerm>;
519    type _Simplified = <Self::_IsUTerm as IBit>::UTernary<UTerm, UInt<Msb::_Simplified, Bit>>;
520    type _BitAndInner<T: IUnsigned> = UInt<Msb::_BitAndInner<T::Msb>, Bit::And<T::Bit>>;
521    type _BitOrInner<T: IUnsigned> = UInt<Msb::_BitOrInner<T::Msb>, Bit::Or<T::Bit>>;
522    type _Equals<T: IUnsigned> = <Bit::Equals<T::Bit> as IBit>::And<Msb::Equal<T::Msb>>;
523    type _Greater<T: IUnsigned, Hint: IBit> =
524        Msb::_Greater<T::Msb, <T::Bit as IBit>::BTernary<Hint::And<Bit>, Hint::Or<Bit>>>;
525    type Increment = Self::_Add<UTerm, B1>;
526    type _Add<T: IUnsigned, Carry: IBit> =
527        UInt<Msb::_Add<T::Msb, Bit::AdderCarry<T::Bit, Carry>>, Bit::AdderSum<T::Bit, Carry>>;
528    type _Sub<T: IUnsigned, Carry: IBit> =
529        UInt<Msb::_Sub<T::Msb, Bit::SuberCarry<T::Bit, Carry>>, Bit::SuberSum<T::Bit, Carry>>;
530    type _Truncate<T: IUnsigned> =
531        <T::_IsUTerm as IBit>::UTernary<UTerm, UInt<Msb::_Truncate<T::AbsSub<U1>>, Bit>>;
532    type _SatDecrement =
533        <Bit::UTernary<UInt<Msb, B0>, UInt<Msb::_SatDecrement, B1>> as IUnsignedBase>::_Simplified;
534    type _Padding = PaddingHelper<Msb::Padding, Bit>;
535    type NextPow2 = <Msb::NextPow2 as IUnsigned>::Add<<Self::_IsUTerm as IBit>::UTernary<U0, U1>>;
536    type _TruncateAtRightmostOne = Bit::NzTernary<U1, UInt<Msb::_TruncateAtRightmostOne, B0>>;
537    type _NonZero = Self;
538    type _Mul<T: IUnsigned> = <Bit::UTernary<T, UTerm> as IUnsigned>::Add<
539        <UInt<Msb::Mul<T>, B0> as IUnsignedBase>::_Simplified,
540    >;
541    type PaddingBitMask = Array<
542        U0,
543        U255,
544        <<Self::_SatDecrement as IUnsignedBase>::PaddingBitMask as IBitMask>::Shift<U1>,
545    >;
546    type _AddToArray<LsbArray: IStable, ArrayStack: IStable> = Msb::_AddToArray<
547        Bit::StabTernary<
548            <<LsbArray::Size as IUnsignedBase>::_IsUTerm as IBit>::StabTernary<
549                ArrayStack,
550                Tuple<ArrayStack, LsbArray>,
551            >,
552            LsbArray,
553        >,
554        Tuple<ArrayStack, ArrayStack>,
555    >;
556    type Array<T: IStable> = Self::_AddToArray<(), T>;
557}
558impl<Msb: IUnsigned<_IsUTerm = B1>> IPowerOf2 for UInt<Msb, B1> {
559    type Log2 = U0;
560    type Min<T: IPowerOf2> = <Self::Greater<T> as IBit>::PTernary<T, Self>;
561    type Max<T: IPowerOf2> = <Self::Greater<T> as IBit>::PTernary<Self, T>;
562    type Modulate<T: IUnsigned> = UTerm;
563    type Divide<T: IUnsigned> = T;
564}
565impl<Msb: IPowerOf2> IPowerOf2 for UInt<Msb, B0> {
566    type Log2 = <Msb::Log2 as IUnsignedBase>::Increment;
567    type Min<T: IPowerOf2> = <Self::Greater<T> as IBit>::PTernary<T, Self>;
568    type Max<T: IPowerOf2> = <Self::Greater<T> as IBit>::PTernary<Self, T>;
569    type Modulate<T: IUnsigned> =
570        <UInt<Msb::Modulate<T::Msb>, T::Bit> as IUnsignedBase>::_Simplified;
571    type Divide<T: IUnsigned> = Msb::Divide<T::Msb>;
572}
573
574/// An alignment that `stabby` can build an array arround.
575pub trait Alignment: IPowerOf2 {
576    /// max(Self, T)
577    type Max<T: Alignment>: Alignment;
578    /// A type with size and aligment equal to Self
579    type AsUint: Copy + Default + IStable;
580}
581impl Alignment for U1 {
582    type Max<T: Alignment> = <Self::Greater<T> as IBitBase>::_ATernary<Self, T>;
583    type AsUint = u8;
584}
585impl Alignment for U2 {
586    type Max<T: Alignment> = <Self::Greater<T> as IBitBase>::_ATernary<Self, T>;
587    type AsUint = u16;
588}
589impl Alignment for U4 {
590    type Max<T: Alignment> = <Self::Greater<T> as IBitBase>::_ATernary<Self, T>;
591    type AsUint = u32;
592}
593impl Alignment for U8 {
594    type Max<T: Alignment> = <Self::Greater<T> as IBitBase>::_ATernary<Self, T>;
595    type AsUint = u64;
596}
597impl Alignment for U16 {
598    type Max<T: Alignment> = <Self::Greater<T> as IBitBase>::_ATernary<Self, T>;
599    type AsUint = u128;
600}
601macro_rules! gen_align {
602    ($n: literal, $path: ident, $u: ident, $backing: ty) => {
603        /// A type with the alignment specified in its name.
604        ///
605        /// This type is also valid as a contiguous buffer.
606        #[crate::stabby]
607        #[repr(align($n))]
608        #[derive(Debug, Default, Copy, Clone)]
609        pub struct $path(pub $backing);
610        impl Alignment for $u {
611            type Max<T: Alignment> = <Self::Greater<T> as IBitBase>::_ATernary<Self, T>;
612            type AsUint = $path;
613        }
614    };
615}
616gen_align!(32, Align32, U32, [u8; 32]);
617gen_align!(64, Align64, U64, [[u8; 32]; 2]);
618gen_align!(128, Align128, U128, [[u8; 32]; 4]);
619gen_align!(256, Align256, U256, [[u8; 32]; 8]);
620gen_align!(512, Align512, U512, [[u8; 32]; 16]);
621gen_align!(1024, Align1024, U1024, [[u8; 32]; 32]);
622gen_align!(2048, Align2048, U2048, [[[u8; 32]; 32]; 2]);
623gen_align!(4096, Align4096, U4096, [[[u8; 32]; 32]; 4]);
624gen_align!(8192, Align8192, U8192, [[[u8; 32]; 32]; 8]);
625gen_align!(16384, Align16384, U16384, [[[u8; 32]; 32]; 16]);
626gen_align!(32768, Align32768, U32768, [[[u8; 32]; 32]; 32]);
627gen_align!(65536, Align65536, U65536, [[[[u8; 32]; 32]; 32]; 2]);
628
629#[allow(unknown_lints)]
630#[allow(clippy::missing_transmute_annotations)]
631#[test]
632fn ops() {
633    fn test_pair<A: IUnsigned, B: IUnsigned>() {
634        assert_eq!(
635            <A::BitAnd<B> as IUnsigned>::U128,
636            A::U128 & B::U128,
637            "{} & {} ({} & {})",
638            A::U128,
639            B::U128,
640            core::any::type_name::<A>(),
641            core::any::type_name::<B>(),
642        );
643        assert_eq!(
644            <A::BitOr<B> as IUnsigned>::U128,
645            A::U128 | B::U128,
646            "{} | {} ({} | {})",
647            A::U128,
648            B::U128,
649            core::any::type_name::<A>(),
650            core::any::type_name::<B>(),
651        );
652        assert_eq!(
653            <A::Add<B> as IUnsigned>::U128,
654            A::U128 + B::U128,
655            "{} + {} ({} + {})",
656            A::U128,
657            B::U128,
658            core::any::type_name::<A>(),
659            core::any::type_name::<B>(),
660        );
661
662        let mask = if B::U32 == 0 {
663            0
664        } else {
665            u128::MAX.wrapping_shr(128 - B::U32)
666        };
667        assert_eq!(
668            <A::_Truncate<B> as IUnsigned>::U128,
669            A::U128 & mask,
670            "{} trunc {} ({mask:x}) ({} trunc {})",
671            A::U128,
672            B::U128,
673            core::any::type_name::<A>(),
674            core::any::type_name::<B>(),
675        );
676        assert_eq!(
677            <A::Greater<B> as IBitBase>::_BOOL,
678            A::U128 > B::U128,
679            "{} > {}",
680            A::U128,
681            B::U128,
682        );
683        assert_eq!(
684            <A::Smaller<B> as IBitBase>::_BOOL,
685            A::U128 < B::U128,
686            "{} < {}",
687            A::U128,
688            B::U128,
689        );
690        assert_eq!(
691            <A::Equal<B> as IBitBase>::_BOOL,
692            A::U128 == B::U128,
693            "{} == {}",
694            A::U128,
695            B::U128,
696        );
697        assert_eq!(
698            <A::Max<B> as IUnsigned>::U128,
699            A::U128.max(B::U128),
700            "{} max {}",
701            A::U128,
702            B::U128,
703        );
704        assert_eq!(
705            <A::Min<B> as IUnsigned>::U128,
706            A::U128.min(B::U128),
707            "{} min {}",
708            A::U128,
709            B::U128,
710        );
711        assert_eq!(
712            <A::AbsSub<B> as IUnsigned>::U128,
713            A::U128.abs_diff(B::U128),
714            "|{} - {}| (|{} - {}|)",
715            A::U128,
716            B::U128,
717            core::any::type_name::<A>(),
718            core::any::type_name::<B>(),
719        );
720        assert_eq!(
721            <A::NextPow2 as IUnsigned>::U32,
722            128 - A::U128.leading_zeros(),
723            "nextpow2 {}",
724            A::U128,
725        );
726    }
727    test_pair::<U0, U0>();
728    test_pair::<U0, U1>();
729    test_pair::<U1, U0>();
730    test_pair::<U1, U1>();
731    test_pair::<U1, U2>();
732    test_pair::<U2, U2>();
733    test_pair::<U3, U1>();
734    test_pair::<U4, U1>();
735    test_pair::<U2, U1>();
736    test_pair::<U4, U2>();
737    test_pair::<U4, U3>();
738    test_pair::<U4, U4>();
739    test_pair::<U4, U5>();
740    test_pair::<U5, U1>();
741    test_pair::<U1, U5>();
742    test_pair::<U5, U4>();
743    test_pair::<U2, U3>();
744    test_pair::<U3, U2>();
745    test_pair::<U10, U0>();
746    test_pair::<U10, U5>();
747    test_pair::<U10, U4>();
748    let _: <U0 as IUnsigned>::BitOr<U1> = <<U1 as IUnsigned>::BitOr<U0>>::default();
749    let _: B0 = <<U0 as IUnsigned>::NotEqual<U0>>::default();
750    let _: B1 = <<U1 as IUnsigned>::NotEqual<U0>>::default();
751    let _: B1 = <<U2 as IUnsigned>::NotEqual<U0>>::default();
752    let _: B1 = <<U3 as IUnsigned>::NotEqual<U0>>::default();
753    let _: B1 = <<U4 as IUnsigned>::NotEqual<U0>>::default();
754    let _: U2 = <<U10 as IUnsigned>::BitAnd<U6>>::default();
755    let _: B1 = <<U2 as IUnsigned>::Equal<<U10 as IUnsigned>::BitAnd<U6>>>::default();
756    let _: B0 = <<U3 as IUnsigned>::Equal<<U10 as IUnsigned>::BitAnd<U6>>>::default();
757    let _: U11 = <<U16 as IPowerOf2>::Modulate<U11>>::default();
758    let _: U11 = <<U11 as IUnsigned>::Mod<U16>>::default();
759    let _: U10 = <<U10 as IUnsigned>::Mod<U16>>::default();
760    let _: U3 = <<U11 as IUnsigned>::Mod<U8>>::default();
761    let _: U2 = <<U10 as IUnsigned>::Mod<U8>>::default();
762    let _: U3 = <<U11 as IUnsigned>::Mod<U4>>::default();
763    let _: U2 = <<U10 as IUnsigned>::Mod<U4>>::default();
764    let _: U1 = <<U11 as IUnsigned>::Mod<U2>>::default();
765    let _: U0 = <<U10 as IUnsigned>::Mod<U2>>::default();
766    let _: U0 = <<U10 as IUnsigned>::Mod<U1>>::default();
767    let _: U255 = UxFF::default();
768    let _: Ub111100 = <<Ub11111100 as IUnsigned>::BitAnd<Ub111111>>::default();
769    let _: U0 = <<U0 as IUnsigned>::NextMultipleOf<U8>>::default();
770    let _: U16 = <<U10 as IUnsigned>::NextMultipleOf<U8>>::default();
771    let _: U16 = <<U16 as IUnsigned>::NextMultipleOf<U8>>::default();
772    let _: U32 = <<U26 as IUnsigned>::NextMultipleOf<U8>>::default();
773    let _: U32 = <<U26 as IUnsigned>::NextMultipleOf<U32>>::default();
774    assert_eq!(U0::_U128, 0);
775    assert_eq!(U1::_U128, 1);
776    assert_eq!(U2::_U128, 2);
777    assert_eq!(U3::_U128, 3);
778    assert_eq!(U4::_U128, 4);
779    assert_eq!(U5::_U128, 5);
780    assert_eq!(U10::_U128, 10);
781    // SAFETY: These are actually compile-time safety checks.
782    unsafe { core::mem::transmute::<_, <U22 as IUnsignedBase>::Array<u8>>([0u8; 22]) };
783    // SAFETY: These are actually compile-time safety checks.
784    unsafe { core::mem::transmute::<_, <U122 as IUnsignedBase>::Array<u16>>([0u16; 122]) };
785    // SAFETY: These are actually compile-time safety checks.
786    unsafe { core::mem::transmute::<[u8; 0], <U0 as IUnsignedBase>::Array<u8>>([]) };
787}