// Copyright 2025 Gabriel Bjørnager Jensen.

mod test;

use crate::{
	Array,
	CarryingMulAdd,
	DisjointBitOr,
	Int,
};
use crate::compat::{
	CloneToUninit,
	ConstParamTy_,
	Freeze,
	Step,
	StructuralPartialEq,
	Thin,
	ToOwned,
	ToString,
	TrustedStep,
	UseCloned,
};

use core::any::Any;
use core::convert::Infallible;
use core::fmt::{
	Binary,
	Debug,
	Display,
	LowerExp,
	LowerHex,
	Octal,
	UpperExp,
	UpperHex,
};
use core::hash::Hash;
use core::iter::{Product, Sum};
use core::num::ParseIntError;
use core::ops::{
	Add,
	AddAssign,
	BitAnd,
	BitAndAssign,
	BitOr,
	BitOrAssign,
	BitXor,
	BitXorAssign,
	Div,
	DivAssign,
	Mul,
	MulAssign,
	Not,
	Rem,
	RemAssign,
	Shl,
	ShlAssign,
	Shr,
	ShrAssign,
	Sub,
	SubAssign,
};
use core::panic::{RefUnwindSafe, UnwindSafe};
use core::str::FromStr;

/// A generic, unsigned integer.
///
/// This trait abstracts the interfaces defined by [`u8`], [`u16`], [`u32`], [`u64`], [`u128`], and [`usize`] so that these may be used as a single type.
///
/// The following trait(s) are not required due to some unsigned, integral types not implementing them:
/// * <code>[From]&lt;[ascii::Char](core::ascii::Char)&gt;</code>: Not implement by `usize`
/// * <code>[TryFrom]&lt;[char]&gt;</code>: Not implement by `usize`
///
/// These trait(s) will be required when standard support arrives.
///
/// See also [`UintLeast16`](crate::UintLeast16), [`UintLeast32`](crate::UintLeast32), and [`UintLeast64`](crate::UintLeast64).
///
/// # Safety
///
/// [`Int`](Self::Int) must be *the* signed counterpart to `Self` so that transmutations between the two are always valid.
///
/// Furthermore, all items must behave exactly as their standard counterparts.
pub unsafe trait Uint
where
	Self:
		crate::seal::Uint
		+ 'static
		+ Any
		+ Binary
		+ CarryingMulAdd<LowOutput = Self, HighOutput = Self>
		+ CloneToUninit
		+ ConstParamTy_
		+ Copy
		+ Debug
		+ Default
		+ DisjointBitOr
		+ Display
		+ Eq
		+ Freeze
		+ From<bool>
		+ From<u8>
		+ FromStr
		+ Hash
		+ LowerExp
		+ LowerHex
		+ Octal
		+ Ord
		+ PartialEq
		+ PartialOrd
		+ Product
		+ RefUnwindSafe
		+ Send
		+ Step
		+ StructuralPartialEq
		+ Sum
		+ Sync
		+ Thin
		+ ToOwned
		+ ToString
		+ TrustedStep
		+ TryFrom<bool,  Error = Infallible>
		+ TryFrom<i128>
		+ TryFrom<i16>
		+ TryFrom<i32>
		+ TryFrom<i64>
		+ TryFrom<i8>
		+ TryFrom<isize>
		+ TryFrom<u128>
		+ TryFrom<u16>
		+ TryFrom<u32>
		+ TryFrom<u64>
		+ TryFrom<u8,    Error = Infallible>
		+ TryFrom<usize>
		+ TryInto<i128>
		+ TryInto<i16>
		+ TryInto<i32>
		+ TryInto<i64>
		+ TryInto<i8>
		+ TryInto<isize>
		+ TryInto<u128>
		+ TryInto<u16>
		+ TryInto<u32>
		+ TryInto<u64>
		+ TryInto<u8>
		+ TryInto<usize>
		+ Unpin
		+ UnwindSafe
		+ UpperExp
		+ UpperHex
		+ UseCloned
		// Arithmetic operators:
		+ Add<          Output = Self>
		+ BitAnd<       Output = Self>
		+ BitOr<        Output = Self>
		+ BitXor<       Output = Self>
		+ Div<          Output = Self>
		+ Mul<          Output = Self>
		+ Not<          Output = Self>
		+ Rem<          Output = Self>
		+ Shl<          Output = Self>
		+ Shl<   u8,    Output = Self>
		+ Shl<   u16,   Output = Self>
		+ Shl<   u32,   Output = Self>
		+ Shl<   u64,   Output = Self>
		+ Shl<   u128,  Output = Self>
		+ Shl<   usize, Output = Self>
		+ Shl<   i8,    Output = Self>
		+ Shl<   i16,   Output = Self>
		+ Shl<   i32,   Output = Self>
		+ Shl<   i64,   Output = Self>
		+ Shl<   i128,  Output = Self>
		+ Shl<   isize, Output = Self>
		+ Shr<          Output = Self>
		+ Shr<   u8,    Output = Self>
		+ Shr<   u16,   Output = Self>
		+ Shr<   u32,   Output = Self>
		+ Shr<   u64,   Output = Self>
		+ Shr<   u128,  Output = Self>
		+ Shr<   usize, Output = Self>
		+ Shr<   i8,    Output = Self>
		+ Shr<   i16,   Output = Self>
		+ Shr<   i32,   Output = Self>
		+ Shr<   i64,   Output = Self>
		+ Shr<   i128,  Output = Self>
		+ Shr<   isize, Output = Self>
		+ Sub<          Output = Self>
		// Assigning arithmetic operators:
		+ AddAssign
		+ BitAndAssign
		+ BitOrAssign
		+ BitXorAssign
		+ DivAssign
		+ MulAssign
		+ RemAssign
		+ ShlAssign
		+ ShlAssign<u8>
		+ ShlAssign<u16>
		+ ShlAssign<u32>
		+ ShlAssign<u64>
		+ ShlAssign<u128>
		+ ShlAssign<usize>
		+ ShlAssign<i8>
		+ ShlAssign<i16>
		+ ShlAssign<i32>
		+ ShlAssign<i64>
		+ ShlAssign<i128>
		+ ShlAssign<isize>
		+ ShrAssign
		+ ShrAssign<u8>
		+ ShrAssign<u16>
		+ ShrAssign<u32>
		+ ShrAssign<u64>
		+ ShrAssign<u128>
		+ ShrAssign<usize>
		+ ShrAssign<i8>
		+ ShrAssign<i16>
		+ ShrAssign<i32>
		+ ShrAssign<i64>
		+ ShrAssign<i128>
		+ ShrAssign<isize>
		+ SubAssign,
{
	/// The equivalent, signed, integral type.
	type Int: Int<
		Uint  = Self,
		Bytes = Self::Bytes,
	>;

	/// The array type that represents the bytes of this type.
	type Bytes:
		Array<Scalar = u8>
		+ 'static
		+ Any
		+ CloneToUninit
		+ ConstParamTy_
		+ Copy
		+ Debug
		+ Eq
		+ Freeze
		+ Hash
		+ Ord
		+ PartialEq
		+ PartialEq<[u8]>
		+ PartialOrd
		+ RefUnwindSafe
		+ Send
		+ Sync
		+ ToOwned
		+ Unpin
		+ UnwindSafe;

	/// See <code>[u32]::[BITS](u32::BITS)</code>.
	const BITS: u32;

	/// See <code>[u32]::[MIN](u32::MIN)</code>.
	const MIN: Self;

	/// See <code>[u32]::[MAX](u32::MAX)</code>.
	const MAX: Self;

	/// Equivalent to <code>Self::[from](From::from)(0u8)</code>.
	///
	/// # Examples
	///
	/// ```rust
	/// use multitype::Uint;
	///
	/// let v0 = u128::ZERO;
	/// let v1 = 0u128;
	///
	/// assert_eq!(v0, v1);
	/// ```
	const ZERO: Self;

	/// Equivalent to <code>Self::[from](From::from)(1u8)</code>.
	///
	/// # Examples
	///
	/// ```rust
	/// use multitype::Uint;
	///
	/// let v0 = u128::ONE;
	/// let v1 = 1u128;
	///
	/// assert_eq!(v0, v1);
	/// ```
	const ONE: Self;

	/// See <code>[u32]::[from_le](u32::from_le)</code>.
	#[must_use]
	fn from_le(value: Self) -> Self;

	/// See <code>[u32]::[from_be](u32::from_be)</code>.
	#[must_use]
	fn from_be(value: Self) -> Self;

	/// See <code>[u32]::[from_ne_bytes](u32::from_ne_bytes)</code>.
	#[must_use]
	fn from_ne_bytes(bytes: Self::Bytes) -> Self;

	/// See <code>[u32]::[from_le_bytes](u32::from_le_bytes)</code>.
	#[must_use]
	fn from_le_bytes(bytes: Self::Bytes) -> Self;

	/// See <code>[u32]::[from_be_bytes](u32::from_be_bytes)</code>.
	#[must_use]
	fn from_be_bytes(bytes: Self::Bytes) -> Self;

	/// See <code>[u32]::[from_str_radix](u32::from_str_radix)</code>.
	fn from_str_radix(s: &str, radix: u32) -> Result<Self, ParseIntError>;

	/// See <code>[u32]::[div_ceil](u32::div_ceil)</code>.
	#[must_use]
	fn div_ceil(self, rhs: Self) -> Self;

	/// See <code>[u32]::[div_euclid](u32::div_euclid)</code>.
	#[must_use]
	fn div_euclid(self, rhs: Self) -> Self;

	/// See <code>[u32]::[rem_euclid](u32::rem_euclid)</code>.
	#[must_use]
	fn rem_euclid(self, rhs: Self) -> Self;

	/// See <code>[u32]::[rotate_left](u32::rotate_left)</code>.
	#[must_use]
	fn rotate_left(self, rhs: u32) -> Self;

	/// See <code>[u32]::[rotate_right](u32::rotate_right)</code>.
	#[must_use]
	fn rotate_right(self, rhs: u32) -> Self;

	/// See <code>[u32]::[swap_bytes](u32::swap_bytes)</code>.
	#[must_use]
	fn swap_bytes(self) -> Self;

	/// See <code>[u32]::[reverse_bits](u32::reverse_bits)</code>.
	#[must_use]
	fn reverse_bits(self) -> Self;

	/// See <code>[u32]::[pow](u32::pow)</code>.
	#[must_use]
	fn pow(self, exp: u32) -> Self;

	/// See <code>[u32]::[isqrt](u32::isqrt)</code>.
	#[must_use]
	fn isqrt(self) -> Self;

	/// See <code>[u32]::[ilog](u32::ilog)</code>.
	#[must_use]
	fn ilog(self, base: Self) -> u32;

	/// See <code>[u32]::[ilog2](u32::ilog2)</code>.
	#[must_use]
	fn ilog2(self) -> u32;

	/// See <code>[u32]::[ilog10](u32::ilog10)</code>.
	#[must_use]
	fn ilog10(self) -> u32;

	/// See <code>[u32]::[abs_diff](u32::abs_diff)</code>.
	#[must_use]
	fn abs_diff(self, rhs: Self) -> Self;

	/// See <code>[u32]::[midpoint](u32::midpoint)</code>.
	#[must_use]
	fn midpoint(self, rhs: Self) -> Self;

	/// See <code>[u32]::[count_zeros](u32::count_zeros)</code>.
	#[must_use]
	fn count_zeros(self) -> u32;

	/// See <code>[u32]::[count_ones](u32::count_ones)</code>.
	#[must_use]
	fn count_ones(self) -> u32;

	/// See <code>[u32]::[leading_zeros](u32::leading_zeros)</code>.
	#[must_use]
	fn leading_zeros(self) -> u32;

	/// See <code>[u32]::[leading_ones](u32::leading_ones)</code>.
	#[must_use]
	fn leading_ones(self) -> u32;

	/// See <code>[u32]::[trailing_zeros](u32::trailing_zeros)</code>.
	#[must_use]
	fn trailing_zeros(self) -> u32;

	/// See <code>[u32]::[trailing_ones](u32::trailing_ones)</code>.
	#[must_use]
	fn trailing_ones(self) -> u32;

	/// See <code>[u32]::[is_multiple_of](u32::is_multiple_of)</code>.
	#[must_use]
	fn is_multiple_of(self, rhs: Self) -> bool;

	/// See <code>[u32]::[is_power_of_two](u32::is_power_of_two)</code>.
	#[must_use]
	fn is_power_of_two(self) -> bool;

	/// See <code>[u32]::[next_multiple_of](u32::next_multiple_of)</code>.
	#[must_use]
	fn next_multiple_of(self, rhs: Self) -> Self;

	/// See <code>[u32]::[next_power_of_two](u32::next_power_of_two)</code>.
	#[must_use]
	fn next_power_of_two(self) -> Self;

	/// See <code>[u32]::[checked_add](u32::checked_add)</code>.
	#[must_use]
	fn checked_add(self, rhs: Self) -> Option<Self>;

	/// See <code>[u32]::[checked_add_signed](u32::checked_add_signed)</code>.
	#[must_use]
	fn checked_add_signed(self, rhs: <Self as Uint>::Int) -> Option<Self>;

	/// See <code>[u32]::[checked_sub](u32::checked_sub)</code>.
	#[must_use]
	fn checked_sub(self, rhs: Self) -> Option<Self>;

	/// See <code>[u32]::[checked_sub_signed](u32::checked_sub_signed)</code>.
	#[must_use]
	fn checked_sub_signed(self, rhs: <Self as Uint>::Int) -> Option<Self>;

	/// See <code>[u32]::[checked_mul](u32::checked_mul)</code>.
	#[must_use]
	fn checked_mul(self, rhs: Self) -> Option<Self>;

	/// See <code>[u32]::[checked_div](u32::checked_div)</code>.
	#[must_use]
	fn checked_div(self, rhs: Self) -> Option<Self>;

	/// See <code>[u32]::[checked_div_euclid](u32::checked_div_euclid)</code>.
	#[must_use]
	fn checked_div_euclid(self, rhs: Self) -> Option<Self>;

 	/// See <code>[u32]::[checked_rem](u32::checked_rem)</code>.
	#[must_use]
	fn checked_rem(self, rhs: Self) -> Option<Self>;

	/// See <code>[u32]::[checked_rem_euclid](u32::checked_rem_euclid)</code>.
	#[must_use]
	fn checked_rem_euclid(self, rhs: Self) -> Option<Self>;

	/// See <code>[u32]::[checked_shl](u32::checked_shl)</code>.
	#[must_use]
	fn checked_shl(self, rhs: u32) -> Option<Self>;

	/// See <code>[u32]::[checked_shr](u32::checked_shr)</code>.
	#[must_use]
	fn checked_shr(self, rhs: u32) -> Option<Self>;

	/// See <code>[u32]::[checked_neg](u32::checked_neg)</code>.
	#[must_use]
	fn checked_neg(self) -> Option<Self>;

	/// See <code>[u32]::[checked_pow](u32::checked_pow)</code>.
	#[must_use]
	fn checked_pow(self, exp: u32) -> Option<Self>;

	/// See <code>[u32]::[checked_ilog](u32::checked_ilog)</code>.
	#[must_use]
	fn checked_ilog(self, base: Self) -> Option<u32>;

	/// See <code>[u32]::[checked_ilog2](u32::checked_ilog2)</code>.
	#[must_use]
	fn checked_ilog2(self) -> Option<u32>;

	/// See <code>[u32]::[checked_ilog10](u32::checked_ilog10)</code>.
	#[must_use]
	fn checked_ilog10(self) -> Option<u32>;

	/// See <code>[u32]::[checked_next_multiple_of](u32::checked_next_multiple_of)</code>.
	#[must_use]
	fn checked_next_multiple_of(self, rhs: Self) -> Option<Self>;

	/// See <code>[u32]::[checked_next_power_of_two](u32::checked_next_power_of_two)</code>.
	#[must_use]
	fn checked_next_power_of_two(self) -> Option<Self>;

	/// See <code>[u32]::[strict_add](u32::strict_add)</code>.
	#[must_use]
	fn strict_add(self, rhs: Self) -> Self;

	/// See <code>[u32]::[strict_add_signed](u32::strict_add_signed)</code>.
	#[must_use]
	fn strict_add_signed(self, rhs: <Self as Uint>::Int) -> Self;

	/// See <code>[u32]::[strict_sub](u32::strict_sub)</code>.
	#[must_use]
	fn strict_sub(self, rhs: Self) -> Self;

	/// See <code>[u32]::[strict_sub_signed](u32::strict_sub_signed)</code>.
	#[must_use]
	fn strict_sub_signed(self, rhs: <Self as Uint>::Int) -> Self;

	/// See <code>[u32]::[strict_mul](u32::strict_mul)</code>.
	#[must_use]
	fn strict_mul(self, rhs: Self) -> Self;

	/// See <code>[u32]::[strict_div](u32::strict_div)</code>.
	#[must_use]
	fn strict_div(self, rhs: Self) -> Self;

	/// See <code>[u32]::[strict_div_euclid](u32::strict_div_euclid)</code>.
	#[must_use]
	fn strict_div_euclid(self, rhs: Self) -> Self;

	/// See <code>[u32]::[strict_rem](u32::strict_rem)</code>.
	#[must_use]
	fn strict_rem(self, rhs: Self) -> Self;

	/// See <code>[u32]::[strict_rem_euclid](u32::strict_rem_euclid)</code>.
	#[must_use]
	fn strict_rem_euclid(self, rhs: Self) -> Self;

	/// See <code>[u32]::[strict_shl](u32::strict_shl)</code>.
	#[must_use]
	fn strict_shl(self, rhs: u32) -> Self;

	/// See <code>[u32]::[strict_shr](u32::strict_shr)</code>.
	#[must_use]
	fn strict_shr(self, rhs: u32) -> Self;

	/// See <code>[u32]::[strict_neg](u32::strict_neg)</code>.
	#[must_use]
	fn strict_neg(self) -> Self;

	/// See <code>[u32]::[strict_pow](u32::strict_pow)</code>.
	#[must_use]
	fn strict_pow(self, rhs: u32) -> Self;

	/// See <code>[u32]::[unchecked_add](u32::unchecked_add)</code>.
	#[expect(clippy::missing_safety_doc)]
	#[must_use]
	unsafe fn unchecked_add(self, rhs: Self) -> Self;

	/// See <code>[u32]::[unchecked_sub](u32::unchecked_sub)</code>.
	#[expect(clippy::missing_safety_doc)]
	#[must_use]
	unsafe fn unchecked_sub(self, rhs: Self) -> Self;

	/// See <code>[u32]::[unchecked_mul](u32::unchecked_mul)</code>.
	#[expect(clippy::missing_safety_doc)]
	#[must_use]
	unsafe fn unchecked_mul(self, rhs: Self) -> Self;

	/// See <code>[u32]::[overflowing_add](u32::overflowing_add)</code>.
	#[must_use]
	fn overflowing_add(self, rhs: Self) -> (Self, bool);

	/// See <code>[u32]::[overflowing_add_signed](u32::overflowing_add_signed)</code>.
	#[must_use]
	fn overflowing_add_signed(self, rhs: <Self as Uint>::Int) -> (Self, bool);

	/// See <code>[u32]::[overflowing_sub](u32::overflowing_sub)</code>.
	#[must_use]
	fn overflowing_sub(self, rhs: Self) -> (Self, bool);

	/// See <code>[u32]::[overflowing_sub_signed](u32::overflowing_sub_signed)</code>.
	#[must_use]
	fn overflowing_sub_signed(self, rhs: <Self as Uint>::Int) -> (Self, bool);

	/// See <code>[u32]::[overflowing_mul](u32::overflowing_mul)</code>.
	#[must_use]
	fn overflowing_mul(self, rhs: Self) -> (Self, bool);

	/// See <code>[u32]::[overflowing_div](u32::overflowing_div)</code>.
	#[must_use]
	fn overflowing_div(self, rhs: Self) -> (Self, bool);

	/// See <code>[u32]::[overflowing_div_euclid](u32::overflowing_div_euclid)</code>.
	#[must_use]
	fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool);

	/// See <code>[u32]::[overflowing_rem](u32::overflowing_rem)</code>.
	#[must_use]
	fn overflowing_rem(self, rhs: Self) -> (Self, bool);

	/// See <code>[u32]::[overflowing_rem_euclid](u32::overflowing_rem_euclid)</code>.
	#[must_use]
	fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool);

	/// See <code>[u32]::[overflowing_shl](u32::overflowing_shl)</code>.
	#[must_use]
	fn overflowing_shl(self, rhs: u32) -> (Self, bool);

	/// See <code>[u32]::[overflowing_shr](u32::overflowing_shr)</code>.
	#[must_use]
	fn overflowing_shr(self, rhs: u32) -> (Self, bool);

	/// See <code>[u32]::[overflowing_neg](u32::overflowing_neg)</code>.
	#[must_use]
	fn overflowing_neg(self) -> (Self, bool);

	/// See <code>[u32]::[overflowing_pow](u32::overflowing_pow)</code>.
	#[must_use]
	fn overflowing_pow(self, exp: u32) -> (Self, bool);

	/// See <code>[u32]::[carrying_add](u32::carrying_add)</code>.
	#[must_use]
	fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool);

	/// See <code>[u32]::[carrying_mul](u32::carrying_mul)</code>.
	#[must_use]
	fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self);

	/// See <code>[u32]::[carrying_mul_add](u32::carrying_mul_add)</code>.
	#[must_use]
	fn carrying_mul_add(self, mul: Self, add: Self, carry: Self) -> (Self, Self);

	/// See <code>[u32]::[borrowing_sub](u32::borrowing_sub)</code>.
	#[must_use]
	fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool);

	/// See <code>[u32]::[wrapping_add](u32::wrapping_add)</code>.
	#[must_use]
	fn wrapping_add(self, rhs: Self) -> Self;

	/// See <code>[u32]::[wrapping_add_signed](u32::wrapping_add_signed)</code>.
	#[must_use]
	fn wrapping_add_signed(self, rhs: <Self as Uint>::Int) -> Self;

	/// See <code>[u32]::[wrapping_sub](u32::wrapping_sub)</code>.
	#[must_use]
	fn wrapping_sub(self, rhs: Self) -> Self;

	/// See <code>[u32]::[wrapping_sub_signed](u32::wrapping_sub_signed)</code>.
	#[must_use]
	fn wrapping_sub_signed(self, rhs: <Self as Uint>::Int) -> Self;

	/// See <code>[u32]::[wrapping_mul](u32::wrapping_mul)</code>.
	#[must_use]
	fn wrapping_mul(self, rhs: Self) -> Self;

	/// See <code>[u32]::[wrapping_div](u32::wrapping_div)</code>.
	#[must_use]
	fn wrapping_div(self, rhs: Self) -> Self;

	/// See <code>[u32]::[wrapping_div_euclid](u32::wrapping_div_euclid)</code>.
	#[must_use]
	fn wrapping_div_euclid(self, rhs: Self) -> Self;

	/// See <code>[u32]::[wrapping_rem](u32::wrapping_rem)</code>.
	#[must_use]
	fn wrapping_rem(self, rhs: Self) -> Self;

	/// See <code>[u32]::[wrapping_rem_euclid](u32::wrapping_rem_euclid)</code>.
	#[must_use]
	fn wrapping_rem_euclid(self, rhs: Self) -> Self;

	/// See <code>[u32]::[wrapping_shl](u32::wrapping_shl)</code>.
	#[must_use]
	fn wrapping_shl(self, rhs: u32) -> Self;

	/// See <code>[u32]::[wrapping_shr](u32::wrapping_shr)</code>.
	#[must_use]
	fn wrapping_shr(self, rhs: u32) -> Self;

	/// See <code>[u32]::[wrapping_neg](u32::wrapping_neg)</code>.
	#[must_use]
	fn wrapping_neg(self) -> Self;

	/// See <code>[u32]::[wrapping_pow](u32::wrapping_pow)</code>.
	#[must_use]
	fn wrapping_pow(self, exp: u32) -> Self;

	/// See <code>[u32]::[saturating_add](u32::saturating_add)</code>.
	#[must_use]
	fn saturating_add(self, rhs: Self) -> Self;

	/// See <code>[u32]::[saturating_add_signed](u32::saturating_add_signed)</code>.
	#[must_use]
	fn saturating_add_signed(self, rhs: <Self as Uint>::Int) -> Self;

	/// See <code>[u32]::[saturating_sub](u32::saturating_sub)</code>.
	#[must_use]
	fn saturating_sub(self, rhs: Self) -> Self;

	/// See <code>[u32]::[saturating_sub_signed](u32::saturating_sub_signed)</code>.
	#[must_use]
	fn saturating_sub_signed(self, rhs: <Self as Uint>::Int) -> Self;

	/// See <code>[u32]::[saturating_mul](u32::saturating_mul)</code>.
	#[must_use]
	fn saturating_mul(self, rhs: Self) -> Self;

	/// See <code>[u32]::[saturating_div](u32::saturating_div)</code>.
	#[must_use]
	fn saturating_div(self, rhs: Self) -> Self;

	/// See <code>[u32]::[saturating_pow](u32::saturating_pow)</code>.
	#[must_use]
	fn saturating_pow(self, exp: u32) -> Self;

	/// See <code>[u32]::[unbounded_shl](u32::unbounded_shl)</code>.
	#[must_use]
	fn unbounded_shl(self, rhs: u32) -> Self;

	/// See <code>[u32]::[unbounded_shr](u32::unbounded_shr)</code>.
	#[must_use]
	fn unbounded_shr(self, rhs: u32) -> Self;

	/// See <code>[u32]::[cast_signed](u32::cast_signed)</code>.
	#[must_use]
	fn cast_signed(self) -> <Self as Uint>::Int;

	/// See <code>[u32]::[to_le](u32::to_le)</code>.
	#[must_use]
	fn to_le(self) -> Self;

	/// See <code>[u32]::[to_be](u32::to_be)</code>.
	#[must_use]
	fn to_be(self) -> Self;

	/// See <code>[u32]::[to_ne_bytes](u32::to_ne_bytes)</code>.
	#[must_use]
	fn to_ne_bytes(self) -> Self::Bytes;

	/// See <code>[u32]::[to_le_bytes](u32::to_le_bytes)</code>.
	#[must_use]
	fn to_le_bytes(self) -> Self::Bytes;

	/// See <code>[u32]::[to_be_bytes](u32::to_be_bytes)</code>.
	#[must_use]
	fn to_be_bytes(self) -> Self::Bytes;
}

