1+ #[ cfg( feature = "use_std" ) ]
2+ use std:: error:: Error ;
3+ use std:: fmt:: { Debug , Display , Formatter , Result as FmtResult } ;
4+
15use std:: iter:: ExactSizeIterator ;
26
7+ use either:: Either ;
8+
39use crate :: size_hint;
410
511/// Iterator returned for the error case of `IterTools::exactly_one()`
@@ -10,12 +16,12 @@ use crate::size_hint;
1016///
1117/// This is very similar to PutBackN except this iterator only supports 0-2 elements and does not
1218/// use a `Vec`.
13- #[ derive( Debug , Clone ) ]
19+ #[ derive( Clone ) ]
1420pub struct ExactlyOneError < I >
1521where
1622 I : Iterator ,
1723{
18- first_two : ( Option < I :: Item > , Option < I :: Item > ) ,
24+ first_two : Option < Either < [ I :: Item ; 2 ] , I :: Item > > ,
1925 inner : I ,
2026}
2127
2430 I : Iterator ,
2531{
2632 /// 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 {
2834 Self { first_two, inner }
2935 }
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+ }
3044}
3145
3246impl < I > Iterator for ExactlyOneError < I >
@@ -36,23 +50,61 @@ where
3650 type Item = I :: Item ;
3751
3852 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+ }
4465 }
4566
4667 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" )
5084 }
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+ }
53103 }
54- size_hint:: add_scalar ( self . inner . size_hint ( ) , additional_len)
55104 }
56105}
57106
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