1
+ use core:: fmt;
1
2
use core:: iter:: FusedIterator ;
3
+ use core:: marker:: PhantomData ;
4
+ use core:: mem:: { self , MaybeUninit } ;
2
5
use core:: ptr:: { self , NonNull } ;
3
- use core:: { fmt, mem} ;
4
6
5
7
use crate :: alloc:: { Allocator , Global } ;
6
8
7
- use super :: { count, Iter , VecDeque } ;
9
+ use super :: { count, wrap_index , VecDeque } ;
8
10
9
11
/// A draining iterator over the elements of a `VecDeque`.
10
12
///
@@ -20,18 +22,24 @@ pub struct Drain<
20
22
> {
21
23
after_tail : usize ,
22
24
after_head : usize ,
23
- iter : Iter < ' a , T > ,
25
+ ring : NonNull < [ T ] > ,
26
+ tail : usize ,
27
+ head : usize ,
24
28
deque : NonNull < VecDeque < T , A > > ,
29
+ _phantom : PhantomData < & ' a T > ,
25
30
}
26
31
27
32
impl < ' a , T , A : Allocator > Drain < ' a , T , A > {
28
33
pub ( super ) unsafe fn new (
29
34
after_tail : usize ,
30
35
after_head : usize ,
31
- iter : Iter < ' a , T > ,
36
+ ring : & ' a [ MaybeUninit < T > ] ,
37
+ tail : usize ,
38
+ head : usize ,
32
39
deque : NonNull < VecDeque < T , A > > ,
33
40
) -> Self {
34
- Drain { after_tail, after_head, iter, deque }
41
+ let ring = unsafe { NonNull :: new_unchecked ( ring as * const [ MaybeUninit < T > ] as * mut _ ) } ;
42
+ Drain { after_tail, after_head, ring, tail, head, deque, _phantom : PhantomData }
35
43
}
36
44
}
37
45
@@ -41,7 +49,9 @@ impl<T: fmt::Debug, A: Allocator> fmt::Debug for Drain<'_, T, A> {
41
49
f. debug_tuple ( "Drain" )
42
50
. field ( & self . after_tail )
43
51
. field ( & self . after_head )
44
- . field ( & self . iter )
52
+ . field ( & self . ring )
53
+ . field ( & self . tail )
54
+ . field ( & self . head )
45
55
. finish ( )
46
56
}
47
57
}
@@ -118,20 +128,36 @@ impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
118
128
119
129
#[ inline]
120
130
fn next ( & mut self ) -> Option < T > {
121
- self . iter . next ( ) . map ( |elt| unsafe { ptr:: read ( elt) } )
131
+ if self . tail == self . head {
132
+ return None ;
133
+ }
134
+ let tail = self . tail ;
135
+ self . tail = wrap_index ( self . tail . wrapping_add ( 1 ) , self . ring . len ( ) ) ;
136
+ // Safety:
137
+ // - `self.tail` in a ring buffer is always a valid index.
138
+ // - `self.head` and `self.tail` equality is checked above.
139
+ unsafe { Some ( ptr:: read ( self . ring . as_ptr ( ) . get_unchecked_mut ( tail) ) ) }
122
140
}
123
141
124
142
#[ inline]
125
143
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
126
- self . iter . size_hint ( )
144
+ let len = count ( self . tail , self . head , self . ring . len ( ) ) ;
145
+ ( len, Some ( len) )
127
146
}
128
147
}
129
148
130
149
#[ stable( feature = "drain" , since = "1.6.0" ) ]
131
150
impl < T , A : Allocator > DoubleEndedIterator for Drain < ' _ , T , A > {
132
151
#[ inline]
133
152
fn next_back ( & mut self ) -> Option < T > {
134
- self . iter . next_back ( ) . map ( |elt| unsafe { ptr:: read ( elt) } )
153
+ if self . tail == self . head {
154
+ return None ;
155
+ }
156
+ self . head = wrap_index ( self . head . wrapping_sub ( 1 ) , self . ring . len ( ) ) ;
157
+ // Safety:
158
+ // - `self.head` in a ring buffer is always a valid index.
159
+ // - `self.head` and `self.tail` equality is checked above.
160
+ unsafe { Some ( ptr:: read ( self . ring . as_ptr ( ) . get_unchecked_mut ( self . head ) ) ) }
135
161
}
136
162
}
137
163
0 commit comments