macro_rules! impl_uint {
	{ $($Ty:ty { Int = $Int:ty, Bytes = $Bytes:ty$(,)? }),*$(,)? } => {$(
		impl ::multitype::seal::Uint for $Ty {}

		unsafe impl ::multitype::Uint for $Ty {
			type Int = $Int;

			type Bytes = $Bytes;

			const BITS: ::core::primitive::u32 = Self::BITS;

			const MIN: Self = Self::MIN;
			const MAX: Self = Self::MAX;

			const ZERO: Self = 0;
			const ONE:  Self = 1;

			#[inline(always)]
			#[track_caller]
			fn from_le(value: Self) -> Self {
				Self::from_le(value)
			}

			#[inline(always)]
			#[track_caller]
			fn from_be(value: Self) -> Self {
				Self::from_be(value)
			}

			#[inline(always)]
			#[track_caller]
			fn from_ne_bytes(bytes: Self::Bytes) -> Self {
				Self::from_ne_bytes(bytes)
			}

			#[inline(always)]
			#[track_caller]
			fn from_le_bytes(bytes: Self::Bytes) -> Self {
				Self::from_le_bytes(bytes)
			}

			#[inline(always)]
			#[track_caller]
			fn from_be_bytes(bytes: Self::Bytes) -> Self {
				Self::from_be_bytes(bytes)
			}

			#[inline(always)]
			#[track_caller]
			fn from_str_radix(s: &str, radix: ::core::primitive::u32) -> ::core::result::Result<Self, ::core::num::ParseIntError> {
				Self::from_str_radix(s, radix)
			}

			#[inline(always)]
			#[track_caller]
			fn div_ceil(self, rhs: Self) -> Self {
				self.div_ceil(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn div_euclid(self, rhs: Self) -> Self {
				self.div_euclid(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn rem_euclid(self, rhs: Self) -> Self {
				self.rem_euclid(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn rotate_left(self, rhs: ::core::primitive::u32) -> Self {
				self.rotate_left(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn rotate_right(self, rhs: ::core::primitive::u32) -> Self {
				self.rotate_right(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn swap_bytes(self) -> Self {
				self.swap_bytes()
			}

			#[inline(always)]
			#[track_caller]
			fn reverse_bits(self) -> Self {
				self.reverse_bits()
			}

			#[inline(always)]
			#[track_caller]
			fn pow(self, exp: ::core::primitive::u32) -> Self {
				self.pow(exp)
			}

			#[inline(always)]
			#[track_caller]
			fn isqrt(self) -> Self {
				self.isqrt()
			}

			#[inline(always)]
			#[track_caller]
			fn ilog(self, base: Self) -> ::core::primitive::u32 {
				self.ilog(base)
			}

			#[inline(always)]
			#[track_caller]
			fn ilog2(self) -> ::core::primitive::u32 {
				self.ilog2()
			}

			#[inline(always)]
			#[track_caller]
			fn ilog10(self) -> ::core::primitive::u32 {
				self.ilog10()
			}

			#[inline(always)]
			#[track_caller]
			fn abs_diff(self, rhs: Self) -> Self {
				self.abs_diff(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn midpoint(self, rhs: Self) -> Self {
				self.midpoint(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn count_zeros(self) -> ::core::primitive::u32 {
				self.count_zeros()
			}

			#[inline(always)]
			#[track_caller]
			fn count_ones(self) -> ::core::primitive::u32 {
				self.count_ones()
			}

			#[inline(always)]
			#[track_caller]
			fn leading_zeros(self) -> ::core::primitive::u32 {
				self.leading_zeros()
			}

			#[inline(always)]
			#[track_caller]
			fn leading_ones(self) -> ::core::primitive::u32 {
				self.leading_ones()
			}

			#[inline(always)]
			#[track_caller]
			fn trailing_zeros(self) -> ::core::primitive::u32 {
				self.trailing_zeros()
			}

			#[inline(always)]
			#[track_caller]
			fn trailing_ones(self) -> ::core::primitive::u32 {
				self.trailing_ones()
			}

			// BACKPORT(1.87)
			#[inline]
			fn is_multiple_of(self, rhs: Self) -> ::core::primitive::bool {
				match rhs {
					0 => self == 0,
					_ => self % rhs == 0,
				}
			}

			#[inline(always)]
			#[track_caller]
			fn is_power_of_two(self) -> ::core::primitive::bool {
				self.is_power_of_two()
			}

			#[inline(always)]
			#[track_caller]
			fn next_multiple_of(self, rhs: Self) -> Self {
				self.next_multiple_of(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn next_power_of_two(self) -> Self {
				self.next_power_of_two()
			}

			#[inline(always)]
			#[track_caller]
			fn checked_add(self, rhs: Self) -> ::core::option::Option<Self> {
				self.checked_add(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn checked_add_signed(self, rhs: <Self as Uint>::Int) -> ::core::option::Option<Self> {
				self.checked_add_signed(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn checked_sub(self, rhs: Self) -> ::core::option::Option<Self> {
				self.checked_sub(rhs)
			}

			// BACKPORT(1.90)
			#[inline(always)]
			#[track_caller]
			fn checked_sub_signed(self, rhs: <Self as Uint>::Int) -> ::core::option::Option<Self> {
				let (result, overflow) = <Self as Uint>::overflowing_sub_signed(self, rhs);

				overflow.then_some(result)
			}

			#[inline(always)]
			#[track_caller]
			fn checked_mul(self, rhs: Self) -> ::core::option::Option<Self> {
				self.checked_mul(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn checked_div(self, rhs: Self) -> ::core::option::Option<Self> {
				self.checked_div(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
				self.checked_div_euclid(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn checked_rem(self, rhs: Self) -> ::core::option::Option<Self> {
				self.checked_rem(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
				self.checked_rem_euclid(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn checked_shl(self, rhs: ::core::primitive::u32) -> ::core::option::Option<Self> {
				self.checked_shl(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn checked_shr(self, rhs: ::core::primitive::u32) -> ::core::option::Option<Self> {
				self.checked_shr(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn checked_neg(self) -> ::core::option::Option<Self> {
				self.checked_neg()
			}

			#[inline(always)]
			#[track_caller]
			fn checked_pow(self, exp: ::core::primitive::u32) -> ::core::option::Option<Self> {
				self.checked_pow(exp)
			}

			#[inline(always)]
			#[track_caller]
			fn checked_ilog(self, base: Self) -> ::core::option::Option<::core::primitive::u32> {
				self.checked_ilog(base)
			}

			#[inline(always)]
			#[track_caller]
			fn checked_ilog2(self) -> ::core::option::Option<::core::primitive::u32> {
				self.checked_ilog2()
			}

			#[inline(always)]
			#[track_caller]
			fn checked_ilog10(self) -> ::core::option::Option<::core::primitive::u32> {
				self.checked_ilog10()
			}

			#[inline(always)]
			#[track_caller]
			fn checked_next_multiple_of(self, rhs: Self) -> ::core::option::Option<Self> {
				self.checked_next_multiple_of(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn checked_next_power_of_two(self) -> ::core::option::Option<Self> {
				self.checked_next_power_of_two()
			}

			// BACKPORT(1.91)
			#[inline]
			#[track_caller]
			fn strict_add(self, rhs: Self) -> Self {
				self.checked_add(rhs).expect("attempt to add with overflow")
			}

			// BACKPORT(1.91)
			#[inline]
			#[track_caller]
			fn strict_add_signed(self, rhs: <Self as Uint>::Int) -> Self {
				self.checked_add_signed(rhs).expect("attempt to add with overflow")
			}

			// BACKPORT(1.91)
			#[inline]
			#[track_caller]
			fn strict_sub(self, rhs: Self) -> Self {
				self.checked_sub(rhs).expect("attempt to subtract with overflow")
			}

			// BACKPORT(1.91)
			#[inline]
			#[track_caller]
			fn strict_sub_signed(self, rhs: <Self as Uint>::Int) -> Self {
				<Self as Uint>::checked_sub_signed(self, rhs).expect("attempt to subtract with overflow")
			}

			// BACKPORT(1.91)
			#[inline]
			#[track_caller]
			fn strict_mul(self, rhs: Self) -> Self {
				self.checked_mul(rhs).expect("attempt to multiply with overflow")
			}

			// BACKPORT(1.91)
			#[inline]
			#[track_caller]
			fn strict_div(self, rhs: Self) -> Self {
				self.checked_div(rhs).expect("attempt to divide with overflow")
			}

			// BACKPORT(1.91)
			#[inline]
			#[track_caller]
			fn strict_div_euclid(self, rhs: Self) -> Self {
				self.checked_div_euclid(rhs).expect("attempt to divide with overflow")
			}

			// BACKPORT(1.91)
			#[inline]
			#[track_caller]
			fn strict_rem(self, rhs: Self) -> Self {
				self.checked_rem(rhs).expect("attempt to calculate the remainder with overflow")
			}

			// BACKPORT(1.91)
			#[inline]
			#[track_caller]
			fn strict_rem_euclid(self, rhs: Self) -> Self {
				self.checked_rem_euclid(rhs).expect("attempt to calculate the remainder with overflow")
			}

			// BACKPORT(1.91)
			#[inline]
			#[track_caller]
			fn strict_shl(self, rhs: ::core::primitive::u32) -> Self {
				self.checked_shl(rhs).expect("attempt to shift left with overflow")
			}

			// BACKPORT(1.91)
			#[inline]
			#[track_caller]
			fn strict_shr(self, rhs: ::core::primitive::u32) -> Self {
				self.checked_shr(rhs).expect("attempt to shift right with overflow")
			}

			// BACKPORT(1.91)
			#[inline]
			#[track_caller]
			fn strict_neg(self) -> Self {
				self.checked_neg().expect("attempt to negate with overflow")
			}

			// BACKPORT(1.91)
			#[inline]
			#[track_caller]
			fn strict_pow(self, exp: ::core::primitive::u32) -> Self {
				self.checked_pow(exp).expect("attempt to multiply with overflow")
			}

			#[inline(always)]
			#[track_caller]
			unsafe fn unchecked_add(self, rhs: Self) -> Self {
				unsafe { self.unchecked_add(rhs) }
			}

			#[inline(always)]
			#[track_caller]
			unsafe fn unchecked_sub(self, rhs: Self) -> Self {
				unsafe { self.unchecked_sub(rhs) }
			}

			#[inline(always)]
			#[track_caller]
			unsafe fn unchecked_mul(self, rhs: Self) -> Self {
				unsafe { self.unchecked_mul(rhs) }
			}

			#[inline(always)]
			#[track_caller]
			fn overflowing_add(self, rhs: Self) -> (Self, ::core::primitive::bool) {
				self.overflowing_add(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn overflowing_add_signed(self, rhs: <Self as Uint>::Int) -> (Self, ::core::primitive::bool) {
				self.overflowing_add_signed(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn overflowing_sub(self, rhs: Self) -> (Self, ::core::primitive::bool) {
				self.overflowing_sub(rhs)
			}

			// BACKPORT(1.90)
			#[inline]
			fn overflowing_sub_signed(self, rhs: <Self as Uint>::Int) -> (Self, ::core::primitive::bool) {
				let (result, mut overflow) = <Self as Uint>::overflowing_sub(self, rhs as Self);

				overflow ^= rhs.is_negative();

				(result, overflow)
			}

			#[inline(always)]
			#[track_caller]
			fn overflowing_mul(self, rhs: Self) -> (Self, ::core::primitive::bool) {
				self.overflowing_mul(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn overflowing_div(self, rhs: Self) -> (Self, ::core::primitive::bool) {
				self.overflowing_div(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn overflowing_div_euclid(self, rhs: Self) -> (Self, ::core::primitive::bool) {
				self.overflowing_div_euclid(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn overflowing_rem(self, rhs: Self) -> (Self, ::core::primitive::bool) {
				self.overflowing_rem(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn overflowing_rem_euclid(self, rhs: Self) -> (Self, ::core::primitive::bool) {
				self.overflowing_rem_euclid(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn overflowing_shl(self, rhs: ::core::primitive::u32) -> (Self, ::core::primitive::bool) {
				self.overflowing_shl(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn overflowing_shr(self, rhs: ::core::primitive::u32) -> (Self, ::core::primitive::bool) {
				self.overflowing_shr(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn overflowing_neg(self) -> (Self, ::core::primitive::bool) {
				self.overflowing_neg()
			}

			#[inline(always)]
			#[track_caller]
			fn overflowing_pow(self, exp: ::core::primitive::u32) -> (Self, ::core::primitive::bool) {
				self.overflowing_pow(exp)
			}

			// BACKPORT(1.91)
			#[inline]
			fn carrying_add(self, rhs: Self, carry: ::core::primitive::bool) -> (Self, ::core::primitive::bool) {
				let (tmp, carry0) = self.overflowing_add(rhs);
				let (low, carry1) = tmp.overflowing_add(carry.into());

				let high = unsafe { DisjointBitOr::disjoint_bitor(carry0, carry1) };

				(low, high)
			}

			// BACKPORT(1.91)
			#[inline]
			fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self) {
				<Self as Uint>::carrying_mul_add(self, rhs, carry, 0)
			}

			// BACKPORT(1.91)
			#[inline]
			fn carrying_mul_add(self, mul: Self, add: Self, carry: Self) -> (Self, Self) {
				<Self as CarryingMulAdd>::carrying_mul_add(self, mul, add, carry)
			}

			// BACKPORT(1.91)
			#[inline]
			fn borrowing_sub(self, rhs: Self, borrow: ::core::primitive::bool) -> (Self, ::core::primitive::bool) {
				let (tmp,     carry0) = self.overflowing_sub(rhs);
				let (result0, carry1) = tmp.overflowing_sub(borrow.into());

				let result1 = unsafe { DisjointBitOr::disjoint_bitor(carry0, carry1) };

				(result0, result1)
			}

			#[inline(always)]
			#[track_caller]
			fn wrapping_add(self, rhs: Self) -> Self {
				self.wrapping_add(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn wrapping_add_signed(self, rhs: <Self as Uint>::Int) -> Self {
				self.wrapping_add_signed(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn wrapping_sub(self, rhs: Self) -> Self {
				self.wrapping_sub(rhs)
			}

			// BACKPORT(1.90)
			#[inline]
			fn wrapping_sub_signed(self, rhs: <Self as Uint>::Int) -> Self {
				self.wrapping_sub(rhs as Self)
			}

			#[inline(always)]
			#[track_caller]
			fn wrapping_mul(self, rhs: Self) -> Self {
				self.wrapping_mul(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn wrapping_div(self, rhs: Self) -> Self {
				self.wrapping_div(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn wrapping_div_euclid(self, rhs: Self) -> Self {
				self.wrapping_div_euclid(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn wrapping_rem(self, rhs: Self) -> Self {
				self.wrapping_rem(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn wrapping_rem_euclid(self, rhs: Self) -> Self {
				self.wrapping_rem_euclid(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn wrapping_shl(self, rhs: ::core::primitive::u32) -> Self {
				self.wrapping_shl(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn wrapping_shr(self, rhs: ::core::primitive::u32) -> Self {
				self.wrapping_shr(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn wrapping_neg(self) -> Self {
				self.wrapping_neg()
			}

			#[inline(always)]
			#[track_caller]
			fn wrapping_pow(self, exp: ::core::primitive::u32) -> Self {
				self.wrapping_pow(exp)
			}

			#[inline(always)]
			#[track_caller]
			fn saturating_add(self, rhs: Self) -> Self {
				self.saturating_add(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn saturating_add_signed(self, rhs: <Self as Uint>::Int) -> Self {
				self.saturating_add_signed(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn saturating_sub(self, rhs: Self) -> Self {
				self.saturating_sub(rhs)
			}

			// BACKPORT(1.90)
			#[inline]
			fn saturating_sub_signed(self, rhs: <Self as Uint>::Int) -> Self {
				let (result, overflow) = <Self as Uint>::overflowing_sub_signed(self, rhs);

				if !overflow {
					result
				} else if rhs.is_negative() {
					Self::MAX
				} else {
					Self::MIN
				}
			}

			#[inline(always)]
			#[track_caller]
			fn saturating_mul(self, rhs: Self) -> Self {
				self.saturating_mul(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn saturating_div(self, rhs: Self) -> Self {
				self.saturating_div(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn saturating_pow(self, exp: ::core::primitive::u32) -> Self {
				self.saturating_pow(exp)
			}

			// BACKPORT(1.87)
			#[inline]
			fn unbounded_shl(self, rhs: ::core::primitive::u32) -> Self {
				if rhs < Self::BITS {
					self << rhs
				} else {
					0
				}
			}

			// BACKPORT(1.87)
			#[inline]
			fn unbounded_shr(self, rhs: ::core::primitive::u32) -> Self {
				if rhs < Self::BITS {
					self >> rhs
				} else {
					0
				}
			}

			// BACKPORT(1.87)
			#[expect(clippy::cast_possible_wrap)]
			#[inline(always)]
			fn cast_signed(self) -> <Self as Uint>::Int {
				self as Self::Int
			}

			#[inline(always)]
			#[track_caller]
			fn to_le(self) -> Self {
				self.to_le()
			}

			#[inline(always)]
			#[track_caller]
			fn to_be(self) -> Self {
				self.to_be()
			}

			#[inline(always)]
			#[track_caller]
			fn to_ne_bytes(self) -> Self::Bytes {
				self.to_ne_bytes()
			}

			#[inline(always)]
			#[track_caller]
			fn to_le_bytes(self) -> Self::Bytes {
				self.to_le_bytes()
			}

			#[inline(always)]
			#[track_caller]
			fn to_be_bytes(self) -> Self::Bytes {
				self.to_be_bytes()
			}
		}
	)*};
}

impl_uint! {
	u8   { Int = i8,   Bytes = [u8; 1] },
	u16  { Int = i16,  Bytes = [u8; 02] },
	u32  { Int = i32,  Bytes = [u8; 04] },
	u64  { Int = i64,  Bytes = [u8; 08] },
	u128 { Int = i128, Bytes = [u8; 16] },
}

#[cfg(target_pointer_width = "16")]
impl_uint! {
	usize { Int = isize, Bytes = [u8; 2] },
}

#[cfg(target_pointer_width = "32")]
impl_uint! {
	usize { Int = isize, Bytes = [u8; 4] },
}

#[cfg(target_pointer_width = "64")]
impl_uint! {
	usize { Int = isize, Bytes = [u8; 8] },
}
