@@ -4,6 +4,8 @@ use core::cell::UnsafeCell;
44use core:: clone:: CloneToUninit ;
55#[ cfg( not( no_global_oom_handling) ) ]
66use core:: convert;
7+ #[ cfg( not( no_global_oom_handling) ) ]
8+ use core:: iter:: TrustedLen ;
79use core:: marker:: PhantomData ;
810#[ cfg( not( no_global_oom_handling) ) ]
911use core:: mem:: { self , SizedTypeProperties } ;
@@ -595,6 +597,116 @@ impl<T, A> RawRc<MaybeUninit<T>, A> {
595597 }
596598}
597599
600+ impl < T , A > RawRc < [ T ] , A > {
601+ #[ cfg( not( no_global_oom_handling) ) ]
602+ fn from_trusted_len_iter < I > ( iter : I ) -> Self
603+ where
604+ A : Allocator + Default ,
605+ I : TrustedLen < Item = T > ,
606+ {
607+ /// Returns a drop guard that calls the destructors of a slice of elements on drop.
608+ ///
609+ /// # Safety
610+ ///
611+ /// - `head..tail` must describe a valid consecutive slice of `T` values when the destructor
612+ /// of the returned guard is called.
613+ /// - After calling the returned function, the corresponding values should not be accessed
614+ /// anymore.
615+ unsafe fn drop_range_on_drop < T > (
616+ head : NonNull < T > ,
617+ tail : NonNull < T > ,
618+ ) -> impl DerefMut < Target = ( NonNull < T > , NonNull < T > ) > {
619+ // SAFETY:
620+ DropGuard :: new ( ( head, tail) , |( head, tail) | unsafe {
621+ let length = tail. offset_from_unsigned ( head) ;
622+
623+ NonNull :: < [ T ] > :: slice_from_raw_parts ( head, length) . drop_in_place ( ) ;
624+ } )
625+ }
626+
627+ let ( length, Some ( high) ) = iter. size_hint ( ) else {
628+ // TrustedLen contract guarantees that `upper_bound == None` implies an iterator
629+ // length exceeding `usize::MAX`.
630+ // The default implementation would collect into a vec which would panic.
631+ // Thus we panic here immediately without invoking `Vec` code.
632+ panic ! ( "capacity overflow" ) ;
633+ } ;
634+
635+ debug_assert_eq ! (
636+ length,
637+ high,
638+ "TrustedLen iterator's size hint is not exact: {:?}" ,
639+ ( length, high)
640+ ) ;
641+
642+ let rc_layout = RcLayout :: new_array :: < T > ( length) ;
643+
644+ let ( ptr, alloc) = rc_alloc:: allocate_with :: < A , _ , 1 > ( rc_layout, |ptr| {
645+ let ptr = ptr. as_ptr ( ) . cast :: < T > ( ) ;
646+ let mut guard = unsafe { drop_range_on_drop :: < T > ( ptr, ptr) } ;
647+
648+ // SAFETY: `iter` is `TrustedLen`, we can assume we will write correct number of
649+ // elements to the buffer.
650+ iter. for_each ( |value| unsafe {
651+ guard. 1 . write ( value) ;
652+ guard. 1 = guard. 1 . add ( 1 ) ;
653+ } ) ;
654+
655+ mem:: forget ( guard) ;
656+ } ) ;
657+
658+ // SAFETY: We have written `length` of `T` values to the buffer, the buffer is now
659+ // initialized.
660+ unsafe {
661+ Self :: from_raw_parts (
662+ NonNull :: slice_from_raw_parts ( ptr. as_ptr ( ) . cast :: < T > ( ) , length) ,
663+ alloc,
664+ )
665+ }
666+ }
667+ }
668+
669+ impl < T , A > RawRc < [ MaybeUninit < T > ] , A > {
670+ #[ cfg( not( no_global_oom_handling) ) ]
671+ pub ( crate ) fn new_uninit_slice ( length : usize ) -> Self
672+ where
673+ A : Allocator + Default ,
674+ {
675+ unsafe { Self :: from_weak ( RawWeak :: new_uninit_slice :: < 1 > ( length) ) }
676+ }
677+
678+ #[ cfg( not( no_global_oom_handling) ) ]
679+ pub ( crate ) fn new_uninit_slice_in ( length : usize , alloc : A ) -> Self
680+ where
681+ A : Allocator ,
682+ {
683+ unsafe { Self :: from_weak ( RawWeak :: new_uninit_slice_in :: < 1 > ( length, alloc) ) }
684+ }
685+
686+ #[ cfg( not( no_global_oom_handling) ) ]
687+ pub ( crate ) fn new_zeroed_slice ( length : usize ) -> Self
688+ where
689+ A : Allocator + Default ,
690+ {
691+ unsafe { Self :: from_weak ( RawWeak :: new_zeroed_slice :: < 1 > ( length) ) }
692+ }
693+
694+ #[ cfg( not( no_global_oom_handling) ) ]
695+ pub ( crate ) fn new_zeroed_slice_in ( length : usize , alloc : A ) -> Self
696+ where
697+ A : Allocator ,
698+ {
699+ unsafe { Self :: from_weak ( RawWeak :: new_zeroed_slice_in :: < 1 > ( length, alloc) ) }
700+ }
701+
702+ /// # Safety
703+ ///
704+ /// All `MaybeUninit<T>`s values contained by `self` must be initialized.
705+ pub ( crate ) unsafe fn assume_init ( self ) -> RawRc < [ T ] , A > {
706+ unsafe { self . cast_with ( |ptr| NonNull :: new_unchecked ( ptr. as_ptr ( ) as _ ) ) }
707+ }
708+ }
709+
598710/// Decrements strong reference count in a reference-counted allocation with a value object that is
599711/// pointed to by `value_ptr`.
600712#[ inline]
0 commit comments