Skip to content

Commit 4289f23

Browse files
committed
Make iterators generic on Deref to allow for owned versions through Rc
1 parent 9958c45 commit 4289f23

File tree

2 files changed

+85
-37
lines changed

2 files changed

+85
-37
lines changed

src/groupbylazy.rs

Lines changed: 83 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use std::cell::{Cell, RefCell};
2+
use std::ops::Deref;
3+
use std::rc::Rc;
24
use alloc::vec::{self, Vec};
35

46
/// A trait to unify FnMut for GroupBy with the chunk key in IntoChunks
@@ -334,20 +336,44 @@ impl<K, I, F> GroupBy<K, I, F>
334336
}
335337
}
336338

339+
impl<K, I, F> IntoIterator for GroupBy<K, I, F>
340+
where I: Iterator,
341+
F: FnMut(&I::Item) -> K,
342+
K: PartialEq
343+
{
344+
type Item = (K, Group<K, I, F, Rc<Self>>);
345+
type IntoIter = Groups<K, I, F, Rc<Self>>;
346+
347+
fn into_iter(self) -> Self::IntoIter {
348+
Groups { parent: Rc::new(self) }
349+
}
350+
}
351+
337352
impl<'a, K, I, F> IntoIterator for &'a GroupBy<K, I, F>
338353
where I: Iterator,
339-
I::Item: 'a,
340354
F: FnMut(&I::Item) -> K,
341355
K: PartialEq
342356
{
343-
type Item = (K, Group<'a, K, I, F>);
344-
type IntoIter = Groups<'a, K, I, F>;
357+
type Item = (K, Group<K, I, F, Self>);
358+
type IntoIter = Groups<K, I, F, Self>;
345359

346360
fn into_iter(self) -> Self::IntoIter {
347361
Groups { parent: self }
348362
}
349363
}
350364

365+
impl<K, I, F> GroupBy<K, I, F>
366+
where I: Iterator,
367+
F: FnMut(&I::Item) -> K,
368+
K: PartialEq
369+
{
370+
/// This is pretty much the same as `.into_iter()`, except it uses references
371+
/// in the underlying iterators instead of reference counts, resulting in one less
372+
/// allocation. You may however hit lifetime errors if you require full ownership.
373+
pub fn borrowed_iter<'a>(&'a self) -> <&'a Self as IntoIterator>::IntoIter {
374+
self.into_iter()
375+
}
376+
}
351377

352378
/// An iterator that yields the Group iterators.
353379
///
@@ -356,20 +382,19 @@ impl<'a, K, I, F> IntoIterator for &'a GroupBy<K, I, F>
356382
///
357383
/// See [`.group_by()`](../trait.Itertools.html#method.group_by) for more information.
358384
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
359-
pub struct Groups<'a, K: 'a, I: 'a, F: 'a>
385+
pub struct Groups<K, I, F, D: Deref<Target=GroupBy<K, I, F>>>
360386
where I: Iterator,
361-
I::Item: 'a
362387
{
363-
parent: &'a GroupBy<K, I, F>,
388+
parent: D,
364389
}
365390

