1
+ #[ cfg( feature = "use_std" ) ]
2
+ use std:: error:: Error ;
3
+ use std:: fmt:: { Debug , Display , Formatter , Result as FmtResult } ;
4
+
1
5
use std:: iter:: ExactSizeIterator ;
2
6
7
+ use either:: Either ;
8
+
3
9
use crate :: size_hint;
4
10
5
11
/// Iterator returned for the error case of `IterTools::exactly_one()`
@@ -10,12 +16,12 @@ use crate::size_hint;
10
16
///
11
17
/// This is very similar to PutBackN except this iterator only supports 0-2 elements and does not
12
18
/// use a `Vec`.
13
- #[ derive( Debug , Clone ) ]
19
+ #[ derive( Clone ) ]
14
20
pub struct ExactlyOneError < I >
15
21
where
16
22
I : Iterator ,
17
23
{
18
- first_two : ( Option < I :: Item > , Option < I :: Item > ) ,
24
+ first_two : Option < Either < [ I :: Item ; 2 ] , I :: Item > > ,
19
25
inner : I ,
20
26
}
21
27
24
30
I : Iterator ,
25
31
{
26
32
/// Creates a new `ExactlyOneErr` iterator.
27
- pub ( crate ) fn new ( first_two : ( Option < I :: Item > , Option < I :: Item > ) , inner : I ) -> Self {
33
+ pub ( crate ) fn new ( first_two : Option < Either < [ I :: Item ; 2 ] , I :: Item > > , inner : I ) -> Self {
28
34
Self { first_two, inner }
29
35
}
36
+
37
+ fn additional_len ( & self ) -> usize {
38
+ match self . first_two {
39
+ Some ( Either :: Left ( _) ) => 2 ,
40
+ Some ( Either :: Right ( _) ) => 1 ,
41
+ None => 0 ,
42
+ }
43
+ }
30
44
}
31
45
32
46
impl < I > Iterator for ExactlyOneError < I >
@@ -36,23 +50,61 @@ where
36
50
type Item = I :: Item ;
37
51
38
52
fn next ( & mut self ) -> Option < Self :: Item > {
39
- self . first_two
40
- . 0
41
- . take ( )
42
- . or_else ( || self . first_two . 1 . take ( ) )
43
- . or_else ( || self . inner . next ( ) )
53
+ match self . first_two . take ( ) {
54
+ Some ( Either :: Left ( [ first, second] ) ) => {
55
+ self . first_two = Some ( Either :: Right ( second) ) ;
56
+ Some ( first)
57
+ } ,
58
+ Some ( Either :: Right ( second) ) => {
59
+ Some ( second)
60
+ }
61
+ None => {
62
+ self . inner . next ( )
63
+ }
64
+ }
44
65
}
45
66
46
67
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
47
- let mut additional_len = 0 ;
48
- if self . first_two . 0 . is_some ( ) {
49
- additional_len += 1 ;
68
+ size_hint:: add_scalar ( self . inner . size_hint ( ) , self . additional_len ( ) )
69
+ }
70
+ }
71
+
72
+
73
+ impl < I > ExactSizeIterator for ExactlyOneError < I > where I : ExactSizeIterator { }
74
+
75
+ impl < I > Display for ExactlyOneError < I >
76
+ where I : Iterator ,
77
+ {
78
+ fn fmt ( & self , f : & mut Formatter ) -> FmtResult {
79
+ let additional = self . additional_len ( ) ;
80
+ if additional > 0 {
81
+ write ! ( f, "got at least 2 elements when exactly one was expected" )
82
+ } else {
83
+ write ! ( f, "got zero elements when exactly one was expected" )
50
84
}
51
- if self . first_two . 1 . is_some ( ) {
52
- additional_len += 1 ;
85
+ }
86
+ }
87
+
88
+ impl < I > Debug for ExactlyOneError < I >
89
+ where I : Iterator + Debug ,
90
+ I :: Item : Debug ,
91
+ {
92
+ fn fmt ( & self , f : & mut Formatter ) -> FmtResult {
93
+ match & self . first_two {
94
+ Some ( Either :: Left ( [ first, second] ) ) => {
95
+ write ! ( f, "ExactlyOneError[First: {:?}, Second: {:?}, RemainingIter: {:?}]" , first, second, self . inner)
96
+ } ,
97
+ Some ( Either :: Right ( second) ) => {
98
+ write ! ( f, "ExactlyOneError[Second: {:?}, RemainingIter: {:?}]" , second, self . inner)
99
+ }
100
+ None => {
101
+ write ! ( f, "ExactlyOneError[RemainingIter: {:?}]" , self . inner)
102
+ }
53
103
}
54
- size_hint:: add_scalar ( self . inner . size_hint ( ) , additional_len)
55
104
}
56
105
}
57
106
58
- impl < I > ExactSizeIterator for ExactlyOneError < I > where I : ExactSizeIterator { }
107
+ #[ cfg( feature = "use_std" ) ]
108
+ impl < I > Error for ExactlyOneError < I > where I : Iterator + Debug , I :: Item : Debug , { }
109
+
110
+
0 commit comments