@@ -571,61 +571,91 @@ macro_rules! arbitrary_tuple {
571
571
}
572
572
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 ) ;
573
573
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) ?;
574
+ // Helper to safely create arrays since the standard library doesn't
575
+ // provide one yet. Shouldn't be necessary in the future.
576
+ struct ArrayGuard < T , const N : usize > {
577
+ dst : * mut T ,
578
+ initialized : usize ,
579
+ }
590
580
591
- Ok ( [
592
- $( $as, ) * last
593
- ] )
594
- }
581
+ impl < T , const N : usize > Drop for ArrayGuard < T , N > {
582
+ fn drop ( & mut self ) {
583
+ debug_assert ! ( self . initialized <= N ) ;
584
+ let initialized_part = core:: ptr:: slice_from_raw_parts_mut ( self . dst , self . initialized ) ;
585
+ unsafe {
586
+ core:: ptr:: drop_in_place ( initialized_part) ;
587
+ }
588
+ }
589
+ }
595
590
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
- }
591
+ fn create_array < F , T , const N : usize > ( mut cb : F ) -> [ T ; N ]
592
+ where
593
+ F : FnMut ( usize ) -> T ,
594
+ {
595
+ let mut array: mem:: MaybeUninit < [ T ; N ] > = mem:: MaybeUninit :: uninit ( ) ;
596
+ let array_ptr = array. as_mut_ptr ( ) ;
597
+ let dst = array_ptr as _ ;
598
+ let mut guard: ArrayGuard < T , N > = ArrayGuard {
599
+ dst,
600
+ initialized : 0 ,
601
+ } ;
602
+ unsafe {
603
+ for ( idx, value_ptr) in ( & mut * array. as_mut_ptr ( ) ) . iter_mut ( ) . enumerate ( ) {
604
+ core:: ptr:: write ( value_ptr, cb ( idx) ) ;
605
+ guard. initialized += 1 ;
603
606
}
607
+ mem:: forget ( guard) ;
608
+ array. assume_init ( )
609
+ }
610
+ }
611
+
612
+ fn try_create_array < F , T , const N : usize > ( mut cb : F ) -> Result < [ T ; N ] >
613
+ where
614
+ F : FnMut ( usize ) -> Result < T > ,
615
+ {
616
+ let mut array: mem:: MaybeUninit < [ T ; N ] > = mem:: MaybeUninit :: uninit ( ) ;
617
+ let array_ptr = array. as_mut_ptr ( ) ;
618
+ let dst = array_ptr as _ ;
619
+ let mut guard: ArrayGuard < T , N > = ArrayGuard {
620
+ dst,
621
+ initialized : 0 ,
604
622
} ;
605
- ( $n: expr, ) => { } ;
623
+ unsafe {
624
+ for ( idx, value_ptr) in ( & mut * array. as_mut_ptr ( ) ) . iter_mut ( ) . enumerate ( ) {
625
+ core:: ptr:: write ( value_ptr, cb ( idx) ?) ;
626
+ guard. initialized += 1 ;
627
+ }
628
+ mem:: forget ( guard) ;
629
+ Ok ( array. assume_init ( ) )
630
+ }
606
631
}
607
632
608
- impl < ' a , T : Arbitrary < ' a > > Arbitrary < ' a > for [ T ; 0 ] {
609
- fn arbitrary ( _: & mut Unstructured < ' a > ) -> Result < [ T ; 0 ] > {
610
- Ok ( [ ] )
633
+ impl < ' a , T , const N : usize > Arbitrary < ' a > for [ T ; N ]
634
+ where
635
+ T : Arbitrary < ' a > ,
636
+ {
637
+ #[ inline]
638
+ fn arbitrary ( u : & mut Unstructured < ' a > ) -> Result < Self > {
639
+ try_create_array ( |_| <T as Arbitrary < ' a > >:: arbitrary ( u) )
611
640
}
612
641
613
- fn arbitrary_take_rest ( _: Unstructured < ' a > ) -> Result < [ T ; 0 ] > {
614
- Ok ( [ ] )
642
+ #[ inline]
643
+ fn arbitrary_take_rest ( mut u : Unstructured < ' a > ) -> Result < Self > {
644
+ let mut array = Self :: arbitrary ( & mut u) ?;
645
+ if let Some ( last) = array. last_mut ( ) {
646
+ * last = Arbitrary :: arbitrary_take_rest ( u) ?;
647
+ }
648
+ Ok ( array)
615
649
}
616
650
617
651
#[ inline]
618
- fn size_hint ( _: usize ) -> ( usize , Option < usize > ) {
619
- crate :: size_hint:: and_all ( & [ ] )
652
+ fn size_hint ( d : usize ) -> ( usize , Option < usize > ) {
653
+ crate :: size_hint:: and_all ( & create_array :: < _ , ( usize , Option < usize > ) , N > ( |_| {
654
+ <T as Arbitrary >:: size_hint ( d)
655
+ } ) )
620
656
}
621
657
}
622
658
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
659
impl < ' a > Arbitrary < ' a > for & ' a [ u8 ] {
630
660
fn arbitrary ( u : & mut Unstructured < ' a > ) -> Result < Self > {
631
661
let len = u. arbitrary_len :: < u8 > ( ) ?;
0 commit comments