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