1#![recursion_limit="256"] #[macro_export]
34macro_rules! enum_seq_len {
35 () => (0);
36 ($($enumval_0: tt, $enumval_1: tt,)*) => (2*(enum_seq_len!($($enumval_0,)*)));
37 ($enumval: tt, $($enumval_0: tt, $enumval_1: tt,)*) => (1+2*(enum_seq_len!($($enumval_0,)*)));
38}
39
40#[macro_use]
41mod plain_enum {
42 macro_rules! for_each_prefix (
43 ($m:ident, [$($acc:tt,)*], []) => {
44 $m!($($acc,)*);
45 };
46 ($m:ident, [$($acc:tt,)*], [$arg0:tt, $($arg:tt,)*]) => {
47 $m!($($acc,)*);
48 for_each_prefix!($m, [$($acc,)* $arg0,], [$($arg,)*]);
49 };
50 );
51 pub trait TArrayFromFn<T> {
52 fn array_from_fn<F>(func: F) -> Self
53 where F: FnMut(usize) -> T;
54 unsafe fn index(a: &Self, e: usize) -> &T;
55 unsafe fn index_mut(a: &mut Self, e: usize) -> &mut T;
56 fn iter(a: &Self) -> slice::Iter<T>;
57 fn iter_mut(a: &mut Self) -> slice::IterMut<T>;
58 type TupleType;
59 fn from_tuple(tpl: Self::TupleType) -> Self;
60 }
62 macro_rules! ignore_first{($a0: tt, $a1: tt) => {$a1}}
63 macro_rules! impl_array_from_fn{($($i: tt,)*) => {
64 impl<T> TArrayFromFn<T> for [T; enum_seq_len!($($i,)*)] {
65 fn array_from_fn<F>(mut func: F) -> Self
66 where F: FnMut(usize) -> T
67 {
68 [$(func($i),)*]
69 }
70 #[inline(always)]
71 unsafe fn index(a: &Self, e: usize) -> &T {
72 a.get_unchecked(e)
73 }
74 #[inline(always)]
75 unsafe fn index_mut(a: &mut Self, e: usize) -> &mut T {
76 a.get_unchecked_mut(e)
77 }
78 fn iter(a: &Self) -> slice::Iter<T> {
79 a.iter()
80 }
81 fn iter_mut(a: &mut Self) -> slice::IterMut<T> {
82 a.iter_mut()
83 }
84 type TupleType = ($(ignore_first!($i, T),)*);
85 fn from_tuple(tpl: Self::TupleType) -> Self {
86 [$(tpl.$i,)*]
87 }
88 }
89 }}
90 for_each_prefix!{
91 impl_array_from_fn,
92 [0,],
93 [
94 1, 2, 3, 4, 5, 6, 7, 8, 9,
95 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
96 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
97 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
98 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
99 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
100 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
101 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
102 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
103 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
104 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
105 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
106 120, 121, 122, 123, 124, 125, 126, 127, 128,
107 ]
108 }
109 pub trait TArrayMapInto<V> {
110 type MappedType<W>;
111 fn map_into2<W>(self, f: impl FnMut(V)->W) -> Self::MappedType::<W>;
112 }
113 macro_rules! impl_array_map_into{($($val: tt,)*) => {
114 impl<V> TArrayMapInto<V> for [V; enum_seq_len!($($val,)*)] {
115 type MappedType<W> = [W; enum_seq_len!($($val,)*)];
116 fn map_into2<W>(self, mut f: impl FnMut(V)->W) -> Self::MappedType::<W> {
117 let [ $($val,)* ] = self;
118 [$(f($val),)*]
119 }
120 }
121 }}
122 for_each_prefix!{
123 impl_array_map_into,
124 [t0,],
125 [
126 t1, t2, t3, t4, t5, t6, t7, t8, t9,
127 t10, t11, t12, t13, t14, t15, t16, t17, t18, t19,
128 t20, t21, t22, t23, t24, t25, t26, t27, t28, t29,
129 t30, t31, t32, t33, t34, t35, t36, t37, t38, t39,
130 t40, t41, t42, t43, t44, t45, t46, t47, t48, t49,
131 t50, t51, t52, t53, t54, t55, t56, t57, t58, t59,
132 t60, t61, t62, t63, t64, t65, t66, t67, t68, t69,
133 t70, t71, t72, t73, t74, t75, t76, t77, t78, t79,
134 t80, t81, t82, t83, t84, t85, t86, t87, t88, t89,
135 t90, t91, t92, t93, t94, t95, t96, t97, t98, t99,
136 t100, t101, t102, t103, t104, t105, t106, t107, t108, t109,
137 t110, t111, t112, t113, t114, t115, t116, t117, t118, t119,
138 t120, t121, t122, t123, t124, t125, t126, t127, t128,
139 ]
140 }
141
142 use std;
143 use std::iter;
144 use std::ops;
145 use std::ops::{Index, IndexMut};
146 use std::slice;
147
148 pub struct SWrappedDifference<E>(pub E);
149
150 pub unsafe trait PlainEnum : Sized {
153 const SIZE : usize;
155 type EnumMapArray<T> : TArrayFromFn<T> + TArrayMapInto<T>;
157 unsafe fn from_usize(u: usize) -> Self;
159 fn to_usize(self) -> usize;
161
162 fn valid_usize(u: usize) -> bool {
164 u < Self::SIZE
165 }
166 fn checked_from_usize(u: usize) -> Option<Self> {
168 if Self::valid_usize(u) {
169 unsafe { Some(Self::from_usize(u)) }
170 } else {
171 None
172 }
173 }
174 fn wrapped_from_usize(u: usize) -> Self {
177 unsafe { Self::from_usize(u % Self::SIZE) }
178 }
179 fn wrapped_difference_usize(self, e_other: Self) -> usize {
181 (self.to_usize() + Self::SIZE - e_other.to_usize()) % Self::SIZE
182 }
183 fn wrapped_difference(self, e_other: Self) -> SWrappedDifference<Self> {
185 SWrappedDifference(unsafe{Self::from_usize(self.wrapped_difference_usize(e_other))})
186 }
187 fn values() -> iter::Map<ops::Range<usize>, fn(usize) -> Self> {
189 (0..Self::SIZE)
190 .map(|u| unsafe { Self::from_usize(u) })
191 }
192 fn wrapping_add(self, n_offset: usize) -> Self {
194 unsafe { Self::from_usize((self.to_usize() + n_offset) % Self::SIZE) }
195 }
196 fn map_from_fn<F, T>(mut func: F) -> EnumMap<Self, T>
199 where F: FnMut(Self) -> T,
200 {
201 EnumMap::from_raw(TArrayFromFn::array_from_fn(|i| func(unsafe{Self::from_usize(i)})))
202 }
203 fn map_from_raw<V>(a: Self::EnumMapArray::<V>) -> EnumMap<Self, V>
205 where
206 {
207 EnumMap::from_raw(a)
208 }
209 fn map_from_tuple<V>(tpl: <Self::EnumMapArray::<V> as TArrayFromFn<V>>::TupleType) -> EnumMap<Self, V>
211 {
212 EnumMap::from_tuple(tpl)
213 }
214 }
215
216 #[allow(dead_code)]
217 #[derive(Eq, PartialEq, Hash, Copy)]
218 pub struct EnumMap<E: PlainEnum, V>
219 where E: PlainEnum,
220 {
221 phantome: std::marker::PhantomData<E>,
222 a: E::EnumMapArray<V>,
223 }
224
225 impl<E, V> Clone for EnumMap<E, V>
226 where
227 E: PlainEnum,
228 V: Clone,
229 {
230 fn clone(&self) -> Self {
231 E::map_from_fn(|e| self[e].clone()) }
233 }
234
235 impl<E, V> std::fmt::Debug for EnumMap<E, V> where
237 E: PlainEnum + std::fmt::Debug,
238 V: std::fmt::Debug,
239 {
240 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
241 f
242 .debug_map()
243 .entries(E::values().map(|e| {
244 let i = e.to_usize();
245 let e2 = unsafe { E::from_usize(i) }; let e3 = unsafe { E::from_usize(i) }; (e2, &self[e3])
248 }))
249 .finish()
250 }
251 }
252
253 impl<V: Default, E: PlainEnum> Default for EnumMap<E, V> {
254 fn default() -> Self {
255 E::map_from_fn(|_| Default::default())
256 }
257 }
258
259 impl<E, V> EnumMap<E, V>
260 where E: PlainEnum,
261 {
262 pub fn from_raw(a: E::EnumMapArray<V>) -> Self {
264 EnumMap{
265 phantome: std::marker::PhantomData{},
266 a,
267 }
268 }
269 pub fn from_tuple(tpl: <E::EnumMapArray<V> as TArrayFromFn<V>>::TupleType) -> Self {
270 Self::from_raw(E::EnumMapArray::<V>::from_tuple(tpl))
271 }
272 pub fn iter(&self) -> slice::Iter<V> {
274 TArrayFromFn::iter(&self.a)
275 }
276 pub fn iter_mut(&mut self) -> slice::IterMut<V> {
278 TArrayFromFn::iter_mut(&mut self.a)
279 }
280 pub fn map<FnMap, W>(&self, fn_map: FnMap) -> EnumMap<E, W>
282 where FnMap: Fn(&V) -> W,
283 E: PlainEnum,
284 {
285 E::map_from_fn(|e|
286 fn_map(&self[e])
287 )
288 }
289 pub fn map_into<FnMap, W>(self, fn_map: FnMap) -> EnumMap<E, W>
291 where FnMap: Fn(V) -> W,
292 E: PlainEnum,
293 <<E as PlainEnum>::EnumMapArray<V> as TArrayMapInto<V>>::MappedType::<W>: Into<E::EnumMapArray<W>>
294 {
295 EnumMap::<E, W>::from_raw(self.a.map_into2(fn_map).into())
296 }
297 pub fn into_raw(self) -> E::EnumMapArray::<V> {
299 self.a
300 }
301 pub fn as_raw(&self) -> &E::EnumMapArray::<V> {
303 &self.a
304 }
305 pub fn as_raw_mut(&mut self) -> &mut E::EnumMapArray::<V> {
307 &mut self.a
308 }
309 }
310 impl<E, V> Index<E> for EnumMap<E, V>
311 where E: PlainEnum,
312 {
313 type Output = V;
314 fn index(&self, e: E) -> &V {
315 unsafe { TArrayFromFn::index(&self.a, e.to_usize()) } }
317 }
318 impl<E, V> IndexMut<E> for EnumMap<E, V>
319 where E: PlainEnum,
320 {
321 fn index_mut(&mut self, e: E) -> &mut Self::Output {
322 unsafe { TArrayFromFn::index_mut(&mut self.a, e.to_usize()) } }
324 }
325
326 #[macro_export]
327 macro_rules! tt {
328 ($func: ident, [$($acc: expr,)*], []) => {
329 [$($acc,)*]
330 };
331 ($func: ident, [$($acc: expr,)*], [$enumval: ident, $($enumvals: ident,)*]) => {
332 acc_arr!($func, [$($acc,)* $func($enumval),], [$($enumvals,)*])
333 };
334 }
335
336
337 #[macro_export]
338 macro_rules! internal_impl_plainenum {($enumname: ty, $enumsize: expr, $from_usize: expr,) => {
339 unsafe impl PlainEnum for $enumname {
340 const SIZE : usize = $enumsize;
341 type EnumMapArray<T> = [T; $enumsize];
342 unsafe fn from_usize(u: usize) -> Self {
343 $from_usize(u)
344 }
345 fn to_usize(self) -> usize {
346 self as usize
347 }
348 }
349 }}
350
351 #[macro_export]
352 macro_rules! plain_enum_mod {
353 ($modname: ident, derive($($derives:ident, )*), map_derive($($mapderives:ident, )*), $enumname: ident {
354 $($enumvals: ident,)*
355 } ) => {
356 #[repr(usize)]
357 #[derive(PartialEq, Eq, Debug, Copy, Clone, PartialOrd, Ord, $($derives,)*)]
358 pub enum $enumname {
359 $(#[allow(dead_code)] $enumvals,)*
360 }
361 mod $modname {
362 use plain_enum::*;
363 use super::$enumname;
364
365 const SIZE : usize = enum_seq_len!($($enumvals,)*);
366 internal_impl_plainenum!(
367 $enumname,
368 SIZE,
369 |u|{
370 use std::mem;
371 debug_assert!(Self::valid_usize(u));
372 mem::transmute(u)
373 },
374 );
375 }
376 };
377 ($modname: ident, $enumname: ident {
378 $($enumvals: ident,)*
379 } ) => {
380 plain_enum_mod!($modname, derive(), map_derive(), $enumname { $($enumvals,)* });
381 };
382 }
383}
384
385pub use plain_enum::PlainEnum;
386pub use plain_enum::EnumMap;
387pub use plain_enum::TArrayMapInto;
388
389internal_impl_plainenum!(
390 bool,
391 2,
392 |u|{
393 debug_assert!(u==0 || u==1);
394 0!=u
395 },
396);
397
398unsafe impl PlainEnum for () {
399 const SIZE : usize = 1;
400 type EnumMapArray<T> = [T; 1];
401 unsafe fn from_usize(u: usize) -> Self {
402 debug_assert_eq!(0, u);
403 }
404 fn to_usize(self) -> usize {
405 0
406 }
407}
408
409unsafe impl PlainEnum for std::cmp::Ordering {
410 const SIZE : usize = 3;
411 type EnumMapArray<T> = [T; 3];
412 unsafe fn from_usize(u: usize) -> Self {
414 match u {
415 0 => std::cmp::Ordering::Less,
416 1 => std::cmp::Ordering::Equal,
417 u => {
418 debug_assert_eq!(u, 2);
419 std::cmp::Ordering::Greater
420 },
421 }
422 }
423 fn to_usize(self) -> usize {
424 match self {
425 std::cmp::Ordering::Less => 0,
426 std::cmp::Ordering::Equal => 1,
427 std::cmp::Ordering::Greater => 2,
428 }
429 }
430}
431
432#[cfg(test)]
436mod tests {
437 use plain_enum::*;
438 plain_enum_mod!{test_module, ETest {
439 E1, E2, E3,
440 }}
441 plain_enum_mod!{test_module_with_hash, derive(Hash,), map_derive(Hash,), ETestWithHash {
442 E1, E2, E3,
443 }}
444
445 #[test]
446 fn test_hash() {
447 use std::collections::HashSet;
448 let mut set = HashSet::new();
449 set.insert(ETestWithHash::E1);
450 assert!(set.contains(&ETestWithHash::E1));
451 assert!(!set.contains(&ETestWithHash::E2));
452 let enummap = ETestWithHash::map_from_fn(|e| e);
453 let mut set2 = HashSet::new();
454 set2.insert(enummap);
455 }
456
457 #[test]
458 fn test_clone() {
459 let map1 = ETest::map_from_fn(|e| e);
460 let map2 = map1.clone();
461 assert_eq!(map1, map2);
462 }
463
464 #[test]
465 fn test_enum_seq_len() {
466 assert_eq!(0, enum_seq_len!());
467 assert_eq!(1, enum_seq_len!(E1,));
468 assert_eq!(2, enum_seq_len!(E1, E3,));
469 assert_eq!(3, enum_seq_len!(E1, E2, E3,));
470 assert_eq!(14, enum_seq_len!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,));
471 assert_eq!(13, enum_seq_len!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, ));
472 }
473
474 #[test]
475 fn test_plain_enum() {
476 assert_eq!(3, ETest::SIZE);
477 }
478
479 #[test]
480 fn test_values() {
481 assert_eq!(vec![ETest::E1, ETest::E2, ETest::E3], ETest::values().collect::<Vec<_>>());
482 assert_eq!(ETest::values().count(), 3);
483 assert_eq!((3, Some(3)), ETest::values().size_hint());
484 assert_eq!(3, ETest::values().len());
485 assert!(ETest::values().eq(ETest::values().rev().rev()));
486 }
487
488 #[test]
489 fn test_enummap() {
490 let mut map_test_to_usize = ETest::map_from_fn(|test| test.to_usize());
491 for test in ETest::values() {
492 assert_eq!(map_test_to_usize[test], test.to_usize());
493 }
494 for test in ETest::values() {
495 map_test_to_usize[test] += 1;
496 }
497 for test in ETest::values() {
498 assert_eq!(map_test_to_usize[test], test.to_usize()+1);
499 }
500 for v in map_test_to_usize.iter().zip(ETest::values()) {
501 assert_eq!(*v.0, v.1.to_usize()+1);
502 }
503 for v in map_test_to_usize.map(|n| Some(n*n)).iter() {
504 assert!(v.is_some());
505 }
506 }
507
508 #[test]
509 fn test_map_into() {
510 struct NonCopy;
511 let map_test_to_usize = ETest::map_from_fn(|_| NonCopy);
512 let _map2 : EnumMap<_, (NonCopy, usize)> = map_test_to_usize.map_into(|noncopy| (noncopy, 0));
513 }
514
515 #[test]
516 fn test_bool() {
517 let mapbn = bool::map_from_fn(|b| b as usize);
518 assert_eq!(mapbn[false], 0);
519 assert_eq!(mapbn[true], 1);
520 }
521
522 #[test]
523 fn test_unit() {
524 let mapbn = <()>::map_from_fn(|()| 42);
525 assert_eq!(mapbn[()], 42);
526 assert_eq!(<()>::SIZE, 1);
527 }
528
529 #[test]
530 fn test_wrapped_difference() {
531 assert_eq!(ETest::E3.wrapped_difference_usize(ETest::E1), 2);
532 assert_eq!(ETest::E1.wrapped_difference_usize(ETest::E3), 1);
533 assert_eq!(ETest::E3.wrapped_difference(ETest::E1).0, ETest::E3);
534 assert_eq!(ETest::E1.wrapped_difference(ETest::E3).0, ETest::E2);
535 for e1 in ETest::values() {
536 for e2 in ETest::values() {
537 assert_eq!(e1.wrapped_difference_usize(e2), e1.wrapped_difference(e2).0.to_usize());
538 }
539 }
540 }
541
542 #[test]
543 fn test_default() {
544 let _enummap : EnumMap<ETest, usize> = Default::default();
545 }
546
547 #[test]
548 fn test_from_tuple() {
549 let enummap = ETest::map_from_tuple((1,2,3));
550 assert_eq!(enummap[ETest::E1], 1);
551 assert_eq!(enummap[ETest::E2], 2);
552 assert_eq!(enummap[ETest::E3], 3);
553 }
554}
555