11use core:: alloc:: { AllocError , Allocator } ;
22use core:: cell:: UnsafeCell ;
33use core:: clone:: CloneToUninit ;
4+ #[ cfg( not( no_global_oom_handling) ) ]
5+ use core:: iter:: TrustedLen ;
46use core:: marker:: PhantomData ;
57#[ cfg( not( no_global_oom_handling) ) ]
68use core:: mem:: { self , SizedTypeProperties } ;
@@ -15,7 +17,7 @@ use crate::raw_rc::MakeMutStrategy;
1517use crate :: raw_rc:: raw_weak;
1618use crate :: raw_rc:: raw_weak:: RawWeak ;
1719#[ cfg( not( no_global_oom_handling) ) ]
18- use crate :: raw_rc:: rc_layout:: RcLayoutExt ;
20+ use crate :: raw_rc:: rc_layout:: { RcLayout , RcLayoutExt } ;
1921use crate :: raw_rc:: rc_value_pointer:: RcValuePointer ;
2022use crate :: raw_rc:: { RefCounter , rc_alloc} ;
2123
@@ -613,6 +615,135 @@ impl<T, A> RawRc<MaybeUninit<T>, A> {
613615 }
614616}
615617
618+ impl < T , A > RawRc < [ T ] , A > {
619+ #[ cfg( not( no_global_oom_handling) ) ]
620+ fn from_trusted_len_iter < I > ( iter : I ) -> Self
621+ where
622+ A : Allocator + Default ,
623+ I : TrustedLen < Item = T > ,
624+ {
625+ /// Returns a drop guard that calls the destructors of a slice of elements on drop.
626+ ///
627+ /// # Safety
628+ ///
629+ /// - `head..tail` must describe a valid consecutive slice of `T` values when the destructor
630+ /// of the returned guard is called.
631+ /// - After calling the returned function, the corresponding values should not be accessed
632+ /// anymore.
633+ unsafe fn drop_range_on_drop < T > (
634+ head : NonNull < T > ,
635+ tail : NonNull < T > ,
636+ ) -> impl DerefMut < Target = ( NonNull < T > , NonNull < T > ) > {
637+ // SAFETY:
638+ DropGuard :: new ( ( head, tail) , |( head, tail) | unsafe {
639+ let length = tail. offset_from_unsigned ( head) ;
640+
641+ NonNull :: < [ T ] > :: slice_from_raw_parts ( head, length) . drop_in_place ( ) ;
642+ } )
643+ }
644+
645+ let ( length, Some ( high) ) = iter. size_hint ( ) else {
646+ // TrustedLen contract guarantees that `upper_bound == None` implies an iterator
647+ // length exceeding `usize::MAX`.
648+ // The default implementation would collect into a vec which would panic.
649+ // Thus we panic here immediately without invoking `Vec` code.
650+ panic ! ( "capacity overflow" ) ;
651+ } ;
652+
653+ debug_assert_eq ! (
654+ length,
655+ high,
656+ "TrustedLen iterator's size hint is not exact: {:?}" ,
657+ ( length, high)
658+ ) ;
659+
660+ let rc_layout = RcLayout :: new_array :: < T > ( length) ;
661+
662+ let ( ptr, alloc) = rc_alloc:: allocate_with :: < A , _ , 1 > ( rc_layout, |ptr| {
663+ let ptr = ptr. as_ptr ( ) . cast :: < T > ( ) ;
664+ let mut guard = unsafe { drop_range_on_drop :: < T > ( ptr, ptr) } ;
665+
666+ // SAFETY: `iter` is `TrustedLen`, we can assume we will write correct number of
667+ // elements to the buffer.
668+ iter. for_each ( |value| unsafe {
669+ guard. 1 . write ( value) ;
670+ guard. 1 = guard. 1 . add ( 1 ) ;
671+ } ) ;
672+
673+ mem:: forget ( guard) ;
674+ } ) ;
675+
676+ // SAFETY: We have written `length` of `T` values to the buffer, the buffer is now
677+ // initialized.
678+ unsafe {
679+ Self :: from_raw_parts (
680+ NonNull :: slice_from_raw_parts ( ptr. as_ptr ( ) . cast :: < T > ( ) , length) ,
681+ alloc,
682+ )
683+ }
684+ }
685+
686+ fn try_into_array < const N : usize > ( self ) -> Result < RawRc < [ T ; N ] , A > , Self > {
687+ if self . as_ref ( ) . len ( ) == N { Ok ( unsafe { self . cast ( ) } ) } else { Err ( self ) }
688+ }
689+
690+ pub ( crate ) unsafe fn into_array < const N : usize , R > ( self ) -> Option < RawRc < [ T ; N ] , A > >
691+ where
692+ A : Allocator ,
693+ R : RefCounter ,
694+ {
695+ match self . try_into_array :: < N > ( ) {
696+ Ok ( result) => Some ( result) ,
697+ Err ( mut raw_rc) => {
698+ unsafe { raw_rc. drop :: < R > ( ) } ;
699+
700+ None
701+ }
702+ }
703+ }
704+ }
705+
706+ impl < T , A > RawRc < [ MaybeUninit < T > ] , A > {
707+ #[ cfg( not( no_global_oom_handling) ) ]
708+ pub ( crate ) fn new_uninit_slice_in ( length : usize , alloc : A ) -> Self
709+ where
710+ A : Allocator ,
711+ {
712+ unsafe { Self :: from_weak ( RawWeak :: new_uninit_slice_in :: < 1 > ( length, alloc) ) }
713+ }
714+
715+ #[ cfg( not( no_global_oom_handling) ) ]
716+ pub ( crate ) fn new_uninit_slice ( length : usize ) -> Self
717+ where
718+ A : Allocator + Default ,
719+ {
720+ unsafe { Self :: from_weak ( RawWeak :: new_uninit_slice :: < 1 > ( length) ) }
721+ }
722+
723+ #[ cfg( not( no_global_oom_handling) ) ]
724+ pub ( crate ) fn new_zeroed_slice_in ( length : usize , alloc : A ) -> Self
725+ where
726+ A : Allocator ,
727+ {
728+ unsafe { Self :: from_weak ( RawWeak :: new_zeroed_slice_in :: < 1 > ( length, alloc) ) }
729+ }
730+
731+ #[ cfg( not( no_global_oom_handling) ) ]
732+ pub ( crate ) fn new_zeroed_slice ( length : usize ) -> Self
733+ where
734+ A : Allocator + Default ,
735+ {
736+ unsafe { Self :: from_weak ( RawWeak :: new_zeroed_slice :: < 1 > ( length) ) }
737+ }
738+
739+ /// # Safety
740+ ///
741+ /// All `MaybeUninit<T>`s values contained by `self` must be initialized.
742+ pub ( crate ) unsafe fn assume_init ( self ) -> RawRc < [ T ] , A > {
743+ unsafe { self . cast_with ( |ptr| NonNull :: new_unchecked ( ptr. as_ptr ( ) as _ ) ) }
744+ }
745+ }
746+
616747/// Decrements strong reference count in a reference-counted allocation with a value object that is
617748/// pointed to by `value_ptr`.
618749#[ inline]
0 commit comments