11use crate :: fmt;
22use crate :: iter:: { FusedIterator , TrustedLen , UncheckedIterator } ;
3- use crate :: mem:: { self , MaybeUninit } ;
43use crate :: num:: NonZero ;
54
65/// Creates a new iterator that repeats a single element a given number of times.
@@ -57,78 +56,48 @@ use crate::num::NonZero;
5756#[ inline]
5857#[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
5958pub fn repeat_n < T : Clone > ( element : T , count : usize ) -> RepeatN < T > {
60- let element = if count == 0 {
61- // `element` gets dropped eagerly.
62- MaybeUninit :: uninit ( )
63- } else {
64- MaybeUninit :: new ( element)
65- } ;
66-
67- RepeatN { element, count }
59+ RepeatN { inner : RepeatNInner :: new ( element, count) }
60+ }
61+
62+ #[ derive( Clone ) ]
63+ struct RepeatNInner < T > {
64+ element : T ,
65+ count : NonZero < usize > ,
66+ }
67+
68+ impl < T > RepeatNInner < T > {
69+ fn new ( element : T , count : usize ) -> Option < Self > {
70+ let count = NonZero :: < usize > :: new ( count) ?;
71+ Some ( Self { element, count } )
72+ }
6873}
6974
7075/// An iterator that repeats an element an exact number of times.
7176///
7277/// This `struct` is created by the [`repeat_n()`] function.
7378/// See its documentation for more.
7479#[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
80+ #[ derive( Clone ) ]
7581pub struct RepeatN < A > {
76- count : usize ,
77- // Invariant: uninit iff count == 0.
78- element : MaybeUninit < A > ,
82+ inner : Option < RepeatNInner < A > > ,
7983}
8084
8185impl < A > RepeatN < A > {
82- /// Returns the element if it hasn't been dropped already.
83- fn element_ref ( & self ) -> Option < & A > {
84- if self . count > 0 {
85- // SAFETY: The count is non-zero, so it must be initialized.
86- Some ( unsafe { self . element . assume_init_ref ( ) } )
87- } else {
88- None
89- }
90- }
9186 /// If we haven't already dropped the element, return it in an option.
92- ///
93- /// Clears the count so it won't be dropped again later.
9487 #[ inline]
9588 fn take_element ( & mut self ) -> Option < A > {
96- if self . count > 0 {
97- self . count = 0 ;
98- let element = mem:: replace ( & mut self . element , MaybeUninit :: uninit ( ) ) ;
99- // SAFETY: We just set count to zero so it won't be dropped again,
100- // and it used to be non-zero so it hasn't already been dropped.
101- unsafe { Some ( element. assume_init ( ) ) }
102- } else {
103- None
104- }
105- }
106- }
107-
108- #[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
109- impl < A : Clone > Clone for RepeatN < A > {
110- fn clone ( & self ) -> RepeatN < A > {
111- RepeatN {
112- count : self . count ,
113- element : self . element_ref ( ) . cloned ( ) . map_or_else ( MaybeUninit :: uninit, MaybeUninit :: new) ,
114- }
89+ self . inner . take ( ) . map ( |inner| inner. element )
11590 }
11691}
11792
11893#[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
11994impl < A : fmt:: Debug > fmt:: Debug for RepeatN < A > {
12095 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
121- f. debug_struct ( "RepeatN" )
122- . field ( "count" , & self . count )
123- . field ( "element" , & self . element_ref ( ) )
124- . finish ( )
125- }
126- }
127-
128- #[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
129- impl < A > Drop for RepeatN < A > {
130- fn drop ( & mut self ) {
131- self . take_element ( ) ;
96+ let ( count, element) = match self . inner . as_ref ( ) {
97+ Some ( inner) => ( inner. count . get ( ) , Some ( & inner. element ) ) ,
98+ None => ( 0 , None ) ,
99+ } ;
100+ f. debug_struct ( "RepeatN" ) . field ( "count" , & count) . field ( "element" , & element) . finish ( )
132101 }
133102}
134103
@@ -138,12 +107,17 @@ impl<A: Clone> Iterator for RepeatN<A> {
138107
139108 #[ inline]
140109 fn next ( & mut self ) -> Option < A > {
141- if self . count > 0 {
142- // SAFETY: Just checked it's not empty
143- unsafe { Some ( self . next_unchecked ( ) ) }
144- } else {
145- None
110+ let inner = self . inner . as_mut ( ) ?;
111+ let count = inner. count . get ( ) ;
112+
113+ if let Some ( decremented) = NonZero :: < usize > :: new ( count - 1 ) {
114+ // Order of these is important for optimization
115+ let tmp = inner. element . clone ( ) ;
116+ inner. count = decremented;
117+ return Some ( tmp) ;
146118 }
119+
120+ return self . take_element ( ) ;
147121 }
148122
149123 #[ inline]
@@ -154,19 +128,19 @@ impl<A: Clone> Iterator for RepeatN<A> {
154128
155129 #[ inline]
156130 fn advance_by ( & mut self , skip : usize ) -> Result < ( ) , NonZero < usize > > {
157- let len = self . count ;
131+ let Some ( inner) = self . inner . as_mut ( ) else {
132+ return NonZero :: < usize > :: new ( skip) . map ( Err ) . unwrap_or ( Ok ( ( ) ) ) ;
133+ } ;
158134
159- if skip >= len {
160- self . take_element ( ) ;
161- }
135+ let len = inner. count . get ( ) ;
162136
163- if skip > len {
164- // SAFETY: we just checked that the difference is positive
165- Err ( unsafe { NonZero :: new_unchecked ( skip - len) } )
166- } else {
167- self . count = len - skip;
168- Ok ( ( ) )
137+ if let Some ( new_len) = len. checked_sub ( skip) . and_then ( NonZero :: < usize > :: new) {
138+ inner. count = new_len;
139+ return Ok ( ( ) ) ;
169140 }
141+
142+ self . inner = None ;
143+ return NonZero :: < usize > :: new ( skip - len) . map ( Err ) . unwrap_or ( Ok ( ( ) ) ) ;
170144 }
171145
172146 #[ inline]
@@ -183,7 +157,7 @@ impl<A: Clone> Iterator for RepeatN<A> {
183157#[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
184158impl < A : Clone > ExactSizeIterator for RepeatN < A > {
185159 fn len ( & self ) -> usize {
186- self . count
160+ self . inner . as_ref ( ) . map ( |inner| inner . count . get ( ) ) . unwrap_or ( 0 )
187161 }
188162}
189163
@@ -211,20 +185,4 @@ impl<A: Clone> FusedIterator for RepeatN<A> {}
211185#[ unstable( feature = "trusted_len" , issue = "37572" ) ]
212186unsafe impl < A : Clone > TrustedLen for RepeatN < A > { }
213187#[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
214- impl < A : Clone > UncheckedIterator for RepeatN < A > {
215- #[ inline]
216- unsafe fn next_unchecked ( & mut self ) -> Self :: Item {
217- // SAFETY: The caller promised the iterator isn't empty
218- self . count = unsafe { self . count . unchecked_sub ( 1 ) } ;
219- if self . count == 0 {
220- // SAFETY: the check above ensured that the count used to be non-zero,
221- // so element hasn't been dropped yet, and we just lowered the count to
222- // zero so it won't be dropped later, and thus it's okay to take it here.
223- unsafe { mem:: replace ( & mut self . element , MaybeUninit :: uninit ( ) ) . assume_init ( ) }
224- } else {
225- // SAFETY: the count is non-zero, so it must have not been dropped yet.
226- let element = unsafe { self . element . assume_init_ref ( ) } ;
227- A :: clone ( element)
228- }
229- }
230- }
188+ impl < A : Clone > UncheckedIterator for RepeatN < A > { }
0 commit comments