use std::fmt::Debug;
use std::ops::AddAssign;
use num_traits::int::PrimInt;
pub trait SpIndex:
Debug + PrimInt + AddAssign<Self> + Default + Send + Sync
{
fn index(self) -> usize;
fn try_index(self) -> Option<usize>;
fn index_unchecked(self) -> usize;
fn from_usize(ind: usize) -> Self;
fn try_from_usize(ind: usize) -> Option<Self>;
fn from_usize_unchecked(ind: usize) -> Self;
}
impl SpIndex for usize {
#[inline(always)]
fn index(self) -> usize {
self
}
#[inline(always)]
fn try_index(self) -> Option<usize> {
Some(self)
}
#[inline(always)]
fn index_unchecked(self) -> usize {
self
}
#[inline(always)]
#[allow(clippy::wrong_self_convention)]
fn from_usize(ind: usize) -> Self {
ind
}
#[inline(always)]
fn try_from_usize(ind: usize) -> Option<Self> {
Some(ind)
}
#[inline(always)]
#[allow(clippy::wrong_self_convention)]
fn from_usize_unchecked(ind: usize) -> Self {
ind
}
}
macro_rules! sp_index_impl {
($int: ident) => {
impl SpIndex for $int {
#[inline(always)]
fn index(self) -> usize {
self.try_index().unwrap_or_else(|| {
panic!("Failed to convert {} to usize", self)
})
}
#[inline(always)]
fn try_index(self) -> Option<usize> {
num_traits::cast(self)
}
#[inline(always)]
fn index_unchecked(self) -> usize {
debug_assert!(self.try_index().is_some());
self as usize
}
#[inline(always)]
fn from_usize(ind: usize) -> Self {
Self::try_from_usize(ind).unwrap_or_else(|| {
panic!("Failed to convert {} to index type", ind)
})
}
#[inline(always)]
fn try_from_usize(ind: usize) -> Option<Self> {
num_traits::cast(ind)
}
#[inline(always)]
fn from_usize_unchecked(ind: usize) -> Self {
debug_assert!(Self::try_from_usize(ind).is_some());
ind as Self
}
}
};
}
sp_index_impl!(isize);
sp_index_impl!(i64);
sp_index_impl!(i32);
sp_index_impl!(i16);
sp_index_impl!(u64);
sp_index_impl!(u32);
sp_index_impl!(u16);
#[cfg(test)]
mod test {
use super::SpIndex;
#[test]
#[should_panic]
fn overflow_u16() {
let b: u16 = u16::from_usize(131072); println!("{}", b);
}
#[test]
#[should_panic]
fn negative_i16() {
let b: i16 = -1;
let a = b.index();
println!("{}", a);
}
}