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