@@ -3,6 +3,8 @@ use core::cell::UnsafeCell;
33#[ cfg( not( no_global_oom_handling) ) ]
44use core:: clone:: CloneToUninit ;
55#[ cfg( not( no_global_oom_handling) ) ]
6+ use core:: iter:: TrustedLen ;
7+ #[ cfg( not( no_global_oom_handling) ) ]
68use core:: marker:: PhantomData ;
79#[ cfg( not( no_global_oom_handling) ) ]
810use core:: mem;
@@ -543,3 +545,106 @@ impl<T, A> RawRc<MaybeUninit<T>, A> {
543545 unsafe { self . cast ( ) }
544546 }
545547}
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+ /// Used for dropping initialized elements in the slice if the iteration process panics.
557+ struct Guard < T > {
558+ head : NonNull < T > ,
559+ tail : NonNull < T > ,
560+ }
561+
562+ impl < T > Drop for Guard < T > {
563+ fn drop ( & mut self ) {
564+ unsafe {
565+ let length = self . tail . offset_from_unsigned ( self . head ) ;
566+
567+ NonNull :: < [ T ] > :: slice_from_raw_parts ( self . head , length) . drop_in_place ( ) ;
568+ }
569+ }
570+ }
571+
572+ let ( length, Some ( high) ) = iter. size_hint ( ) else {
573+ // TrustedLen contract guarantees that `upper_bound == None` implies an iterator
574+ // length exceeding `usize::MAX`.
575+ // The default implementation would collect into a vec which would panic.
576+ // Thus we panic here immediately without invoking `Vec` code.
577+ panic ! ( "capacity overflow" ) ;
578+ } ;
579+
580+ debug_assert_eq ! (
581+ length,
582+ high,
583+ "TrustedLen iterator's size hint is not exact: {:?}" ,
584+ ( length, high)
585+ ) ;
586+
587+ let rc_layout = RcLayout :: new_array :: < T > ( length) ;
588+
589+ let ( ptr, alloc) = super :: allocate_with :: < A , _ , 1 > ( rc_layout, |ptr| {
590+ let ptr = ptr. as_ptr ( ) . cast :: < T > ( ) ;
591+ let mut guard = Guard :: < T > { head : ptr, tail : ptr } ;
592+
593+ // SAFETY: `iter` is `TrustedLen`, we can assume we will write correct number of
594+ // elements to the buffer.
595+ iter. for_each ( |value| unsafe {
596+ guard. tail . write ( value) ;
597+ guard. tail = guard. tail . add ( 1 ) ;
598+ } ) ;
599+
600+ mem:: forget ( guard) ;
601+ } ) ;
602+
603+ // SAFETY: We have written `length` of `T` values to the buffer, the buffer is now
604+ // initialized.
605+ unsafe {
606+ Self :: from_raw_parts (
607+ NonNull :: slice_from_raw_parts ( ptr. as_ptr ( ) . cast :: < T > ( ) , length) ,
608+ alloc,
609+ )
610+ }
611+ }
612+ }
613+
614+ impl < T , A > RawRc < [ MaybeUninit < T > ] , A > {
615+ #[ cfg( not( no_global_oom_handling) ) ]
616+ pub ( crate ) fn new_uninit_slice ( length : usize ) -> Self
617+ where
618+ A : Allocator + Default ,
619+ {
620+ unsafe { Self :: from_weak ( RawWeak :: new_uninit_slice :: < 1 > ( length) ) }
621+ }
622+
623+ #[ cfg( not( no_global_oom_handling) ) ]
624+ pub ( crate ) fn new_uninit_slice_in ( length : usize , alloc : A ) -> Self
625+ where
626+ A : Allocator ,
627+ {
628+ unsafe { Self :: from_weak ( RawWeak :: new_uninit_slice_in :: < 1 > ( length, alloc) ) }
629+ }
630+
631+ #[ cfg( not( no_global_oom_handling) ) ]
632+ pub ( crate ) fn new_zeroed_slice ( length : usize ) -> Self
633+ where
634+ A : Allocator + Default ,
635+ {
636+ unsafe { Self :: from_weak ( RawWeak :: new_zeroed_slice :: < 1 > ( length) ) }
637+ }
638+
639+ #[ cfg( not( no_global_oom_handling) ) ]
640+ pub ( crate ) fn new_zeroed_slice_in ( length : usize , alloc : A ) -> Self
641+ where
642+ A : Allocator ,
643+ {
644+ unsafe { Self :: from_weak ( RawWeak :: new_zeroed_slice_in :: < 1 > ( length, alloc) ) }
645+ }
646+
647+ pub ( crate ) unsafe fn assume_init ( self ) -> RawRc < [ T ] , A > {
648+ unsafe { self . cast_with ( |ptr| NonNull :: new_unchecked ( ptr. as_ptr ( ) as _ ) ) }
649+ }
650+ }
0 commit comments