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