#![recursion_limit="256"] #[macro_export]
macro_rules! enum_seq_len {
() => (0);
($($enumval_0: tt, $enumval_1: tt,)*) => (2*(enum_seq_len!($($enumval_0,)*)));
($enumval: tt, $($enumval_0: tt, $enumval_1: tt,)*) => (1+2*(enum_seq_len!($($enumval_0,)*)));
}
#[macro_use]
mod plain_enum {
macro_rules! for_each_prefix (
($m:ident, [$($acc:tt,)*], []) => {
$m!($($acc,)*);
};
($m:ident, [$($acc:tt,)*], [$arg0:tt, $($arg:tt,)*]) => {
$m!($($acc,)*);
for_each_prefix!($m, [$($acc,)* $arg0,], [$($arg,)*]);
};
);
pub trait TArrayFromFn<T> {
fn array_from_fn<F>(func: F) -> Self
where F: FnMut(usize) -> T;
unsafe fn index(a: &Self, e: usize) -> &T;
unsafe fn index_mut(a: &mut Self, e: usize) -> &mut T;
fn iter(a: &Self) -> slice::Iter<T>;
fn iter_mut(a: &mut Self) -> slice::IterMut<T>;
type TupleType;
fn from_tuple(tpl: Self::TupleType) -> Self;
}
macro_rules! ignore_first{($a0: tt, $a1: tt) => {$a1}}
macro_rules! impl_array_from_fn{($($i: tt,)*) => {
impl<T> TArrayFromFn<T> for [T; enum_seq_len!($($i,)*)] {
fn array_from_fn<F>(mut func: F) -> Self
where F: FnMut(usize) -> T
{
[$(func($i),)*]
}
#[inline(always)]
unsafe fn index(a: &Self, e: usize) -> &T {
a.get_unchecked(e)
}
#[inline(always)]
unsafe fn index_mut(a: &mut Self, e: usize) -> &mut T {
a.get_unchecked_mut(e)
}
fn iter(a: &Self) -> slice::Iter<T> {
a.iter()
}
fn iter_mut(a: &mut Self) -> slice::IterMut<T> {
a.iter_mut()
}
type TupleType = ($(ignore_first!($i, T),)*);
fn from_tuple(tpl: Self::TupleType) -> Self {
[$(tpl.$i,)*]
}
}
}}
for_each_prefix!{
impl_array_from_fn,
[0,],
[
1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127, 128,
]
}
pub trait TArrayMapInto<V> {
type MappedType<W>;
fn map_into2<W>(self, f: impl FnMut(V)->W) -> Self::MappedType::<W>;
}
macro_rules! impl_array_map_into{($($val: tt,)*) => {
impl<V> TArrayMapInto<V> for [V; enum_seq_len!($($val,)*)] {
type MappedType<W> = [W; enum_seq_len!($($val,)*)];
fn map_into2<W>(self, mut f: impl FnMut(V)->W) -> Self::MappedType::<W> {
let [ $($val,)* ] = self;
[$(f($val),)*]
}
}
}}
for_each_prefix!{
impl_array_map_into,
[t0,],
[
t1, t2, t3, t4, t5, t6, t7, t8, t9,
t10, t11, t12, t13, t14, t15, t16, t17, t18, t19,
t20, t21, t22, t23, t24, t25, t26, t27, t28, t29,
t30, t31, t32, t33, t34, t35, t36, t37, t38, t39,
t40, t41, t42, t43, t44, t45, t46, t47, t48, t49,
t50, t51, t52, t53, t54, t55, t56, t57, t58, t59,
t60, t61, t62, t63, t64, t65, t66, t67, t68, t69,
t70, t71, t72, t73, t74, t75, t76, t77, t78, t79,
t80, t81, t82, t83, t84, t85, t86, t87, t88, t89,
t90, t91, t92, t93, t94, t95, t96, t97, t98, t99,
t100, t101, t102, t103, t104, t105, t106, t107, t108, t109,
t110, t111, t112, t113, t114, t115, t116, t117, t118, t119,
t120, t121, t122, t123, t124, t125, t126, t127, t128,
]
}
use std;
use std::iter;
use std::ops;
use std::ops::{Index, IndexMut};
use std::slice;
pub struct SWrappedDifference<E>(pub E);
pub unsafe trait PlainEnum : Sized {
const SIZE : usize;
type EnumMapArray<T> : TArrayFromFn<T> + TArrayMapInto<T>;
unsafe fn from_usize(u: usize) -> Self;
fn to_usize(self) -> usize;
fn valid_usize(u: usize) -> bool {
u < Self::SIZE
}
fn checked_from_usize(u: usize) -> Option<Self> {
if Self::valid_usize(u) {
unsafe { Some(Self::from_usize(u)) }
} else {
None
}
}
fn wrapped_from_usize(u: usize) -> Self {
unsafe { Self::from_usize(u % Self::SIZE) }
}
fn wrapped_difference_usize(self, e_other: Self) -> usize {
(self.to_usize() + Self::SIZE - e_other.to_usize()) % Self::SIZE
}
fn wrapped_difference(self, e_other: Self) -> SWrappedDifference<Self> {
SWrappedDifference(unsafe{Self::from_usize(self.wrapped_difference_usize(e_other))})
}
fn values() -> iter::Map<ops::Range<usize>, fn(usize) -> Self> {
(0..Self::SIZE)
.map(|u| unsafe { Self::from_usize(u) })
}
fn wrapping_add(self, n_offset: usize) -> Self {
unsafe { Self::from_usize((self.to_usize() + n_offset) % Self::SIZE) }
}
fn map_from_fn<F, T>(mut func: F) -> EnumMap<Self, T>
where F: FnMut(Self) -> T,
{
EnumMap::from_raw(TArrayFromFn::array_from_fn(|i| func(unsafe{Self::from_usize(i)})))
}
fn map_from_raw<V>(a: Self::EnumMapArray::<V>) -> EnumMap<Self, V>
where
{
EnumMap::from_raw(a)
}
fn map_from_tuple<V>(tpl: <Self::EnumMapArray::<V> as TArrayFromFn<V>>::TupleType) -> EnumMap<Self, V>
{
EnumMap::from_tuple(tpl)
}
}
#[allow(dead_code)]
#[derive(Eq, PartialEq, Hash, Copy)]
pub struct EnumMap<E: PlainEnum, V>
where E: PlainEnum,
{
phantome: std::marker::PhantomData<E>,
a: E::EnumMapArray<V>,
}
impl<E, V> Clone for EnumMap<E, V>
where
E: PlainEnum,
V: Clone,
{
fn clone(&self) -> Self {
E::map_from_fn(|e| self[e].clone()) }
}
impl<E, V> std::fmt::Debug for EnumMap<E, V> where
E: PlainEnum + std::fmt::Debug,
V: std::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f
.debug_map()
.entries(E::values().map(|e| {
let i = e.to_usize();
let e2 = unsafe { E::from_usize(i) }; let e3 = unsafe { E::from_usize(i) }; (e2, &self[e3])
}))
.finish()
}
}
impl<V: Default, E: PlainEnum> Default for EnumMap<E, V> {
fn default() -> Self {
E::map_from_fn(|_| Default::default())
}
}
impl<E, V> EnumMap<E, V>
where E: PlainEnum,
{
pub fn from_raw(a: E::EnumMapArray<V>) -> Self {
EnumMap{
phantome: std::marker::PhantomData{},
a,
}
}
pub fn from_tuple(tpl: <E::EnumMapArray<V> as TArrayFromFn<V>>::TupleType) -> Self {
Self::from_raw(E::EnumMapArray::<V>::from_tuple(tpl))
}
pub fn iter(&self) -> slice::Iter<V> {
TArrayFromFn::iter(&self.a)
}
pub fn iter_mut(&mut self) -> slice::IterMut<V> {
TArrayFromFn::iter_mut(&mut self.a)
}
pub fn map<FnMap, W>(&self, fn_map: FnMap) -> EnumMap<E, W>
where FnMap: Fn(&V) -> W,
E: PlainEnum,
{
E::map_from_fn(|e|
fn_map(&self[e])
)
}
pub fn map_into<FnMap, W>(self, fn_map: FnMap) -> EnumMap<E, W>
where FnMap: Fn(V) -> W,
E: PlainEnum,
<<E as PlainEnum>::EnumMapArray<V> as TArrayMapInto<V>>::MappedType::<W>: Into<E::EnumMapArray<W>>
{
EnumMap::<E, W>::from_raw(self.a.map_into2(fn_map).into())
}
pub fn into_raw(self) -> E::EnumMapArray::<V> {
self.a
}
pub fn as_raw(&self) -> &E::EnumMapArray::<V> {
&self.a
}
pub fn as_raw_mut(&mut self) -> &mut E::EnumMapArray::<V> {
&mut self.a
}
}
impl<E, V> Index<E> for EnumMap<E, V>
where E: PlainEnum,
{
type Output = V;
fn index(&self, e: E) -> &V {
unsafe { TArrayFromFn::index(&self.a, e.to_usize()) } }
}
impl<E, V> IndexMut<E> for EnumMap<E, V>
where E: PlainEnum,
{
fn index_mut(&mut self, e: E) -> &mut Self::Output {
unsafe { TArrayFromFn::index_mut(&mut self.a, e.to_usize()) } }
}
#[macro_export]
macro_rules! tt {
($func: ident, [$($acc: expr,)*], []) => {
[$($acc,)*]
};
($func: ident, [$($acc: expr,)*], [$enumval: ident, $($enumvals: ident,)*]) => {
acc_arr!($func, [$($acc,)* $func($enumval),], [$($enumvals,)*])
};
}
#[macro_export]
macro_rules! internal_impl_plainenum {($enumname: ty, $enumsize: expr, $from_usize: expr,) => {
unsafe impl PlainEnum for $enumname {
const SIZE : usize = $enumsize;
type EnumMapArray<T> = [T; $enumsize];
unsafe fn from_usize(u: usize) -> Self {
$from_usize(u)
}
fn to_usize(self) -> usize {
self as usize
}
}
}}
#[macro_export]
macro_rules! plain_enum_mod {
($modname: ident, derive($($derives:ident, )*), map_derive($($mapderives:ident, )*), $enumname: ident {
$($enumvals: ident,)*
} ) => {
#[repr(usize)]
#[derive(PartialEq, Eq, Debug, Copy, Clone, PartialOrd, Ord, $($derives,)*)]
pub enum $enumname {
$(#[allow(dead_code)] $enumvals,)*
}
mod $modname {
use plain_enum::*;
use super::$enumname;
const SIZE : usize = enum_seq_len!($($enumvals,)*);
internal_impl_plainenum!(
$enumname,
SIZE,
|u|{
use std::mem;
debug_assert!(Self::valid_usize(u));
mem::transmute(u)
},
);
}
};
($modname: ident, $enumname: ident {
$($enumvals: ident,)*
} ) => {
plain_enum_mod!($modname, derive(), map_derive(), $enumname { $($enumvals,)* });
};
}
}
pub use plain_enum::PlainEnum;
pub use plain_enum::EnumMap;
pub use plain_enum::TArrayMapInto;
internal_impl_plainenum!(
bool,
2,
|u|{
debug_assert!(u==0 || u==1);
0!=u
},
);
unsafe impl PlainEnum for () {
const SIZE : usize = 1;
type EnumMapArray<T> = [T; 1];
unsafe fn from_usize(u: usize) -> Self {
debug_assert_eq!(0, u);
}
fn to_usize(self) -> usize {
0
}
}
unsafe impl PlainEnum for std::cmp::Ordering {
const SIZE : usize = 3;
type EnumMapArray<T> = [T; 3];
unsafe fn from_usize(u: usize) -> Self {
match u {
0 => std::cmp::Ordering::Less,
1 => std::cmp::Ordering::Equal,
u => {
debug_assert_eq!(u, 2);
std::cmp::Ordering::Greater
},
}
}
fn to_usize(self) -> usize {
match self {
std::cmp::Ordering::Less => 0,
std::cmp::Ordering::Equal => 1,
std::cmp::Ordering::Greater => 2,
}
}
}
#[cfg(test)]
mod tests {
use plain_enum::*;
plain_enum_mod!{test_module, ETest {
E1, E2, E3,
}}
plain_enum_mod!{test_module_with_hash, derive(Hash,), map_derive(Hash,), ETestWithHash {
E1, E2, E3,
}}
#[test]
fn test_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(ETestWithHash::E1);
assert!(set.contains(&ETestWithHash::E1));
assert!(!set.contains(&ETestWithHash::E2));
let enummap = ETestWithHash::map_from_fn(|e| e);
let mut set2 = HashSet::new();
set2.insert(enummap);
}
#[test]
fn test_clone() {
let map1 = ETest::map_from_fn(|e| e);
let map2 = map1.clone();
assert_eq!(map1, map2);
}
#[test]
fn test_enum_seq_len() {
assert_eq!(0, enum_seq_len!());
assert_eq!(1, enum_seq_len!(E1,));
assert_eq!(2, enum_seq_len!(E1, E3,));
assert_eq!(3, enum_seq_len!(E1, E2, E3,));
assert_eq!(14, enum_seq_len!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,));
assert_eq!(13, enum_seq_len!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, ));
}
#[test]
fn test_plain_enum() {
assert_eq!(3, ETest::SIZE);
}
#[test]
fn test_values() {
assert_eq!(vec![ETest::E1, ETest::E2, ETest::E3], ETest::values().collect::<Vec<_>>());
assert_eq!(ETest::values().count(), 3);
assert_eq!((3, Some(3)), ETest::values().size_hint());
assert_eq!(3, ETest::values().len());
assert!(ETest::values().eq(ETest::values().rev().rev()));
}
#[test]
fn test_enummap() {
let mut map_test_to_usize = ETest::map_from_fn(|test| test.to_usize());
for test in ETest::values() {
assert_eq!(map_test_to_usize[test], test.to_usize());
}
for test in ETest::values() {
map_test_to_usize[test] += 1;
}
for test in ETest::values() {
assert_eq!(map_test_to_usize[test], test.to_usize()+1);
}
for v in map_test_to_usize.iter().zip(ETest::values()) {
assert_eq!(*v.0, v.1.to_usize()+1);
}
for v in map_test_to_usize.map(|n| Some(n*n)).iter() {
assert!(v.is_some());
}
}
#[test]
fn test_map_into() {
struct NonCopy;
let map_test_to_usize = ETest::map_from_fn(|_| NonCopy);
let _map2 : EnumMap<_, (NonCopy, usize)> = map_test_to_usize.map_into(|noncopy| (noncopy, 0));
}
#[test]
fn test_bool() {
let mapbn = bool::map_from_fn(|b| b as usize);
assert_eq!(mapbn[false], 0);
assert_eq!(mapbn[true], 1);
}
#[test]
fn test_unit() {
let mapbn = <()>::map_from_fn(|()| 42);
assert_eq!(mapbn[()], 42);
assert_eq!(<()>::SIZE, 1);
}
#[test]
fn test_wrapped_difference() {
assert_eq!(ETest::E3.wrapped_difference_usize(ETest::E1), 2);
assert_eq!(ETest::E1.wrapped_difference_usize(ETest::E3), 1);
assert_eq!(ETest::E3.wrapped_difference(ETest::E1).0, ETest::E3);
assert_eq!(ETest::E1.wrapped_difference(ETest::E3).0, ETest::E2);
for e1 in ETest::values() {
for e2 in ETest::values() {
assert_eq!(e1.wrapped_difference_usize(e2), e1.wrapped_difference(e2).0.to_usize());
}
}
}
#[test]
fn test_default() {
let _enummap : EnumMap<ETest, usize> = Default::default();
}
#[test]
fn test_from_tuple() {
let enummap = ETest::map_from_tuple((1,2,3));
assert_eq!(enummap[ETest::E1], 1);
assert_eq!(enummap[ETest::E2], 2);
assert_eq!(enummap[ETest::E3], 3);
}
}