6464#![ deny( warnings) ]
6565#![ no_std]
6666
67- use core:: iter:: FusedIterator ;
67+ use core:: { iter:: FusedIterator , ops :: ControlFlow } ;
6868
6969pub use enum_iterator_derive:: Sequence ;
7070
@@ -527,6 +527,69 @@ impl<T: Sequence> Sequence for Option<T> {
527527 }
528528}
529529
530+ impl < const N : usize , T : Sequence + Clone > Sequence for [ T ; N ] {
531+ const CARDINALITY : usize = {
532+ let tc = T :: CARDINALITY ;
533+ let mut c = 1 ;
534+ let mut i = 0 ;
535+ loop {
536+ if i == N {
537+ break c;
538+ }
539+ c *= tc;
540+ i += 1 ;
541+ }
542+ } ;
543+
544+ fn next ( & self ) -> Option < Self > {
545+ advance_for_array ( self , T :: first)
546+ }
547+
548+ fn previous ( & self ) -> Option < Self > {
549+ advance_for_array ( self , T :: last)
550+ }
551+
552+ fn first ( ) -> Option < Self > {
553+ if N == 0 {
554+ Some ( core:: array:: from_fn ( |_| unreachable ! ( ) ) )
555+ } else {
556+ let x = T :: first ( ) ?;
557+ Some ( core:: array:: from_fn ( |_| x. clone ( ) ) )
558+ }
559+ }
560+
561+ fn last ( ) -> Option < Self > {
562+ if N == 0 {
563+ Some ( core:: array:: from_fn ( |_| unreachable ! ( ) ) )
564+ } else {
565+ let x = T :: last ( ) ?;
566+ Some ( core:: array:: from_fn ( |_| x. clone ( ) ) )
567+ }
568+ }
569+ }
570+
571+ fn advance_for_array < const N : usize , T , R > ( a : & [ T ; N ] , reset : R ) -> Option < [ T ; N ] >
572+ where
573+ T : Sequence + Clone ,
574+ R : Fn ( ) -> Option < T > ,
575+ {
576+ let mut a = a. clone ( ) ;
577+ let keep = a. iter_mut ( ) . rev ( ) . try_fold ( ( ) , |_, x| match x. next ( ) {
578+ Some ( new_x) => {
579+ * x = new_x;
580+ ControlFlow :: Break ( true )
581+ }
582+ None => match reset ( ) {
583+ Some ( new_x) => {
584+ * x = new_x;
585+ ControlFlow :: Continue ( ( ) )
586+ }
587+ None => ControlFlow :: Break ( false ) ,
588+ } ,
589+ } ) ;
590+ Some ( a) . filter ( |_| matches ! ( keep, ControlFlow :: Break ( true ) ) )
591+ }
592+
530593macro_rules! impl_seq_advance_for_tuple {
531594 (
532595 $this: ident,
@@ -778,7 +841,7 @@ mod tests {
778841 }
779842
780843 #[ test]
781- fn check_option_items ( ) {
844+ fn all_bool_option_items_are_yielded ( ) {
782845 assert ! ( all:: <Option <bool >>( ) . eq( [ None , Some ( false ) , Some ( true ) ] ) ) ;
783846 }
784847
@@ -793,4 +856,59 @@ mod tests {
793856 ( Some ( true ) , true ) ,
794857 ] ) ) ;
795858 }
859+
860+ #[ test]
861+ fn cardinality_of_empty_array_is_one ( ) {
862+ assert_eq ! ( cardinality:: <[ u8 ; 0 ] >( ) , 1 ) ;
863+ }
864+
865+ #[ test]
866+ fn cardinality_equals_item_count_for_empty_array ( ) {
867+ cardinality_equals_item_count :: < [ u8 ; 0 ] > ( ) ;
868+ }
869+
870+ #[ test]
871+ fn cardinality_equals_item_count_for_array ( ) {
872+ cardinality_equals_item_count :: < [ u8 ; 3 ] > ( ) ;
873+ }
874+
875+ #[ test]
876+ fn array_items_vary_from_right_to_left ( ) {
877+ assert ! ( all:: <[ Option <bool >; 2 ] >( ) . eq( [
878+ [ None , None ] ,
879+ [ None , Some ( false ) ] ,
880+ [ None , Some ( true ) ] ,
881+ [ Some ( false ) , None ] ,
882+ [ Some ( false ) , Some ( false ) ] ,
883+ [ Some ( false ) , Some ( true ) ] ,
884+ [ Some ( true ) , None ] ,
885+ [ Some ( true ) , Some ( false ) ] ,
886+ [ Some ( true ) , Some ( true ) ] ,
887+ ] ) ) ;
888+ }
889+
890+ #[ test]
891+ fn all_empty_array_items_are_yielded ( ) {
892+ assert ! ( all:: <[ bool ; 0 ] >( ) . eq( [ [ ] ] ) ) ;
893+ }
894+
895+ #[ test]
896+ fn cardinality_of_empty_infallible_array_is_one ( ) {
897+ assert_eq ! ( cardinality:: <[ Infallible ; 0 ] >( ) , 1 ) ;
898+ }
899+
900+ #[ test]
901+ fn cardinality_of_non_empty_infallible_array_is_zero ( ) {
902+ assert_eq ! ( cardinality:: <[ Infallible ; 1 ] >( ) , 0 ) ;
903+ }
904+
905+ #[ test]
906+ fn all_empty_infallible_array_items_are_yielded ( ) {
907+ assert ! ( all:: <[ Infallible ; 0 ] >( ) . eq( [ [ ] ] ) ) ;
908+ }
909+
910+ #[ test]
911+ fn all_non_empty_infallible_array_items_are_yielded ( ) {
912+ assert ! ( all:: <[ Infallible ; 1 ] >( ) . next( ) . is_none( ) ) ;
913+ }
796914}
0 commit comments