// Copyright 2025 Gabriel Bjørnager Jensen.

mod test;

use crate::Uint;

macro_rules! def_uint_leasts {
	{$(
		$Ident:ident {
			seal:      $Seal:path,
			extends:   $Extends:path,
			uint:      $Uint:ty,
			uint_ctor: $uint_ctor:ident$(,)?
		} for {
			$($Ty:ty $(= $feature:literal)?),*$(,)?
		}
	)*} => {$(
		#[doc = ::core::concat!(
			"Denotes an unsigned that is at least as wide as [`",
			::core::stringify!($Uint),
			"`].\n",
			"\n",
			"# Safety\n",
			"\n",
			"Only primitive, unsigned, integral type that fit the size requirement may implement this type.\n",
		)]
		pub trait $Ident
		where
			Self:
				$Seal
				+ $Extends
				+ ::core::convert::From<$Uint>,
		{
			#[doc = ::core::concat!(
				"Constructs a new, unsigned integer number from a [`",
				::core::stringify!($Uint),
				"`] value.\n",
			)]
			#[must_use]
			fn $uint_ctor(value: $Uint) -> Self;
		}

		$(
			impl $Seal for $Ty { }

			impl $Ident for $Ty {
				#[inline(always)]
				fn $uint_ctor(value: $Uint) -> Self {
					value.into()
				}
			}
		)*
	)*};
}

def_uint_leasts! {
	UintLeast16 {
		seal:      crate::SealedUintLeast16,
		extends:   Uint,
		uint:      u16,
		uint_ctor: from_u16,
	} for {
		u16,
		u32,
		u64,
		u128,
		usize
	}

	UintLeast32 {
		seal:      crate::SealedUintLeast32,
		extends:   UintLeast16,
		uint:      u32,
		uint_ctor: from_u32,
	} for {
		u32,
		u64,
		u128,
	}

	UintLeast64 {
		seal:      crate::SealedUintLeast64,
		extends:   UintLeast32,
		uint:      u64,
		uint_ctor: from_u64,
	} for {
		u64,
		u128,
	}
}