366-
impl<'a, K, I, F> Iterator for Groups<'a, K, I, F>
391+
impl<K, I, F, D> Iterator for Groups<K, I, F, D>
367392
where I: Iterator,
368-
I::Item: 'a,
369393
F: FnMut(&I::Item) -> K,
370-
K: PartialEq
394+
K: PartialEq,
395+
D: Deref<Target=GroupBy<K, I, F>> + Clone,
371396
{
372-
type Item = (K, Group<'a, K, I, F>);
397+
type Item = (K, Group<K, I, F, D>);
373398

374399
#[inline]
375400
fn next(&mut self) -> Option<Self::Item> {
@@ -379,7 +404,7 @@ impl<'a, K, I, F> Iterator for Groups<'a, K, I, F>
379404
inner.step(index).map(|elt| {
380405
let key = inner.group_key(index);
381406
(key, Group {
382-
parent: self.parent,
407+
parent: self.parent.clone(),
383408
index,
384409
first: Some(elt),
385410
})
@@ -390,29 +415,29 @@ impl<'a, K, I, F> Iterator for Groups<'a, K, I, F>
390415
/// An iterator for the elements in a single group.
391416
///
392417
/// Iterator element type is `I::Item`.
393-
pub struct Group<'a, K: 'a, I: 'a, F: 'a>
418+
pub struct Group<K, I, F, D>
394419
where I: Iterator,
395-
I::Item: 'a,
420+
D: Deref<Target=GroupBy<K,I,F>>
396421
{
397-
parent: &'a GroupBy<K, I, F>,
422+
parent: D,
398423
index: usize,
399424
first: Option<I::Item>,
400425
}
401426

402-
impl<'a, K, I, F> Drop for Group<'a, K, I, F>
427+
impl<K, I, F, D> Drop for Group<K, I, F, D>
403428
where I: Iterator,
404-
I::Item: 'a,
429+
D: Deref<Target=GroupBy<K,I,F>>
405430
{
406431
fn drop(&mut self) {
407432
self.parent.drop_group(self.index);
408433
}
409434
}
410435

411-
impl<'a, K, I, F> Iterator for Group<'a, K, I, F>
436+
impl<K, I, F, D> Iterator for Group<K, I, F, D>
412437
where I: Iterator,
413-
I::Item: 'a,
414438
F: FnMut(&I::Item) -> K,
415439
K: PartialEq,
440+
D: Deref<Target=GroupBy<K,I,F>>
416441
{
417442
type Item = I::Item;
418443
#[inline]
@@ -486,12 +511,24 @@ impl<I> IntoChunks<I>
486511
}
487512
}
488513

514+
impl<I> IntoIterator for IntoChunks<I>
515+
where I: Iterator,
516+
{
517+
type Item = Chunk<I, Rc<Self>>;
518+
type IntoIter = Chunks<I, Rc<Self>>;
519+
520+
fn into_iter(self) -> Self::IntoIter {
521+
Chunks {
522+
parent: Rc::new(self),
523+
}
524+
}
525+
}
526+
489527
impl<'a, I> IntoIterator for &'a IntoChunks<I>
490528
where I: Iterator,
491-
I::Item: 'a,
492529
{
493-
type Item = Chunk<'a, I>;
494-
type IntoIter = Chunks<'a, I>;
530+
type Item = Chunk<I, Self>;
531+
type IntoIter = Chunks<I, Self>;
495532

496533
fn into_iter(self) -> Self::IntoIter {
497534
Chunks {
@@ -500,25 +537,36 @@ impl<'a, I> IntoIterator for &'a IntoChunks<I>
500537
}
501538
}
502539

540+
impl<I> IntoChunks<I>
541+
where I: Iterator,
542+
{
543+
/// This is pretty much the same as `.into_iter()`, except it uses references
544+
/// in the underlying iterators instead of reference counts, resulting in one less
545+
/// allocation. You may however hit lifetime errors if you require full ownership.
546+
pub fn borrowed_iter<'a>(&'a self) -> <&'a Self as IntoIterator>::IntoIter {
547+
self.into_iter()
548+
}
549+
}
550+
503551

504552
/// An iterator that yields the Chunk iterators.
505553
///
506554
/// Iterator element type is `Chunk`.
507555
///
508556
/// See [`.chunks()`](../trait.Itertools.html#method.chunks) for more information.
509557
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
510-
pub struct Chunks<'a, I: 'a>
558+
pub struct Chunks<I, D>
511559
where I: Iterator,
512-
I::Item: 'a,
560+
D: Deref<Target=IntoChunks<I>>
513561
{
514-
parent: &'a IntoChunks<I>,
562+
parent: D,
515563
}
516564

517-
impl<'a, I> Iterator for Chunks<'a, I>
565+
impl<I, D> Iterator for Chunks<I, D>
518566
where I: Iterator,
519-
I::Item: 'a,
567+
D: Deref<Target=IntoChunks<I>> + Clone,
520568
{
521-
type Item = Chunk<'a, I>;
569+
type Item = Chunk<I, D>;
522570

523571
#[inline]
524572
fn next(&mut self) -> Option<Self::Item> {
@@ -527,7 +575,7 @@ impl<'a, I> Iterator for Chunks<'a, I>
527575
let inner = &mut *self.parent.inner.borrow_mut();
528576
inner.step(index).map(|elt| {
529577
Chunk {
530-
parent: self.parent,
578+
parent: self.parent.clone(),
531579
index,
532580
first: Some(elt),
533581
}
@@ -538,27 +586,27 @@ impl<'a, I> Iterator for Chunks<'a, I>
538586
/// An iterator for the elements in a single chunk.
539587
///
540588
/// Iterator element type is `I::Item`.
541-
pub struct Chunk<'a, I: 'a>
589+
pub struct Chunk<I, D>
542590
where I: Iterator,
543-
I::Item: 'a,
591+
D: Deref<Target=IntoChunks<I>>
544592
{
545-
parent: &'a IntoChunks<I>,
593+
parent: D,
546594
index: usize,
547595
first: Option<I::Item>,
548596
}
549597

550-
impl<'a, I> Drop for Chunk<'a, I>
598+
impl<I, D> Drop for Chunk<I, D>
551599
where I: Iterator,
552-
I::Item: 'a,
600+
D: Deref<Target=IntoChunks<I>>
553601
{
554602
fn drop(&mut self) {
555603
self.parent.drop_group(self.index);
556604
}
557605
}
558606

559-
impl<'a, I> Iterator for Chunk<'a, I>
607+
impl<I, D> Iterator for Chunk<I, D>
560608
where I: Iterator,
561-
I::Item: 'a,
609+
D: Deref<Target=IntoChunks<I>>
562610
{
563611
type Item = I::Item;
564612
#[inline]

tests/quick.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -954,8 +954,8 @@ quickcheck! {
954954
quickcheck! {
955955
fn fuzz_group_by_lazy_duo(data: Vec<u8>, order: Vec<(bool, bool)>) -> bool {
956956
let grouper = data.iter().group_by(|k| *k / 3);
957-
let mut groups1 = grouper.into_iter();
958-
let mut groups2 = grouper.into_iter();
957+
let mut groups1 = grouper.borrowed_iter();
958+
let mut groups2 = grouper.borrowed_iter();
959959
let mut elts = Vec::<&u8>::new();
960960
let mut old_groups = Vec::new();
961961

0 commit comments

Comments
 (0)