@@ -3,7 +3,7 @@ use super::{
3
3
utils:: modulus,
4
4
} ;
5
5
use crate :: utils:: { move_uninit_slice, slice_as_uninit_mut, slice_assume_init_mut, slice_assume_init_ref} ;
6
- use core:: { iter:: Chain , marker :: PhantomData , mem:: MaybeUninit , ptr, slice} ;
6
+ use core:: { iter:: Chain , mem:: MaybeUninit , ptr, slice} ;
7
7
#[ cfg( feature = "std" ) ]
8
8
use std:: io:: { self , Write } ;
9
9
@@ -156,10 +156,7 @@ pub trait Consumer: Observer {
156
156
}
157
157
158
158
/// Returns an iterator that removes items one by one from the ring buffer.
159
- fn pop_iter ( & mut self ) -> PopIter < & mut Self , Self >
160
- where
161
- Self : AsMut < Self > + AsRef < Self > ,
162
- {
159
+ fn pop_iter ( & mut self ) -> PopIter < Self > {
163
160
PopIter :: new ( self )
164
161
}
165
162
@@ -256,37 +253,90 @@ pub trait Consumer: Observer {
256
253
}
257
254
}
258
255
256
+ /// Owning ring buffer iterator.
257
+ pub struct IntoIter < C : Consumer + ?Sized > {
258
+ inner : C ,
259
+ }
260
+
261
+ impl < C : Consumer > IntoIter < C > {
262
+ pub fn new ( inner : C ) -> Self {
263
+ Self { inner }
264
+ }
265
+ pub fn into_inner ( self ) -> C {
266
+ self . inner
267
+ }
268
+ }
269
+
270
+ impl < C : Consumer > Iterator for IntoIter < C > {
271
+ type Item = C :: Item ;
272
+
273
+ #[ inline]
274
+ fn next ( & mut self ) -> Option < Self :: Item > {
275
+ self . inner . try_pop ( )
276
+ }
277
+ #[ inline]
278
+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
279
+ ( self . inner . occupied_len ( ) , None )
280
+ }
281
+ }
282
+
259
283
/// An iterator that removes items from the ring buffer.
260
- pub struct PopIter < U : AsMut < C > + AsRef < C > , C : Consumer + ?Sized > {
261
- inner : U ,
262
- _ghost : PhantomData < C > ,
284
+ ///
285
+ /// Producer will see removed items only when iterator is dropped or [`PopIter::commit`] is called.
286
+ pub struct PopIter < ' a , C : Consumer + ?Sized > {
287
+ inner : & ' a C ,
288
+ iter : Chain < slice:: Iter < ' a , MaybeUninit < C :: Item > > , slice:: Iter < ' a , MaybeUninit < C :: Item > > > ,
289
+ count : usize ,
290
+ len : usize ,
263
291
}
264
292
265
- impl < U : AsMut < C > + AsRef < C > , C : Consumer + ?Sized > PopIter < U , C > {
266
- pub fn new ( inner : U ) -> Self {
293
+ impl < ' a , C : Consumer + ?Sized > Drop for PopIter < ' a , C > {
294
+ fn drop ( & mut self ) {
295
+ self . commit ( ) ;
296
+ }
297
+ }
298
+
299
+ impl < ' a , C : Consumer + ?Sized > PopIter < ' a , C > {
300
+ /// Create an iterator.
301
+ pub fn new ( inner : & ' a mut C ) -> Self {
302
+ let ( len, iter) = {
303
+ let ( left, right) = inner. occupied_slices ( ) ;
304
+ ( left. len ( ) + right. len ( ) , left. iter ( ) . chain ( right) )
305
+ } ;
267
306
Self {
268
307
inner,
269
- _ghost : PhantomData ,
308
+ iter,
309
+ count : 0 ,
310
+ len,
270
311
}
271
312
}
272
- pub fn into_inner ( self ) -> U {
273
- self . inner
313
+
314
+ /// Send information about removed items to the ring buffer.
315
+ pub fn commit ( & mut self ) {
316
+ unsafe { self . inner . advance_read_index ( self . count ) } ;
317
+ self . count = 0 ;
274
318
}
275
319
}
276
320
277
- impl < U : AsMut < C > + AsRef < C > , C : Consumer > Iterator for PopIter < U , C > {
321
+ impl < ' a , C : Consumer > Iterator for PopIter < ' a , C > {
278
322
type Item = C :: Item ;
279
323
280
324
#[ inline]
281
325
fn next ( & mut self ) -> Option < Self :: Item > {
282
- self . inner . as_mut ( ) . try_pop ( )
326
+ self . iter . next ( ) . map ( |item| {
327
+ self . count += 1 ;
328
+ unsafe { item. assume_init_read ( ) }
329
+ } )
283
330
}
284
331
#[ inline]
285
332
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
286
- ( self . inner . as_ref ( ) . occupied_len ( ) , None )
333
+ let remain = self . len - self . count ;
334
+ ( remain, Some ( remain) )
287
335
}
288
336
}
289
337
338
+ impl < ' a , C : Consumer > ExactSizeIterator for PopIter < ' a , C > { }
339
+
290
340
/// Iterator over ring buffer contents.
291
341
///
292
342
/// *Please do not rely on actual type, it may change in future.*
@@ -376,9 +426,9 @@ macro_rules! impl_consumer_traits {
376
426
( $type: ident $( < $( $param: tt $( : $first_bound: tt $( + $next_bound: tt ) * ) ? ) ,+ >) ?) => {
377
427
impl $( < $( $param $( : $first_bound $( + $next_bound ) * ) ? ) ,+ >) ? core:: iter:: IntoIterator for $type $( < $( $param ) ,+ >) ? where Self : Sized {
378
428
type Item = <Self as $crate:: traits:: Observer >:: Item ;
379
- type IntoIter = $crate:: traits:: consumer:: PopIter < Self , Self >;
429
+ type IntoIter = $crate:: traits:: consumer:: IntoIter < Self >;
380
430
fn into_iter( self ) -> Self :: IntoIter {
381
- $crate:: traits:: consumer:: PopIter :: new( self )
431
+ $crate:: traits:: consumer:: IntoIter :: new( self )
382
432
}
383
433
}
384
434
0 commit comments