use derive_more::{Add, AddAssign, Sub, SubAssign};
use indexland::{
idx_newtype, index_array,
index_array::{EnumIndexArray, IndexArray},
Idx, IdxEnum, IdxNewtype, IndexArrayVec,
};
#[test]
fn derive_enum_idx() {
#[derive(IdxEnum)]
enum Foo {
A,
B,
}
const FOO: EnumIndexArray<Foo, i32> = IndexArray::new([0, 1]);
assert_eq!(FOO[Foo::B], 1);
}
#[test]
fn derive_idx_newtype() {
#[derive(IdxNewtype)]
pub struct FooId(u32);
let foo = IndexArrayVec::<FooId, i32, 3>::from_iter([0, 1, 2]);
assert_eq!(foo[FooId::ONE], 1);
}
#[test]
fn declarative_idx_newtype() {
idx_newtype! {
pub struct FooId(u32);
}
idx_newtype! {
pub struct BarId(u32);
pub struct BazId(u32);
}
let foo = IndexArrayVec::<FooId, i32, 3>::from_iter([0, 1, 2]);
assert_eq!(foo[FooId::ONE], 1);
}
#[test]
fn derive_idx_newtype_manual() {
#[derive(
Default,
Add,
Sub,
AddAssign,
SubAssign,
Clone,
Copy,
Hash,
PartialEq,
Eq,
PartialOrd,
Ord,
)]
pub struct FooIdx(u32);
impl Idx for FooIdx {
const ZERO: Self = FooIdx(0);
const ONE: Self = FooIdx(1);
const MAX: Self = FooIdx(u32::MAX);
fn from_usize(v: usize) -> Self {
FooIdx(v as u32)
}
fn into_usize(self) -> usize {
self.0 as usize
}
}
let foo = IndexArrayVec::<FooIdx, i32, 3>::from_iter([0, 1, 2]);
assert_eq!(foo[FooIdx::ONE], 1);
}
#[test]
fn derive_idx_enum_manual() {
#[derive(Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
enum Foo {
#[default]
A,
B,
}
impl Idx for Foo {
const ZERO: Self = Foo::A;
const ONE: Self = Foo::B;
const MAX: Self = Foo::B;
fn from_usize(v: usize) -> Self {
match v {
0 => Foo::A,
1 => Foo::B,
_ => panic!(),
}
}
fn into_usize(self) -> usize {
self as usize
}
}
impl core::ops::Add for Foo {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Idx::from_usize(self.into_usize() + rhs.into_usize())
}
}
impl core::ops::Sub for Foo {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Idx::from_usize(self.into_usize() - rhs.into_usize())
}
}
impl core::ops::AddAssign for Foo {
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs;
}
}
impl core::ops::SubAssign for Foo {
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs;
}
}
impl IdxEnum for Foo {
const COUNT: usize = 2;
const VARIANTS: &'static [Self] = &[Foo::A, Foo::B];
type EnumIndexArray<T> = IndexArray<Self, T, 2>;
}
const FOO: EnumIndexArray<Foo, i32> = IndexArray::new([0, 1]);
assert_eq!(FOO[Foo::B], 1);
}
#[test]
fn enum_idx_array_macro() {
#[derive(IdxEnum)]
enum Foo {
A,
B,
C,
}
const FOO: EnumIndexArray<Foo, i32> = index_array![
Foo::A => 1,
Foo::B => 2,
Foo::C => 3,
];
assert_eq!(FOO[Foo::B], 2);
}
#[test]
fn enum_idx_array_macro_non_copy() {
#[derive(IdxEnum)]
enum Foo {
A,
B,
C,
}
let foo: EnumIndexArray<Foo, Box<i32>> = index_array![
Foo::A => Box::new(1),
Foo::B => Box::new(2),
Foo::C => Box::new(3),
];
assert_eq!(*foo[Foo::B], 2);
}
#[test]
fn nested_enum_idx_array() {
#[derive(IdxEnum)]
enum Foo {
A,
B,
}
#[derive(IdxEnum)]
enum Bar {
X,
Y,
}
let foo: EnumIndexArray<Foo, EnumIndexArray<Bar, i32>> = index_array![
Foo::A => index_array![Bar::X => 1, Bar::Y => 2],
Foo::B => index_array![Bar::X => 3, Bar::Y => 4],
];
assert_eq!(foo[Foo::B][Bar::Y], 4);
}