1#![deny(missing_docs)]
64#![deny(warnings)]
65#![no_std]
66
67use core::{cmp::Ordering, iter::FusedIterator, ops::ControlFlow, task::Poll};
68
69pub use enum_iterator_derive::Sequence;
70
71pub const fn cardinality<T: Sequence>() -> usize {
83 T::CARDINALITY
84}
85
86pub fn all<T: Sequence>() -> All<T> {
104 All(T::first())
105}
106
107pub fn reverse_all<T: Sequence>() -> ReverseAll<T> {
122 ReverseAll(T::last())
123}
124
125pub fn next<T: Sequence>(x: &T) -> Option<T> {
139 x.next()
140}
141
142pub fn next_cycle<T: Sequence>(x: &T) -> T {
154 next(x)
155 .or_else(first)
156 .expect("Sequence::first returned None for inhabited type")
157}
158
159pub fn previous<T: Sequence>(x: &T) -> Option<T> {
173 x.previous()
174}
175
176pub fn previous_cycle<T: Sequence>(x: &T) -> T {
188 previous(x)
189 .or_else(last)
190 .expect("Sequence::last returned None for inhabited type")
191}
192
193pub fn first<T: Sequence>() -> Option<T> {
207 T::first()
208}
209
210pub fn last<T: Sequence>() -> Option<T> {
224 T::last()
225}
226
227#[derive(Clone, Debug)]
231pub struct All<T>(Option<T>);
232
233impl<T: Sequence> Iterator for All<T> {
234 type Item = T;
235
236 fn next(&mut self) -> Option<T> {
237 let item = self.0.take()?;
238 self.0 = item.next();
239 Some(item)
240 }
241}
242
243impl<T: Sequence> FusedIterator for All<T> {}
244
245#[derive(Clone, Debug)]
249pub struct ReverseAll<T>(Option<T>);
250
251impl<T: Sequence> Iterator for ReverseAll<T> {
252 type Item = T;
253
254 fn next(&mut self) -> Option<T> {
255 let item = self.0.take()?;
256 self.0 = item.previous();
257 Some(item)
258 }
259}
260
261impl<T: Sequence> FusedIterator for ReverseAll<T> {}
262
263pub trait Sequence: Sized {
380 const CARDINALITY: usize;
392
393 fn next(&self) -> Option<Self>;
418
419 fn previous(&self) -> Option<Self>;
431
432 fn first() -> Option<Self>;
444
445 fn last() -> Option<Self>;
457}
458
459impl Sequence for bool {
460 const CARDINALITY: usize = 2;
461
462 fn next(&self) -> Option<Self> {
463 (!*self).then_some(true)
464 }
465
466 fn previous(&self) -> Option<Self> {
467 (*self).then_some(false)
468 }
469
470 fn first() -> Option<Self> {
471 Some(false)
472 }
473
474 fn last() -> Option<Self> {
475 Some(true)
476 }
477}
478
479macro_rules! impl_sequence_for_int {
480 ($ty:ty) => {
481 impl Sequence for $ty {
482 const CARDINALITY: usize = 1 << <$ty>::BITS;
483
484 fn next(&self) -> Option<Self> {
485 self.checked_add(1)
486 }
487
488 fn previous(&self) -> Option<Self> {
489 self.checked_sub(1)
490 }
491
492 fn first() -> Option<Self> {
493 Some(Self::MIN)
494 }
495
496 fn last() -> Option<Self> {
497 Some(Self::MAX)
498 }
499 }
500 };
501}
502
503impl_sequence_for_int!(i8);
504impl_sequence_for_int!(u8);
505impl_sequence_for_int!(i16);
506impl_sequence_for_int!(u16);
507
508impl Sequence for () {
509 const CARDINALITY: usize = 1;
510
511 fn next(&self) -> Option<Self> {
512 None
513 }
514
515 fn previous(&self) -> Option<Self> {
516 None
517 }
518
519 fn first() -> Option<Self> {
520 Some(())
521 }
522
523 fn last() -> Option<Self> {
524 Some(())
525 }
526}
527
528impl Sequence for core::convert::Infallible {
529 const CARDINALITY: usize = 0;
530
531 fn next(&self) -> Option<Self> {
532 None
533 }
534
535 fn previous(&self) -> Option<Self> {
536 None
537 }
538
539 fn first() -> Option<Self> {
540 None
541 }
542
543 fn last() -> Option<Self> {
544 None
545 }
546}
547
548impl Sequence for Ordering {
549 const CARDINALITY: usize = 3;
550
551 fn next(&self) -> Option<Self> {
552 int_to_ordering(*self as i8 + 1)
553 }
554
555 fn previous(&self) -> Option<Self> {
556 int_to_ordering(*self as i8 - 1)
557 }
558
559 fn first() -> Option<Self> {
560 Some(Ordering::Less)
561 }
562
563 fn last() -> Option<Self> {
564 Some(Ordering::Greater)
565 }
566}
567
568fn int_to_ordering(i: i8) -> Option<Ordering> {
569 match i {
570 -1 => Some(Ordering::Less),
571 0 => Some(Ordering::Equal),
572 1 => Some(Ordering::Greater),
573 _ => None,
574 }
575}
576
577impl<T: Sequence> Sequence for Option<T> {
578 const CARDINALITY: usize = T::CARDINALITY + 1;
579
580 fn next(&self) -> Option<Self> {
581 match self {
582 None => T::first().map(Some),
583 Some(x) => x.next().map(Some),
584 }
585 }
586
587 fn previous(&self) -> Option<Self> {
588 self.as_ref().map(T::previous)
589 }
590
591 fn first() -> Option<Self> {
592 Some(None)
593 }
594
595 fn last() -> Option<Self> {
596 Some(T::last())
597 }
598}
599
600impl<T: Sequence> Sequence for Poll<T> {
601 const CARDINALITY: usize = T::CARDINALITY + 1;
602
603 fn next(&self) -> Option<Self> {
604 match self {
605 Poll::Ready(x) => x.next().map(Poll::Ready).or(Some(Poll::Pending)),
606 Poll::Pending => None,
607 }
608 }
609
610 fn previous(&self) -> Option<Self> {
611 match self {
612 Poll::Ready(x) => x.previous().map(Poll::Ready),
613 Poll::Pending => T::last().map(Poll::Ready),
614 }
615 }
616
617 fn first() -> Option<Self> {
618 T::first().map(Poll::Ready).or(Some(Poll::Pending))
619 }
620
621 fn last() -> Option<Self> {
622 Some(Poll::Pending)
623 }
624}
625
626impl<const N: usize, T: Sequence + Clone> Sequence for [T; N] {
627 const CARDINALITY: usize = {
628 let tc = T::CARDINALITY;
629 let mut c = 1;
630 let mut i = 0;
631 loop {
632 if i == N {
633 break c;
634 }
635 c *= tc;
636 i += 1;
637 }
638 };
639
640 fn next(&self) -> Option<Self> {
641 advance_for_array(self, T::first)
642 }
643
644 fn previous(&self) -> Option<Self> {
645 advance_for_array(self, T::last)
646 }
647
648 fn first() -> Option<Self> {
649 if N == 0 {
650 Some(core::array::from_fn(|_| unreachable!()))
651 } else {
652 let x = T::first()?;
653 Some(core::array::from_fn(|_| x.clone()))
654 }
655 }
656
657 fn last() -> Option<Self> {
658 if N == 0 {
659 Some(core::array::from_fn(|_| unreachable!()))
660 } else {
661 let x = T::last()?;
662 Some(core::array::from_fn(|_| x.clone()))
663 }
664 }
665}
666
667fn advance_for_array<const N: usize, T, R>(a: &[T; N], reset: R) -> Option<[T; N]>
668where
669 T: Sequence + Clone,
670 R: Fn() -> Option<T>,
671{
672 let mut a = a.clone();
673 let keep = a.iter_mut().rev().try_fold((), |_, x| match x.next() {
674 Some(new_x) => {
675 *x = new_x;
676 ControlFlow::Break(true)
677 }
678 None => match reset() {
679 Some(new_x) => {
680 *x = new_x;
681 ControlFlow::Continue(())
682 }
683 None => ControlFlow::Break(false),
684 },
685 });
686 Some(a).filter(|_| matches!(keep, ControlFlow::Break(true)))
687}
688
689macro_rules! impl_seq_advance_for_tuple {
690 (
691 $this:ident,
692 $advance:ident,
693 $reset:ident,
694 $carry:ident
695 @ $($values:expr,)*
696 @
697 @ $($placeholders:pat,)*
698 ) => {
699 Some(($($values,)*)).filter(|_| !$carry)
700 };
701 (
702 $this:ident,
703 $advance:ident,
704 $reset:ident,
705 $carry:ident
706 @ $($values:expr,)*
707 @ $ty:ident, $($types:ident,)*
708 @ $($placeholders:pat,)*
709 ) => {{
710 let (.., item, $($placeholders,)*) = $this;
711 let (x, new_carry) = if $carry {
712 match Sequence::$advance(item) {
713 Some(x) => (x, false),
714 None => (Sequence::$reset()?, true),
715 }
716 } else {
717 (item.clone(), false)
718 };
719 impl_seq_advance_for_tuple!(
720 $this,
721 $advance,
722 $reset,
723 new_carry
724 @ x, $($values,)*
725 @ $($types,)*
726 @ _, $($placeholders,)*
727 )
728 }};
729 ($this:ident, $advance:ident, $reset:ident @ $($types:ident,)*) => {{
730 let (.., item) = $this;
731 let (x, carry) = match Sequence::$advance(item) {
732 Some(x) => (x, false),
733 None => (Sequence::$reset()?, true),
734 };
735 impl_seq_advance_for_tuple!($this, $advance, $reset, carry @ x, @ $($types,)* @ _,)
736 }};
737}
738
739macro_rules! impl_sequence_for_tuple {
740 ($($types:ident,)* @ $last:ident) => {
741 impl<$($types,)* $last> Sequence for ($($types,)* $last,)
742 where
743 $($types: Sequence + Clone,)*
744 $last: Sequence,
745 {
746 const CARDINALITY: usize =
747 $(<$types as Sequence>::CARDINALITY *)* <$last as Sequence>::CARDINALITY;
748
749 fn next(&self) -> Option<Self> {
750 impl_seq_advance_for_tuple!(self, next, first @ $($types,)*)
751 }
752
753 fn previous(&self) -> Option<Self> {
754 impl_seq_advance_for_tuple!(self, previous, last @ $($types,)*)
755 }
756
757 fn first() -> Option<Self> {
758 Some((
759 $(<$types as Sequence>::first()?,)*
760 <$last as Sequence>::first()?,
761 ))
762 }
763
764 fn last() -> Option<Self> {
765 Some((
766 $(<$types as Sequence>::last()?,)*
767 <$last as Sequence>::last()?,
768 ))
769 }
770 }
771 };
772}
773
774macro_rules! impl_sequence_for_tuples {
775 ($($types:ident,)*) => {
776 impl_sequence_for_tuples!(@ $($types,)*);
777 };
778 ($($types:ident,)* @ $head:ident, $($tail:ident,)*) => {
779 impl_sequence_for_tuple!($($types,)* @ $head);
780 impl_sequence_for_tuples!($($types,)* $head, @ $($tail,)*);
781 };
782 ($($types:ident,)* @) => {};
783}
784
785impl_sequence_for_tuples!(
786 T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20,
787 T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31,
788);
789
790#[cfg(test)]
791mod tests {
792 use crate::{all, cardinality, reverse_all, Sequence};
793 use core::{cmp::Ordering, convert::Infallible, task::Poll};
794
795 fn cardinality_equals_item_count<T: Sequence>() {
796 assert_eq!(cardinality::<T>(), all::<T>().count());
797 }
798
799 #[test]
800 fn cardinality_equals_item_count_for_bool() {
801 cardinality_equals_item_count::<bool>();
802 }
803
804 #[test]
805 fn all_bool_values_are_yielded() {
806 assert!(all::<bool>().eq([false, true]));
807 }
808
809 #[test]
810 fn all_bool_values_are_yielded_in_reverse() {
811 assert!(reverse_all::<bool>().eq([true, false]));
812 }
813
814 #[test]
815 fn cardinality_equals_item_count_for_i8() {
816 cardinality_equals_item_count::<i8>();
817 }
818
819 #[test]
820 fn all_i8_values_are_yielded() {
821 assert!(all::<i8>().eq(i8::MIN..=i8::MAX));
822 }
823
824 #[test]
825 fn all_i8_values_are_yielded_in_reverse() {
826 assert!(reverse_all::<i8>().eq((i8::MIN..=i8::MAX).rev()));
827 }
828
829 #[test]
830 fn cardinality_equals_item_count_for_u8() {
831 cardinality_equals_item_count::<u8>();
832 }
833
834 #[test]
835 fn all_u8_values_are_yielded() {
836 assert!(all::<u8>().eq(u8::MIN..=u8::MAX));
837 }
838
839 #[test]
840 fn all_u8_values_are_yielded_in_reverse() {
841 assert!(reverse_all::<u8>().eq((u8::MIN..=u8::MAX).rev()));
842 }
843
844 #[test]
845 fn cardinality_equals_item_count_for_i16() {
846 cardinality_equals_item_count::<i16>();
847 }
848
849 #[test]
850 fn all_i16_values_are_yielded() {
851 assert!(all::<i16>().eq(i16::MIN..=i16::MAX));
852 }
853
854 #[test]
855 fn all_i16_values_are_yielded_in_reverse() {
856 assert!(reverse_all::<i16>().eq((i16::MIN..=i16::MAX).rev()));
857 }
858
859 #[test]
860 fn cardinality_equals_item_count_for_u16() {
861 cardinality_equals_item_count::<u16>();
862 }
863
864 #[test]
865 fn all_u16_values_are_yielded() {
866 assert!(all::<u16>().eq(u16::MIN..=u16::MAX));
867 }
868
869 #[test]
870 fn all_u16_values_are_yielded_in_reverse() {
871 assert!(reverse_all::<u16>().eq((u16::MIN..=u16::MAX).rev()));
872 }
873
874 #[test]
875 fn cardinality_equals_item_count_for_unit() {
876 cardinality_equals_item_count::<()>();
877 }
878
879 #[test]
880 fn all_unit_values_are_yielded() {
881 assert!(all::<()>().eq([()]));
882 }
883
884 #[test]
885 fn all_unit_values_are_yielded_in_reverse() {
886 assert!(reverse_all::<()>().eq([()]));
887 }
888
889 #[test]
890 fn cardinality_equals_item_count_for_infallible() {
891 cardinality_equals_item_count::<Infallible>();
892 }
893
894 #[test]
895 fn all_infallible_values_are_yielded() {
896 assert!(all::<Infallible>().next().is_none());
897 }
898
899 #[test]
900 fn all_infallible_values_are_yielded_in_reverse() {
901 assert!(reverse_all::<Infallible>().next().is_none());
902 }
903
904 #[test]
905 fn cardinality_equals_item_count_for_tuple_with_infallible() {
906 cardinality_equals_item_count::<(bool, Infallible)>();
907 }
908
909 #[test]
910 fn all_tuple_with_infallible_values_are_yielded() {
911 assert!(all::<(bool, Infallible)>().next().is_none());
912 }
913
914 #[test]
915 fn all_tuple_with_infallible_values_are_yielded_in_reverse() {
916 assert!(reverse_all::<(bool, Infallible)>().next().is_none());
917 }
918
919 #[test]
920 fn cardinality_equals_item_count_for_singleton() {
921 cardinality_equals_item_count::<(u8,)>();
922 }
923
924 #[test]
925 fn cardinality_equals_item_count_for_pair() {
926 cardinality_equals_item_count::<(u8, bool)>();
927 }
928
929 #[test]
930 fn cardinality_equals_item_count_for_triple() {
931 cardinality_equals_item_count::<(bool, u8, bool)>();
932 }
933
934 #[test]
935 fn cardinality_equals_item_count_for_option() {
936 cardinality_equals_item_count::<Option<u8>>();
937 }
938
939 #[test]
940 fn all_bool_option_items_are_yielded() {
941 assert!(all::<Option<bool>>().eq([None, Some(false), Some(true)]));
942 }
943
944 #[test]
945 fn all_bool_option_items_are_yielded_in_reverse() {
946 assert!(reverse_all::<Option<bool>>().eq([Some(true), Some(false), None]));
947 }
948
949 #[test]
950 fn all_infallible_option_items_are_yielded() {
951 assert!(all::<Option<Infallible>>().eq([None]));
952 }
953
954 #[test]
955 fn all_infallible_option_items_are_yielded_in_reverse() {
956 assert!(reverse_all::<Option<Infallible>>().eq([None]));
957 }
958
959 #[test]
960 fn cardinality_equals_item_count_for_ordering() {
961 cardinality_equals_item_count::<Ordering>();
962 }
963
964 #[test]
965 fn all_ordering_values_are_yielded() {
966 assert!(all::<Ordering>().eq([Ordering::Less, Ordering::Equal, Ordering::Greater]));
967 }
968
969 #[test]
970 fn all_ordering_values_are_yielded_in_reverse() {
971 assert!(reverse_all::<Ordering>().eq([Ordering::Greater, Ordering::Equal, Ordering::Less]));
972 }
973
974 #[test]
975 fn cardinality_equals_item_count_for_poll() {
976 cardinality_equals_item_count::<Poll<u8>>();
977 }
978
979 #[test]
980 fn all_bool_poll_items_are_yielded() {
981 assert!(all::<Poll<bool>>().eq([Poll::Ready(false), Poll::Ready(true), Poll::Pending]));
982 }
983
984 #[test]
985 fn all_bool_poll_items_are_yielded_in_reverse() {
986 assert!(reverse_all::<Poll<bool>>().eq([
987 Poll::Pending,
988 Poll::Ready(true),
989 Poll::Ready(false),
990 ]));
991 }
992
993 #[test]
994 fn all_infallible_poll_items_are_yielded() {
995 assert!(all::<Poll<Infallible>>().eq([Poll::Pending]));
996 }
997
998 #[test]
999 fn all_infallible_poll_items_are_yielded_in_reverse() {
1000 assert!(reverse_all::<Poll<Infallible>>().eq([Poll::Pending]));
1001 }
1002
1003 #[test]
1004 fn tuple_fields_vary_from_right_to_left() {
1005 assert!(all::<(Option<bool>, bool)>().eq([
1006 (None, false),
1007 (None, true),
1008 (Some(false), false),
1009 (Some(false), true),
1010 (Some(true), false),
1011 (Some(true), true),
1012 ]));
1013 }
1014
1015 #[test]
1016 fn cardinality_of_empty_array_is_one() {
1017 assert_eq!(cardinality::<[u8; 0]>(), 1);
1018 }
1019
1020 #[test]
1021 fn cardinality_equals_item_count_for_empty_array() {
1022 cardinality_equals_item_count::<[u8; 0]>();
1023 }
1024
1025 #[test]
1026 fn cardinality_equals_item_count_for_array() {
1027 cardinality_equals_item_count::<[u8; 3]>();
1028 }
1029
1030 #[test]
1031 fn array_items_vary_from_right_to_left() {
1032 assert!(all::<[Option<bool>; 2]>().eq([
1033 [None, None],
1034 [None, Some(false)],
1035 [None, Some(true)],
1036 [Some(false), None],
1037 [Some(false), Some(false)],
1038 [Some(false), Some(true)],
1039 [Some(true), None],
1040 [Some(true), Some(false)],
1041 [Some(true), Some(true)],
1042 ]));
1043 }
1044
1045 #[test]
1046 fn all_empty_array_items_are_yielded() {
1047 assert!(all::<[bool; 0]>().eq([[]]));
1048 }
1049
1050 #[test]
1051 fn cardinality_of_empty_infallible_array_is_one() {
1052 assert_eq!(cardinality::<[Infallible; 0]>(), 1);
1053 }
1054
1055 #[test]
1056 fn cardinality_of_non_empty_infallible_array_is_zero() {
1057 assert_eq!(cardinality::<[Infallible; 1]>(), 0);
1058 }
1059
1060 #[test]
1061 fn all_empty_infallible_array_items_are_yielded() {
1062 assert!(all::<[Infallible; 0]>().eq([[]]));
1063 }
1064
1065 #[test]
1066 fn all_non_empty_infallible_array_items_are_yielded() {
1067 assert!(all::<[Infallible; 1]>().next().is_none());
1068 }
1069}