1
+ use crate :: size_hint;
1
2
use std:: { fmt, iter:: FusedIterator } ;
2
3
3
4
pub fn flatten_ok < I , T , E > ( iter : I ) -> FlattenOk < I , T , E >
4
5
where
5
6
I : Iterator < Item = Result < T , E > > ,
6
7
T : IntoIterator ,
7
8
{
8
- FlattenOk { iter, inner : None }
9
+ FlattenOk {
10
+ iter,
11
+ inner_front : None ,
12
+ inner_back : None ,
13
+ }
9
14
}
10
15
11
16
/// An iterator adaptor that flattens `Result::Ok` values and
19
24
T : IntoIterator ,
20
25
{
21
26
iter : I ,
22
- inner : Option < T :: IntoIter > ,
27
+ inner_front : Option < T :: IntoIter > ,
28
+ inner_back : Option < T :: IntoIter > ,
23
29
}
24
30
25
31
impl < I , T , E > Iterator for FlattenOk < I , T , E >
@@ -31,45 +37,54 @@ where
31
37
32
38
fn next ( & mut self ) -> Option < Self :: Item > {
33
39
loop {
34
- if let Some ( inner) = & mut self . inner {
40
+ // Handle the front inner iterator.
41
+ if let Some ( inner) = & mut self . inner_front {
35
42
if let Some ( item) = inner. next ( ) {
36
43
return Some ( Ok ( item) ) ;
37
44
} else {
38
45
// This is necessary for the iterator to implement `FusedIterator`
39
46
// with only the orginal iterator being fused.
40
- self . inner = None ;
47
+ self . inner_front = None ;
41
48
}
42
49
}
43
50
44
51
match self . iter . next ( ) {
45
- Some ( Ok ( ok) ) => self . inner = Some ( ok. into_iter ( ) ) ,
52
+ Some ( Ok ( ok) ) => self . inner_front = Some ( ok. into_iter ( ) ) ,
46
53
Some ( Err ( e) ) => return Some ( Err ( e) ) ,
47
- None => return None ,
54
+ None => {
55
+ // Handle the back inner iterator.
56
+ if let Some ( inner) = & mut self . inner_back {
57
+ if let Some ( item) = inner. next ( ) {
58
+ return Some ( Ok ( item) ) ;
59
+ } else {
60
+ // This is necessary for the iterator to implement `FusedIterator`
61
+ // with only the orginal iterator being fused.
62
+ self . inner_back = None ;
63
+ }
64
+ } else {
65
+ return None ;
66
+ }
67
+ }
48
68
}
49
69
}
50
70
}
51
71
52
72
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
53
- if let Some ( inner) = & self . inner {
54
- // If we have an inner iterator, then its lower bound is our lower bound,
55
- // but we still don't know the upper bound.
56
- let ( inner_lower, inner_higher) = inner. size_hint ( ) ;
57
- let ( _, outer_higher) = self . iter . size_hint ( ) ;
58
- if outer_higher == Some ( 0 ) {
59
- // If there is nothing remaining in the outer iterator, we know the upper bound.
60
- ( inner_lower, inner_higher)
61
- } else {
62
- // However, if the outer iterator could have more items in it, we don't
63
- // know the upper bound.
64
- ( inner_lower, None )
65
- }
66
- } else if self . iter . size_hint ( ) == ( 0 , Some ( 0 ) ) {
67
- // If the outer iterator is empty, we have no items.
68
- ( 0 , Some ( 0 ) )
69
- } else {
70
- // Otherwise we do not know anything about the number of items.
71
- ( 0 , None )
72
- }
73
+ let inner_hint = |inner : & Option < T :: IntoIter > | {
74
+ inner
75
+ . as_ref ( )
76
+ . map ( Iterator :: size_hint)
77
+ . unwrap_or ( ( 0 , Some ( 0 ) ) )
78
+ } ;
79
+ let inner_front = inner_hint ( & self . inner_front ) ;
80
+ let inner_back = inner_hint ( & self . inner_back ) ;
81
+ // The outer iterator `Ok` case could be (0, None) as we don't know its size_hint yet.
82
+ let outer = match self . iter . size_hint ( ) {
83
+ ( 0 , Some ( 0 ) ) => ( 0 , Some ( 0 ) ) ,
84
+ _ => ( 0 , None ) ,
85
+ } ;
86
+
87
+ size_hint:: add ( size_hint:: add ( inner_front, inner_back) , outer)
73
88
}
74
89
}
75
90
80
95
T :: IntoIter : Clone ,
81
96
{
82
97
#[ inline]
83
- clone_fields ! ( iter, inner ) ;
98
+ clone_fields ! ( iter, inner_front , inner_back ) ;
84
99
}
85
100
86
101
impl < I , T , E > fmt:: Debug for FlattenOk < I , T , E >
92
107
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
93
108
f. debug_struct ( "FlattenOk" )
94
109
. field ( "iter" , & self . iter )
95
- . field ( "inner" , & self . inner )
110
+ . field ( "inner_front" , & self . inner_front )
111
+ . field ( "inner_back" , & self . inner_back )
96
112
. finish ( )
97
113
}
98
114
}
0 commit comments