1+ use core:: fmt;
12use core:: iter:: FusedIterator ;
3+ use core:: marker:: PhantomData ;
4+ use core:: mem:: { self , MaybeUninit } ;
25use core:: ptr:: { self , NonNull } ;
3- use core:: { fmt, mem} ;
46
57use crate :: alloc:: { Allocator , Global } ;
68
7- use super :: { count, Iter , VecDeque } ;
9+ use super :: { count, wrap_index , VecDeque } ;
810
911/// A draining iterator over the elements of a `VecDeque`.
1012///
@@ -20,18 +22,24 @@ pub struct Drain<
2022> {
2123 after_tail : usize ,
2224 after_head : usize ,
23- iter : Iter < ' a , T > ,
25+ ring : NonNull < [ T ] > ,
26+ tail : usize ,
27+ head : usize ,
2428 deque : NonNull < VecDeque < T , A > > ,
29+ _phantom : PhantomData < & ' a T > ,
2530}
2631
2732impl < ' a , T , A : Allocator > Drain < ' a , T , A > {
2833 pub ( super ) unsafe fn new (
2934 after_tail : usize ,
3035 after_head : usize ,
31- iter : Iter < ' a , T > ,
36+ ring : & ' a [ MaybeUninit < T > ] ,
37+ tail : usize ,
38+ head : usize ,
3239 deque : NonNull < VecDeque < T , A > > ,
3340 ) -> 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 }
3543 }
3644}
3745
@@ -41,7 +49,9 @@ impl<T: fmt::Debug, A: Allocator> fmt::Debug for Drain<'_, T, A> {
4149 f. debug_tuple ( "Drain" )
4250 . field ( & self . after_tail )
4351 . field ( & self . after_head )
44- . field ( & self . iter )
52+ . field ( & self . ring )
53+ . field ( & self . tail )
54+ . field ( & self . head )
4555 . finish ( )
4656 }
4757}
@@ -118,20 +128,36 @@ impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
118128
119129 #[ inline]
120130 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) ) ) }
122140 }
123141
124142 #[ inline]
125143 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) )
127146 }
128147}
129148
130149#[ stable( feature = "drain" , since = "1.6.0" ) ]
131150impl < T , A : Allocator > DoubleEndedIterator for Drain < ' _ , T , A > {
132151 #[ inline]
133152 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 ) ) ) }
135161 }
136162}
137163
0 commit comments