@@ -2,6 +2,8 @@ use core::alloc::{AllocError, Allocator};
2
2
use core:: cell:: UnsafeCell ;
3
3
#[ cfg( not( no_global_oom_handling) ) ]
4
4
use core:: clone:: CloneToUninit ;
5
+ #[ cfg( not( no_global_oom_handling) ) ]
6
+ use core:: iter:: TrustedLen ;
5
7
use core:: marker:: PhantomData ;
6
8
#[ cfg( not( no_global_oom_handling) ) ]
7
9
use core:: mem;
@@ -545,3 +547,113 @@ impl<T, A> RawRc<MaybeUninit<T>, A> {
545
547
unsafe { self . cast ( ) }
546
548
}
547
549
}
550
+
551
+ impl < T , A > RawRc < [ T ] , A > {
552
+ #[ cfg( not( no_global_oom_handling) ) ]
553
+ fn from_trusted_len_iter < I > ( iter : I ) -> Self
554
+ where
555
+ A : Allocator + Default ,
556
+ I : TrustedLen < Item = T > ,
557
+ {
558
+ /// Returns a drop guard that calls the destructors of a slice of elements on drop.
559
+ ///
560
+ /// # Safety
561
+ ///
562
+ /// - `head..tail` must describe a valid consecutive slice of `T` values when the destructor
563
+ /// of the returned guard is called.
564
+ /// - After calling the returned function, the corresponding values should not be accessed
565
+ /// anymore.
566
+ unsafe fn drop_range_on_drop < T > (
567
+ head : NonNull < T > ,
568
+ tail : NonNull < T > ,
569
+ ) -> impl DerefMut < Target = ( NonNull < T > , NonNull < T > ) > {
570
+ // SAFETY:
571
+ DropGuard :: new ( ( head, tail) , |( head, tail) | unsafe {
572
+ let length = tail. offset_from_unsigned ( head) ;
573
+
574
+ NonNull :: < [ T ] > :: slice_from_raw_parts ( head, length) . drop_in_place ( ) ;
575
+ } )
576
+ }
577
+
578
+ let ( length, Some ( high) ) = iter. size_hint ( ) else {
579
+ // TrustedLen contract guarantees that `upper_bound == None` implies an iterator
580
+ // length exceeding `usize::MAX`.
581
+ // The default implementation would collect into a vec which would panic.
582
+ // Thus we panic here immediately without invoking `Vec` code.
583
+ panic ! ( "capacity overflow" ) ;
584
+ } ;
585
+
586
+ debug_assert_eq ! (
587
+ length,
588
+ high,
589
+ "TrustedLen iterator's size hint is not exact: {:?}" ,
590
+ ( length, high)
591
+ ) ;
592
+
593
+ let rc_layout = RcLayout :: new_array :: < T > ( length) ;
594
+
595
+ let ( ptr, alloc) = rc_alloc:: allocate_with :: < A , _ , 1 > ( rc_layout, |ptr| {
596
+ let ptr = ptr. as_ptr ( ) . cast :: < T > ( ) ;
597
+ let mut guard = unsafe { drop_range_on_drop :: < T > ( ptr, ptr) } ;
598
+
599
+ // SAFETY: `iter` is `TrustedLen`, we can assume we will write correct number of
600
+ // elements to the buffer.
601
+ iter. for_each ( |value| unsafe {
602
+ guard. 1 . write ( value) ;
603
+ guard. 1 = guard. 1 . add ( 1 ) ;
604
+ } ) ;
605
+
606
+ mem:: forget ( guard) ;
607
+ } ) ;
608
+
609
+ // SAFETY: We have written `length` of `T` values to the buffer, the buffer is now
610
+ // initialized.
611
+ unsafe {
612
+ Self :: from_raw_parts (
613
+ NonNull :: slice_from_raw_parts ( ptr. as_ptr ( ) . cast :: < T > ( ) , length) ,
614
+ alloc,
615
+ )
616
+ }
617
+ }
618
+ }
619
+
620
+ impl < T , A > RawRc < [ MaybeUninit < T > ] , A > {
621
+ #[ cfg( not( no_global_oom_handling) ) ]
622
+ pub ( crate ) fn new_uninit_slice ( length : usize ) -> Self
623
+ where
624
+ A : Allocator + Default ,
625
+ {
626
+ unsafe { Self :: from_weak ( RawWeak :: new_uninit_slice :: < 1 > ( length) ) }
627
+ }
628
+
629
+ #[ cfg( not( no_global_oom_handling) ) ]
630
+ pub ( crate ) fn new_uninit_slice_in ( length : usize , alloc : A ) -> Self
631
+ where
632
+ A : Allocator ,
633
+ {
634
+ unsafe { Self :: from_weak ( RawWeak :: new_uninit_slice_in :: < 1 > ( length, alloc) ) }
635
+ }
636
+
637
+ #[ cfg( not( no_global_oom_handling) ) ]
638
+ pub ( crate ) fn new_zeroed_slice ( length : usize ) -> Self
639
+ where
640
+ A : Allocator + Default ,
641
+ {
642
+ unsafe { Self :: from_weak ( RawWeak :: new_zeroed_slice :: < 1 > ( length) ) }
643
+ }
644
+
645
+ #[ cfg( not( no_global_oom_handling) ) ]
646
+ pub ( crate ) fn new_zeroed_slice_in ( length : usize , alloc : A ) -> Self
647
+ where
648
+ A : Allocator ,
649
+ {
650
+ unsafe { Self :: from_weak ( RawWeak :: new_zeroed_slice_in :: < 1 > ( length, alloc) ) }
651
+ }
652
+
653
+ /// # Safety
654
+ ///
655
+ /// All `MaybeUninit<T>`s values contained by `self` must be initialized.
656
+ pub ( crate ) unsafe fn assume_init ( self ) -> RawRc < [ T ] , A > {
657
+ unsafe { self . cast_with ( |ptr| NonNull :: new_unchecked ( ptr. as_ptr ( ) as _ ) ) }
658
+ }
659
+ }
0 commit comments