@@ -2,6 +2,8 @@ use core::alloc::{AllocError, Allocator};
22use core:: cell:: UnsafeCell ;
33#[ cfg( not( no_global_oom_handling) ) ]
44use core:: clone:: CloneToUninit ;
5+ #[ cfg( not( no_global_oom_handling) ) ]
6+ use core:: iter:: TrustedLen ;
57use core:: marker:: PhantomData ;
68#[ cfg( not( no_global_oom_handling) ) ]
79use core:: mem;
@@ -545,3 +547,113 @@ impl<T, A> RawRc<MaybeUninit<T>, A> {
545547 unsafe { self . cast ( ) }
546548 }
547549}
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