1- use core:: fmt;
21use core:: iter:: FusedIterator ;
32use core:: marker:: PhantomData ;
4- use core:: mem:: { self , MaybeUninit } ;
5- use core:: ptr:: { self , NonNull } ;
3+ use core:: mem:: { self , SizedTypeProperties } ;
4+ use core:: ptr:: NonNull ;
5+ use core:: { fmt, ptr} ;
66
77use crate :: alloc:: { Allocator , Global } ;
88
9- use super :: { count , wrap_index , VecDeque } ;
9+ use super :: VecDeque ;
1010
1111/// A draining iterator over the elements of a `VecDeque`.
1212///
@@ -20,38 +20,72 @@ pub struct Drain<
2020 T : ' a ,
2121 #[ unstable( feature = "allocator_api" , issue = "32838" ) ] A : Allocator = Global ,
2222> {
23- after_tail : usize ,
24- after_head : usize ,
25- ring : NonNull < [ T ] > ,
26- tail : usize ,
27- head : usize ,
23+ // We can't just use a &mut VecDeque<T, A>, as that would make Drain invariant over T
24+ // and we want it to be covariant instead
2825 deque : NonNull < VecDeque < T , A > > ,
29- _phantom : PhantomData < & ' a T > ,
26+ // drain_start is stored in deque.len
27+ drain_len : usize ,
28+ // index into the logical array, not the physical one (always lies in [0..deque.len))
29+ idx : usize ,
30+ // number of elements after the drain range
31+ tail_len : usize ,
32+ remaining : usize ,
33+ // Needed to make Drain covariant over T
34+ _marker : PhantomData < & ' a T > ,
3035}
3136
3237impl < ' a , T , A : Allocator > Drain < ' a , T , A > {
3338 pub ( super ) unsafe fn new (
34- after_tail : usize ,
35- after_head : usize ,
36- ring : & ' a [ MaybeUninit < T > ] ,
37- tail : usize ,
38- head : usize ,
39- deque : NonNull < VecDeque < T , A > > ,
39+ deque : & ' a mut VecDeque < T , A > ,
40+ drain_start : usize ,
41+ drain_len : usize ,
4042 ) -> Self {
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 }
43+ let orig_len = mem:: replace ( & mut deque. len , drain_start) ;
44+ let tail_len = orig_len - drain_start - drain_len;
45+ Drain {
46+ deque : NonNull :: from ( deque) ,
47+ drain_len,
48+ idx : drain_start,
49+ tail_len,
50+ remaining : drain_len,
51+ _marker : PhantomData ,
52+ }
53+ }
54+
55+ // Only returns pointers to the slices, as that's
56+ // all we need to drop them
57+ fn as_slices ( & self ) -> ( * mut [ T ] , * mut [ T ] ) {
58+ unsafe {
59+ let deque = self . deque . as_ref ( ) ;
60+ let wrapped_start = deque. wrap_idx ( self . idx ) ;
61+
62+ if self . remaining <= deque. capacity ( ) - wrapped_start {
63+ // there's only one contigous slice
64+ (
65+ ptr:: slice_from_raw_parts_mut ( deque. ptr ( ) . add ( wrapped_start) , self . remaining ) ,
66+ & mut [ ] as * mut [ T ] ,
67+ )
68+ } else {
69+ let head_len = deque. capacity ( ) - wrapped_start;
70+ // this will never overflow due to the if condition
71+ let tail_len = self . remaining - head_len;
72+ (
73+ ptr:: slice_from_raw_parts_mut ( deque. ptr ( ) . add ( wrapped_start) , head_len) ,
74+ ptr:: slice_from_raw_parts_mut ( deque. ptr ( ) , tail_len) ,
75+ )
76+ }
77+ }
4378 }
4479}
4580
4681#[ stable( feature = "collection_debug" , since = "1.17.0" ) ]
4782impl < T : fmt:: Debug , A : Allocator > fmt:: Debug for Drain < ' _ , T , A > {
4883 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
4984 f. debug_tuple ( "Drain" )
50- . field ( & self . after_tail )
51- . field ( & self . after_head )
52- . field ( & self . ring )
53- . field ( & self . tail )
54- . field ( & self . head )
85+ . field ( & self . drain_len )
86+ . field ( & self . idx )
87+ . field ( & self . tail_len )
88+ . field ( & self . remaining )
5589 . finish ( )
5690 }
5791}
@@ -68,57 +102,77 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
68102
69103 impl < ' r , ' a , T , A : Allocator > Drop for DropGuard < ' r , ' a , T , A > {
70104 fn drop ( & mut self ) {
71- self . 0 . for_each ( drop) ;
105+ if self . 0 . remaining != 0 {
106+ let ( front, back) = self . 0 . as_slices ( ) ;
107+ unsafe {
108+ ptr:: drop_in_place ( front) ;
109+ ptr:: drop_in_place ( back) ;
110+ }
111+ }
72112
73113 let source_deque = unsafe { self . 0 . deque . as_mut ( ) } ;
74114
75- // T = source_deque_tail; H = source_deque_head; t = drain_tail; h = drain_head
76- //
77- // T t h H
78- // [. . . o o x x o o . . .]
79- //
80- let orig_tail = source_deque. tail ;
81- let drain_tail = source_deque. head ;
82- let drain_head = self . 0 . after_tail ;
83- let orig_head = self . 0 . after_head ;
115+ let drain_start = source_deque. len ( ) ;
116+ let drain_len = self . 0 . drain_len ;
117+ let drain_end = drain_start + drain_len;
84118
85- let tail_len = count ( orig_tail, drain_tail, source_deque. cap ( ) ) ;
86- let head_len = count ( drain_head, orig_head, source_deque. cap ( ) ) ;
119+ let orig_len = self . 0 . tail_len + drain_end;
120+
121+ if T :: IS_ZST {
122+ // no need to copy around any memory if T is a ZST
123+ source_deque. len = orig_len - drain_len;
124+ return ;
125+ }
87126
88- // Restore the original head value
89- source_deque . head = orig_head ;
127+ let head_len = drain_start ;
128+ let tail_len = self . 0 . tail_len ;
90129
91- match ( tail_len , head_len ) {
130+ match ( head_len , tail_len ) {
92131 ( 0 , 0 ) => {
93132 source_deque. head = 0 ;
94- source_deque. tail = 0 ;
133+ source_deque. len = 0 ;
95134 }
96135 ( 0 , _) => {
97- source_deque. tail = drain_head;
136+ source_deque. head = source_deque. wrap_idx ( drain_len) ;
137+ source_deque. len = orig_len - drain_len;
98138 }
99139 ( _, 0 ) => {
100- source_deque. head = drain_tail ;
140+ source_deque. len = orig_len - drain_len ;
101141 }
102142 _ => unsafe {
103- if tail_len <= head_len {
104- source_deque. tail = source_deque. wrap_sub ( drain_head, tail_len) ;
105- source_deque. wrap_copy ( source_deque. tail , orig_tail, tail_len) ;
143+ if head_len <= tail_len {
144+ source_deque. wrap_copy (
145+ source_deque. head ,
146+ source_deque. wrap_idx ( drain_len) ,
147+ head_len,
148+ ) ;
149+ source_deque. head = source_deque. wrap_idx ( drain_len) ;
150+ source_deque. len = orig_len - drain_len;
106151 } else {
107- source_deque. head = source_deque. wrap_add ( drain_tail, head_len) ;
108- source_deque. wrap_copy ( drain_tail, drain_head, head_len) ;
152+ source_deque. wrap_copy (
153+ source_deque. wrap_idx ( head_len + drain_len) ,
154+ source_deque. wrap_idx ( head_len) ,
155+ tail_len,
156+ ) ;
157+ source_deque. len = orig_len - drain_len;
109158 }
110159 } ,
111160 }
112161 }
113162 }
114163
115- while let Some ( item) = self . next ( ) {
116- let guard = DropGuard ( self ) ;
117- drop ( item) ;
118- mem:: forget ( guard) ;
164+ let guard = DropGuard ( self ) ;
165+ let ( front, back) = guard. 0 . as_slices ( ) ;
166+ unsafe {
167+ // since idx is a logical index, we don't need to worry about wrapping.
168+ guard. 0 . idx += front. len ( ) ;
169+ guard. 0 . remaining -= front. len ( ) ;
170+ ptr:: drop_in_place ( front) ;
171+ guard. 0 . remaining = 0 ;
172+ ptr:: drop_in_place ( back) ;
119173 }
120174
121- DropGuard ( self ) ;
175+ // Dropping `guard` handles moving the remaining elements into place.
122176 }
123177}
124178
@@ -128,20 +182,18 @@ impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
128182
129183 #[ inline]
130184 fn next ( & mut self ) -> Option < T > {
131- if self . tail == self . head {
185+ if self . remaining == 0 {
132186 return None ;
133187 }
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) ) ) }
188+ let wrapped_idx = unsafe { self . deque . as_ref ( ) . wrap_idx ( self . idx ) } ;
189+ self . idx += 1 ;
190+ self . remaining -= 1 ;
191+ Some ( unsafe { self . deque . as_mut ( ) . buffer_read ( wrapped_idx) } )
140192 }
141193
142194 #[ inline]
143195 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
144- let len = count ( self . tail , self . head , self . ring . len ( ) ) ;
196+ let len = self . remaining ;
145197 ( len, Some ( len) )
146198 }
147199}
@@ -150,14 +202,12 @@ impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
150202impl < T , A : Allocator > DoubleEndedIterator for Drain < ' _ , T , A > {
151203 #[ inline]
152204 fn next_back ( & mut self ) -> Option < T > {
153- if self . tail == self . head {
205+ if self . remaining == 0 {
154206 return None ;
155207 }
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 ) ) ) }
208+ self . remaining -= 1 ;
209+ let wrapped_idx = unsafe { self . deque . as_ref ( ) . wrap_idx ( self . idx + self . remaining ) } ;
210+ Some ( unsafe { self . deque . as_mut ( ) . buffer_read ( wrapped_idx) } )
161211 }
162212}
163213
0 commit comments