macro_rules! generate_niche_prim {
($_d:tt $($P:ty),+ $(,)?) => { $crate::paste! {
#[doc = crate::_tags!(niche)]
#[doc = crate::_doc_location!("num/grain/niche")]
#[doc(hidden)]
#[macro_export]
macro_rules! _niche_prim {
($head:ident :: $_d($rest:tt)+) => { $crate::niche_prim!($_d($rest)+) };
$(
($P $_d($_:tt)*) => { $P };
(NonNiche<$P> $_d($_:tt)*) => { $P };
(NonZero<$P> $_d($_:tt)*) => { $P };
([<NonZero$P:camel>] $_d($_:tt)*) => { $P };
([<NonExtreme$P:camel>] $_d($_:tt)*) => { $P };
([<NonValue$P:camel>] $_d($_:tt)*) => { $P };
(MaybeNiche<$P> $_d($_:tt)*) => { $P };
(MaybeNiche<NonNiche<$P>> $_d($_:tt)*) => { $P };
(MaybeNiche<NonZero<$P>> $_d($_:tt)*) => { $P };
(MaybeNiche<[<NonZero$P:camel>]> $_d($_:tt)*) => { $P };
(MaybeNiche<[<NonExtreme$P:camel>]> $_d($_:tt)*) => { $P };
(MaybeNiche<[<NonValue$P:camel>]> $_d($_:tt)*) => { $P };
)+
}
#[doc(inline)]
pub use _niche_prim as niche_prim;
}};
}
generate_niche_prim![$ u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize];
#[doc = crate::_tags!(num niche construction)]
#[doc = crate::_doc_location!("num/grain/niche")]
#[macro_export]
#[doc(hidden)]
macro_rules! ne {
(lossy $num:expr) => {{ $crate::NicheNew($num).to_lossy_non_extreme() }};
(lossy $num:expr, $T:ty) => {{ $crate::NicheNew::<$T>($num).to_lossy_non_extreme() }};
($num:expr) => {{ $crate::NicheNew($num).to_non_extreme() }};
($num:expr, $T:ty) => {{ $crate::NicheNew::<$T>($num).to_non_extreme() }};
}
#[doc(inline)]
pub use ne;
#[doc = crate::_tags!(num niche construction)]
#[doc = crate::_doc_location!("num/grain/niche")]
#[macro_export]
#[doc(hidden)]
macro_rules! nv {
(lossy $val:literal: $num:expr) => {{ $crate::NicheNew($num).to_lossy_non_value::<$val>() }};
(lossy $val:literal: $num:expr, $T:ty) => {{ $crate::NicheNew::<$T>($num).to_lossy_non_value::<$val>() }};
($val:literal: $num:expr) => {{ $crate::NicheNew($num).to_non_value::<$val>() }};
($val:literal: $num:expr, $T:ty) => {{ $crate::NicheNew::<$T>($num).to_non_value::<$val>() }};
}
#[doc(inline)]
pub use nv;
#[doc = crate::_tags!(num niche construction)]
#[doc = crate::_doc_location!("num/grain/niche")]
#[macro_export]
#[doc(hidden)]
macro_rules! nz {
(lossy $num:expr) => {{ $crate::NicheNew($num).to_lossy_non_zero() }};
(lossy $num:expr, $T:ty) => {{ $crate::NicheNew::<$T>($num).to_lossy_non_zero() }};
($num:expr) => {{ $crate::NicheNew($num).to_non_zero() }};
($num:expr, $T:ty) => {{ $crate::NicheNew::<$T>($num).to_non_zero() }};
}
#[doc(inline)]
pub use nz;
#[doc = crate::_tags!(num niche construction)]
#[doc = crate::_doc_location!("num/grain/niche")]
#[doc(hidden)]
#[derive(Debug)]
pub struct NicheNew<T>(pub T);
macro_rules! impl_niche_new {
() => {
impl_niche_new!(U: u8, u16, u32, u64, u128, usize);
impl_niche_new!(I: i8, i16, i32, i64, i128, isize);
};
($SIGN:ident: $($prim:ty),+) => { $crate::paste! {
$( impl_niche_new!(@NZ [<NonZero $prim:camel>], $prim); )+
$( impl_niche_new!(@NV [<NonValue $prim:camel>], $prim); )+ $( impl_niche_new!(@$SIGN [<NonExtreme $prim:camel>], $prim); )+
}};
(@NZ $name:ident, $prim:ty) => {
impl NicheNew<$prim> {
pub const fn to_non_zero(self) -> $crate::$name {
if self.0 == 0 { panic!["value must not be 0"]; }
else { $crate::$name::new(self.0).unwrap() }
}
pub const fn to_lossy_non_zero(self) -> $crate::$name {{
let value = if self.0 == 0 { 1 } else { self.0 };
$crate::$name::new(value).unwrap()
}}
}
};
(@NV $name:ident, $prim:ty) => {
impl NicheNew<$prim> {
pub const fn to_non_value<const V: $prim>(self) -> $crate::$name<V> {
$crate::$name::new(self.0).expect("Invalid value")
}
pub const fn to_lossy_non_value<const V: $prim>(self) -> $crate::$name<V> {
$crate::$name::new_lossy(self.0)
}
}
};
(@I $name:ident, $prim:ty) => {
impl NicheNew<$prim> {
pub const fn to_non_extreme(self) -> $crate::$name {
if self.0 == <$prim>::MIN { panic!["value must not be MIN"]; }
else { $crate::$name::new(self.0).unwrap() }
}
pub const fn to_lossy_non_extreme(self) -> $crate::$name {
$crate::$name::new_lossy(self.0)
}
}
};
(@U $name:ident, $prim:ty) => {
impl NicheNew<$prim> {
pub const fn to_non_extreme(self) -> $crate::$name {
if self.0 == <$prim>::MAX { panic!["value must not be MAX"]; }
else { $crate::$name::new(self.0).unwrap() }
}
pub const fn to_lossy_non_extreme(self) -> $crate::$name {
$crate::$name::new_lossy(self.0)
}
}
};
}
impl_niche_new!();
#[cfg(test)]
crate::items! {
#[test]
#[allow(unused)]
fn test_niche_prim() {
let a: niche_prim!(NonValueU8<43>) = 3;
let b: u8 = a + 4_u8;
let a: niche_prim!(MaybeNiche<NonZeroIsize>) = 3;
let b: isize = a + 4_isize;
let a: niche_prim!(crate::num::NonValueU8<43>) = 3;
const fn prim() -> crate::niche_prim![u8] { 32 }
macro_rules! example_macro {
($($P:tt)+) => { const fn prim2() -> crate::niche_prim![$($P)+] { 32 } }; }
example_macro![NonValueU8<43>];
}
#[test]
fn test_nz() {
assert_eq![nz![20i32], crate::NonZeroI32::new(20).unwrap()];
assert_eq![nz![20u8], crate::NonZeroU8::new(20).unwrap()];
assert_eq![nz![20, i32], crate::NonZeroI32::new(20).unwrap()];
assert_eq![nz![20, u8], crate::NonZeroU8::new(20).unwrap()];
}
#[test]
#[should_panic(expected = "value must not be 0")]
fn test_nz_panic() { let _panic = nz![0i64]; }
#[test]
fn test_nv() {
assert_eq![nv![3: 20u8], crate::NonValueU8::new(20).unwrap()];
assert_eq![nv![3: 20, i32], crate::NonValueI32::new(20).unwrap()];
}
#[test]
#[should_panic(expected = "Invalid value")]
fn test_nv_panic() { let _panic = nv![3: 3, i32]; }
#[test]
fn test_ne() {
assert_eq![ne![20i8], crate::NonExtremeI8::new(20).unwrap()];
assert_eq![ne![20u8], crate::NonExtremeU8::new(20).unwrap()];
assert_eq![ne![20, i8], crate::NonExtremeI8::new(20).unwrap()];
assert_eq![ne![20, u8], crate::NonExtremeU8::new(20).unwrap()];
}
#[test]
#[should_panic(expected = "value must not be MIN")]
fn test_ne_min_panic() { let min = i8::MIN; let _panic = ne![min]; }
#[test]
#[should_panic(expected = "value must not be MAX")]
fn test_ne_max_panic() { let max = u8::MAX; let _panic = ne![max]; }
}