1
1
use crate :: fmt;
2
2
use crate :: iter:: { FusedIterator , TrustedLen , UncheckedIterator } ;
3
- use crate :: mem:: { self , MaybeUninit } ;
4
3
use crate :: num:: NonZero ;
5
4
6
5
/// Creates a new iterator that repeats a single element a given number of times.
@@ -57,78 +56,49 @@ use crate::num::NonZero;
57
56
#[ inline]
58
57
#[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
59
58
pub 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 , Copy ) ]
63
+ #[ repr( C ) ] // keep the layout consistent for codegen tests
64
+ struct RepeatNInner < T > {
65
+ count : NonZero < usize > ,
66
+ element : T ,
67
+ }
68
+
69
+ impl < T > RepeatNInner < T > {
70
+ fn new ( element : T , count : usize ) -> Option < Self > {
71
+ let count = NonZero :: < usize > :: new ( count) ?;
72
+ Some ( Self { element, count } )
73
+ }
68
74
}
69
75
70
76
/// An iterator that repeats an element an exact number of times.
71
77
///
72
78
/// This `struct` is created by the [`repeat_n()`] function.
73
79
/// See its documentation for more.
74
80
#[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
81
+ #[ derive( Clone ) ]
75
82
pub struct RepeatN < A > {
76
- count : usize ,
77
- // Invariant: uninit iff count == 0.
78
- element : MaybeUninit < A > ,
83
+ inner : Option < RepeatNInner < A > > ,
79
84
}
80
85
81
86
impl < 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
- }
91
87
/// 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.
94
88
#[ inline]
95
89
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
- }
90
+ self . inner . take ( ) . map ( |inner| inner. element )
115
91
}
116
92
}
117
93
118
94
#[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
119
95
impl < A : fmt:: Debug > fmt:: Debug for RepeatN < A > {
120
96
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 ( ) ;
97
+ let ( count, element) = match self . inner . as_ref ( ) {
98
+ Some ( inner) => ( inner. count . get ( ) , Some ( & inner. element ) ) ,
99
+ None => ( 0 , None ) ,
100
+ } ;
101
+ f. debug_struct ( "RepeatN" ) . field ( "count" , & count) . field ( "element" , & element) . finish ( )
132
102
}
133
103
}
134
104
@@ -138,12 +108,17 @@ impl<A: Clone> Iterator for RepeatN<A> {
138
108
139
109
#[ inline]
140
110
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
111
+ let inner = self . inner . as_mut ( ) ?;
112
+ let count = inner. count . get ( ) ;
113
+
114
+ if let Some ( decremented) = NonZero :: < usize > :: new ( count - 1 ) {
115
+ // Order of these is important for optimization
116
+ let tmp = inner. element . clone ( ) ;
117
+ inner. count = decremented;
118
+ return Some ( tmp) ;
146
119
}
120
+
121
+ return self . take_element ( ) ;
147
122
}
148
123
149
124
#[ inline]
@@ -154,19 +129,19 @@ impl<A: Clone> Iterator for RepeatN<A> {
154
129
155
130
#[ inline]
156
131
fn advance_by ( & mut self , skip : usize ) -> Result < ( ) , NonZero < usize > > {
157
- let len = self . count ;
132
+ let Some ( inner) = self . inner . as_mut ( ) else {
133
+ return NonZero :: < usize > :: new ( skip) . map ( Err ) . unwrap_or ( Ok ( ( ) ) ) ;
134
+ } ;
158
135
159
- if skip >= len {
160
- self . take_element ( ) ;
161
- }
136
+ let len = inner. count . get ( ) ;
162
137
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 ( ( ) )
138
+ if let Some ( new_len) = len. checked_sub ( skip) . and_then ( NonZero :: < usize > :: new) {
139
+ inner. count = new_len;
140
+ return Ok ( ( ) ) ;
169
141
}
142
+
143
+ self . inner = None ;
144
+ return NonZero :: < usize > :: new ( skip - len) . map ( Err ) . unwrap_or ( Ok ( ( ) ) ) ;
170
145
}
171
146
172
147
#[ inline]
@@ -183,7 +158,7 @@ impl<A: Clone> Iterator for RepeatN<A> {
183
158
#[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
184
159
impl < A : Clone > ExactSizeIterator for RepeatN < A > {
185
160
fn len ( & self ) -> usize {
186
- self . count
161
+ self . inner . as_ref ( ) . map ( |inner| inner . count . get ( ) ) . unwrap_or ( 0 )
187
162
}
188
163
}
189
164
@@ -211,20 +186,4 @@ impl<A: Clone> FusedIterator for RepeatN<A> {}
211
186
#[ unstable( feature = "trusted_len" , issue = "37572" ) ]
212
187
unsafe impl < A : Clone > TrustedLen for RepeatN < A > { }
213
188
#[ 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
- }
189
+ impl < A : Clone > UncheckedIterator for RepeatN < A > { }
0 commit comments