@@ -571,74 +571,82 @@ macro_rules! arbitrary_tuple {
571571}
572572arbitrary_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 ) ;
573573
574- macro_rules! arbitrary_array {
575- { $n: expr, ( $t: ident, $a: ident) $( ( $ts: ident, $as: ident) ) * } => {
576- arbitrary_array!{ ( $n - 1 ) , $( ( $ts, $as) ) * }
577-
578- impl <' a, T : Arbitrary <' a>> Arbitrary <' a> for [ T ; $n] {
579- fn arbitrary( u: & mut Unstructured <' a>) -> Result <[ T ; $n] > {
580- Ok ( [
581- Arbitrary :: arbitrary( u) ?,
582- $( <$ts as Arbitrary >:: arbitrary( u) ?) ,*
583- ] )
584- }
585-
586- #[ allow( unused_mut) ]
587- fn arbitrary_take_rest( mut u: Unstructured <' a>) -> Result <[ T ; $n] > {
588- $( let $as = $ts:: arbitrary( & mut u) ?; ) *
589- let last = Arbitrary :: arbitrary_take_rest( u) ?;
590-
591- Ok ( [
592- $( $as, ) * last
593- ] )
594- }
595-
596- #[ inline]
597- fn size_hint( depth: usize ) -> ( usize , Option <usize >) {
598- crate :: size_hint:: and_all( & [
599- <$t as Arbitrary >:: size_hint( depth) ,
600- $( <$ts as Arbitrary >:: size_hint( depth) ) ,*
601- ] )
602- }
603- }
604- } ;
605- ( $n: expr, ) => { } ;
574+ struct ArrayGuard < T , const N : usize > {
575+ dst : * mut T ,
576+ initialized : usize ,
606577}
607578
608- impl < ' a , T : Arbitrary < ' a > > Arbitrary < ' a > for [ T ; 0 ] {
609- fn arbitrary ( _: & mut Unstructured < ' a > ) -> Result < [ T ; 0 ] > {
610- Ok ( [ ] )
579+ impl < T , const N : usize > Drop for ArrayGuard < T , N > {
580+ fn drop ( & mut self ) {
581+ debug_assert ! ( self . initialized <= N ) ;
582+ let initialized_part = core:: ptr:: slice_from_raw_parts_mut ( self . dst , self . initialized ) ;
583+ unsafe {
584+ core:: ptr:: drop_in_place ( initialized_part) ;
585+ }
611586 }
587+ }
612588
613- fn arbitrary_take_rest ( _: Unstructured < ' a > ) -> Result < [ T ; 0 ] > {
614- Ok ( [ ] )
589+ fn create_array < F , T , const N : usize > ( mut cb : F ) -> [ T ; N ]
590+ where
591+ F : FnMut ( usize ) -> T ,
592+ {
593+ let mut array: mem:: MaybeUninit < [ T ; N ] > = mem:: MaybeUninit :: uninit ( ) ;
594+ let mut guard: ArrayGuard < T , N > = ArrayGuard {
595+ dst : array. as_mut_ptr ( ) as _ ,
596+ initialized : 0 ,
597+ } ;
598+ unsafe {
599+ for ( idx, value_ptr) in ( & mut * array. as_mut_ptr ( ) ) . iter_mut ( ) . enumerate ( ) {
600+ core:: ptr:: write ( value_ptr, cb ( idx) ) ;
601+ guard. initialized += 1 ;
602+ }
603+ mem:: forget ( guard) ;
604+ array. assume_init ( )
615605 }
606+ }
616607
617- #[ inline]
618- fn size_hint ( _: usize ) -> ( usize , Option < usize > ) {
619- crate :: size_hint:: and_all ( & [ ] )
608+ fn try_create_array < F , T , const N : usize > ( mut cb : F ) -> Result < [ T ; N ] >
609+ where
610+ F : FnMut ( usize ) -> Result < T > ,
611+ {
612+ let mut array: mem:: MaybeUninit < [ T ; N ] > = mem:: MaybeUninit :: uninit ( ) ;
613+ let mut guard: ArrayGuard < T , N > = ArrayGuard {
614+ dst : array. as_mut_ptr ( ) as _ ,
615+ initialized : 0 ,
616+ } ;
617+ unsafe {
618+ for ( idx, value_ptr) in ( & mut * array. as_mut_ptr ( ) ) . iter_mut ( ) . enumerate ( ) {
619+ core:: ptr:: write ( value_ptr, cb ( idx) ?) ;
620+ guard. initialized += 1 ;
621+ }
622+ mem:: forget ( guard) ;
623+ Ok ( array. assume_init ( ) )
620624 }
621625}
622626
623- arbitrary_array ! { 32 , ( T , a) ( T , b) ( T , c) ( T , d) ( T , e) ( T , f) ( T , g) ( T , h)
624- ( T , i) ( T , j) ( T , k) ( T , l) ( T , m) ( T , n) ( T , o) ( T , p)
625- ( T , q) ( T , r) ( T , s) ( T , u) ( T , v) ( T , w) ( T , x) ( T , y)
626- ( T , z) ( T , aa) ( T , ab) ( T , ac) ( T , ad) ( T , ae) ( T , af)
627- ( T , ag) }
628-
629- impl < ' a > Arbitrary < ' a > for & ' a [ u8 ] {
627+ impl < ' a , T , const N : usize > Arbitrary < ' a > for [ T ; N ]
628+ where
629+ T : Arbitrary < ' a >
630+ {
631+ #[ inline]
630632 fn arbitrary ( u : & mut Unstructured < ' a > ) -> Result < Self > {
631- let len = u. arbitrary_len :: < u8 > ( ) ?;
632- u. bytes ( len)
633+ try_create_array ( |_| <T as Arbitrary < ' a > >:: arbitrary ( u) )
633634 }
634635
635- fn arbitrary_take_rest ( u : Unstructured < ' a > ) -> Result < Self > {
636- Ok ( u. take_rest ( ) )
636+ #[ inline]
637+ fn arbitrary_take_rest ( mut u : Unstructured < ' a > ) -> Result < Self > {
638+ let mut array = Self :: arbitrary ( & mut u) ?;
639+ if let Some ( last) = array. last_mut ( ) {
640+ * last = Arbitrary :: arbitrary_take_rest ( u) ?;
641+ }
642+ Ok ( array)
637643 }
638644
639645 #[ inline]
640- fn size_hint ( depth : usize ) -> ( usize , Option < usize > ) {
641- <usize as Arbitrary >:: size_hint ( depth)
646+ fn size_hint ( d : usize ) -> ( usize , Option < usize > ) {
647+ crate :: size_hint:: and_all ( & create_array :: < _ , ( usize , Option < usize > ) , N > ( |_| {
648+ <T as Arbitrary >:: size_hint ( d)
649+ } ) )
642650 }
643651}
644652
0 commit comments