@@ -713,89 +713,90 @@ macro_rules! arbitrary_tuple {
713
713
}
714
714
arbitrary_tuple ! ( A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ) ;
715
715
716
- macro_rules! arbitrary_array {
717
- { $n: expr, ( $t: ident, $a: ident) $( ( $ts: ident, $as: ident) ) * } => {
718
- arbitrary_array!{ ( $n - 1 ) , $( ( $ts, $as) ) * }
719
-
720
- impl <T : Arbitrary > Arbitrary for [ T ; $n] {
721
- fn arbitrary( u: & mut Unstructured <' _>) -> Result <[ T ; $n] > {
722
- Ok ( [
723
- Arbitrary :: arbitrary( u) ?,
724
- $( <$ts as Arbitrary >:: arbitrary( u) ?) ,*
725
- ] )
726
- }
727
-
728
- #[ allow( unused_mut) ]
729
- fn arbitrary_take_rest( mut u: Unstructured <' _>) -> Result <[ T ; $n] > {
730
- $( let $as = $ts:: arbitrary( & mut u) ?; ) *
731
- let last = Arbitrary :: arbitrary_take_rest( u) ?;
732
-
733
- Ok ( [
734
- $( $as, ) * last
735
- ] )
736
- }
716
+ struct ArrayGuard < T , const N : usize > {
717
+ dst : * mut T ,
718
+ initialized : usize ,
719
+ }
737
720
738
- #[ inline]
739
- fn size_hint( depth: usize ) -> ( usize , Option <usize >) {
740
- crate :: size_hint:: and_all( & [
741
- <$t as Arbitrary >:: size_hint( depth) ,
742
- $( <$ts as Arbitrary >:: size_hint( depth) ) ,*
743
- ] )
744
- }
721
+ impl < T , const N : usize > Drop for ArrayGuard < T , N > {
722
+ fn drop ( & mut self ) {
723
+ debug_assert ! ( self . initialized <= N ) ;
724
+ let initialized_part = core:: ptr:: slice_from_raw_parts_mut ( self . dst , self . initialized ) ;
725
+ unsafe {
726
+ core:: ptr:: drop_in_place ( initialized_part) ;
727
+ }
728
+ }
729
+ }
745
730
746
- #[ allow( unused_mut) ] // For the `[T; 1]` case.
747
- fn shrink( & self ) -> Box <dyn Iterator <Item = Self >> {
748
- let mut i = 0 ;
749
- let mut shrinkers = [
750
- self [ i] . shrink( ) ,
751
- $( {
752
- i += 1 ;
753
- let t: & $ts = & self [ i] ;
754
- t. shrink( )
755
- } ) ,*
756
- ] ;
757
- Box :: new( iter:: from_fn( move || {
758
- let mut i = 0 ;
759
- Some ( [
760
- shrinkers[ i] . next( ) ?,
761
- $( {
762
- i += 1 ;
763
- let t: $ts = shrinkers[ i] . next( ) ?;
764
- t
765
- } ) ,*
766
- ] )
767
- } ) )
768
- }
731
+ fn create_array < F , T , const N : usize > ( mut cb : F ) -> [ T ; N ]
732
+ where
733
+ F : FnMut ( usize ) -> T ,
734
+ {
735
+ let mut array: mem:: MaybeUninit < [ T ; N ] > = mem:: MaybeUninit :: uninit ( ) ;
736
+ let mut guard: ArrayGuard < T , N > = ArrayGuard {
737
+ dst : array. as_mut_ptr ( ) as _ ,
738
+ initialized : 0 ,
739
+ } ;
740
+ unsafe {
741
+ for ( idx, value_ptr) in ( & mut * array. as_mut_ptr ( ) ) . iter_mut ( ) . enumerate ( ) {
742
+ core:: ptr:: write ( value_ptr, cb ( idx) ) ;
743
+ guard. initialized += 1 ;
769
744
}
745
+ mem:: forget ( guard) ;
746
+ array. assume_init ( )
747
+ }
748
+ }
749
+
750
+ fn try_create_array < F , T , const N : usize > ( mut cb : F ) -> Result < [ T ; N ] >
751
+ where
752
+ F : FnMut ( usize ) -> Result < T > ,
753
+ {
754
+ let mut array: mem:: MaybeUninit < [ T ; N ] > = mem:: MaybeUninit :: uninit ( ) ;
755
+ let mut guard: ArrayGuard < T , N > = ArrayGuard {
756
+ dst : array. as_mut_ptr ( ) as _ ,
757
+ initialized : 0 ,
770
758
} ;
771
- ( $n: expr, ) => { } ;
759
+ unsafe {
760
+ for ( idx, value_ptr) in ( & mut * array. as_mut_ptr ( ) ) . iter_mut ( ) . enumerate ( ) {
761
+ core:: ptr:: write ( value_ptr, cb ( idx) ?) ;
762
+ guard. initialized += 1 ;
763
+ }
764
+ mem:: forget ( guard) ;
765
+ Ok ( array. assume_init ( ) )
766
+ }
772
767
}
773
768
774
- impl < T : Arbitrary > Arbitrary for [ T ; 0 ] {
775
- fn arbitrary ( _: & mut Unstructured < ' _ > ) -> Result < [ T ; 0 ] > {
776
- Ok ( [ ] )
769
+ impl < T , const N : usize > Arbitrary for [ T ; N ]
770
+ where
771
+ T : Arbitrary ,
772
+ {
773
+ fn arbitrary ( u : & mut Unstructured < ' _ > ) -> Result < [ T ; N ] > {
774
+ try_create_array ( |_| <T as Arbitrary >:: arbitrary ( u) )
777
775
}
778
776
779
- fn arbitrary_take_rest ( _: Unstructured < ' _ > ) -> Result < [ T ; 0 ] > {
780
- Ok ( [ ] )
777
+ fn arbitrary_take_rest ( mut u : Unstructured < ' _ > ) -> Result < [ T ; N ] > {
778
+ let mut array = Self :: arbitrary ( & mut u) ?;
779
+ if let Some ( last) = array. last_mut ( ) {
780
+ * last = Arbitrary :: arbitrary_take_rest ( u) ?;
781
+ }
782
+ Ok ( array)
781
783
}
782
784
783
- #[ inline]
784
- fn size_hint ( _: usize ) -> ( usize , Option < usize > ) {
785
- crate :: size_hint:: and_all ( & [ ] )
785
+ fn size_hint ( d : usize ) -> ( usize , Option < usize > ) {
786
+ crate :: size_hint:: and_all ( & create_array :: < _ , ( usize , Option < usize > ) , N > ( |_| {
787
+ <T as Arbitrary >:: size_hint ( d)
788
+ } ) )
786
789
}
787
790
788
791
fn shrink ( & self ) -> Box < dyn Iterator < Item = Self > > {
789
- Box :: new ( iter:: from_fn ( || None ) )
792
+ let mut shrinkers =
793
+ create_array :: < _ , Box < dyn Iterator < Item = T > > , N > ( |idx| self [ idx] . shrink ( ) ) ;
794
+ Box :: new ( iter:: from_fn ( move || {
795
+ try_create_array ( |idx| shrinkers[ idx] . next ( ) . ok_or ( Error :: NotEnoughData ) ) . ok ( )
796
+ } ) )
790
797
}
791
798
}
792
799
793
- arbitrary_array ! { 32 , ( T , a) ( T , b) ( T , c) ( T , d) ( T , e) ( T , f) ( T , g) ( T , h)
794
- ( T , i) ( T , j) ( T , k) ( T , l) ( T , m) ( T , n) ( T , o) ( T , p)
795
- ( T , q) ( T , r) ( T , s) ( T , u) ( T , v) ( T , w) ( T , x) ( T , y)
796
- ( T , z) ( T , aa) ( T , ab) ( T , ac) ( T , ad) ( T , ae) ( T , af)
797
- ( T , ag) }
798
-
799
800
fn shrink_collection < ' a , T , A : Arbitrary > (
800
801
entries : impl Iterator < Item = T > ,
801
802
f : impl Fn ( & T ) -> Box < dyn Iterator < Item = A > > ,
0 commit comments