2
2
// to TreeMap
3
3
4
4
use core:: borrow:: Borrow ;
5
- use core:: cmp:: Ordering :: { self , Less , Greater , Equal } ;
5
+ use core:: cmp:: Ordering :: { Less , Greater , Equal } ;
6
6
use core:: cmp:: { max, min} ;
7
7
use core:: fmt:: { self , Debug } ;
8
8
use core:: iter:: { Peekable , FromIterator , FusedIterator } ;
@@ -109,6 +109,77 @@ pub struct Range<'a, T: 'a> {
109
109
iter : btree_map:: Range < ' a , T , ( ) > ,
110
110
}
111
111
112
+ /// Core of SymmetricDifference and Union.
113
+ /// More efficient than btree.map.MergeIter,
114
+ /// and crucially for SymmetricDifference, nexts() reports on both sides.
115
+ #[ derive( Clone ) ]
116
+ struct MergeIterInner < I >
117
+ where I : Iterator ,
118
+ I :: Item : Copy ,
119
+ {
120
+ a : I ,
121
+ b : I ,
122
+ peeked : Option < MergeIterPeeked < I > > ,
123
+ }
124
+
125
+ #[ derive( Copy , Clone , Debug ) ]
126
+ enum MergeIterPeeked < I : Iterator > {
127
+ A ( I :: Item ) ,
128
+ B ( I :: Item ) ,
129
+ }
130
+
131
+ impl < I > MergeIterInner < I >
132
+ where I : ExactSizeIterator + FusedIterator ,
133
+ I :: Item : Copy + Ord ,
134
+ {
135
+ fn new ( a : I , b : I ) -> Self {
136
+ MergeIterInner { a, b, peeked : None }
137
+ }
138
+
139
+ fn nexts ( & mut self ) -> ( Option < I :: Item > , Option < I :: Item > ) {
140
+ let mut a_next = match self . peeked {
141
+ Some ( MergeIterPeeked :: A ( next) ) => Some ( next) ,
142
+ _ => self . a . next ( ) ,
143
+ } ;
144
+ let mut b_next = match self . peeked {
145
+ Some ( MergeIterPeeked :: B ( next) ) => Some ( next) ,
146
+ _ => self . b . next ( ) ,
147
+ } ;
148
+ let ord = match ( a_next, b_next) {
149
+ ( None , None ) => Equal ,
150
+ ( _, None ) => Less ,
151
+ ( None , _) => Greater ,
152
+ ( Some ( a1) , Some ( b1) ) => a1. cmp ( & b1) ,
153
+ } ;
154
+ self . peeked = match ord {
155
+ Less => b_next. take ( ) . map ( MergeIterPeeked :: B ) ,
156
+ Equal => None ,
157
+ Greater => a_next. take ( ) . map ( MergeIterPeeked :: A ) ,
158
+ } ;
159
+ ( a_next, b_next)
160
+ }
161
+
162
+ fn lens ( & self ) -> ( usize , usize ) {
163
+ match self . peeked {
164
+ Some ( MergeIterPeeked :: A ( _) ) => ( 1 + self . a . len ( ) , self . b . len ( ) ) ,
165
+ Some ( MergeIterPeeked :: B ( _) ) => ( self . a . len ( ) , 1 + self . b . len ( ) ) ,
166
+ _ => ( self . a . len ( ) , self . b . len ( ) ) ,
167
+ }
168
+ }
169
+ }
170
+
171
+ impl < I > Debug for MergeIterInner < I >
172
+ where I : Iterator + Debug ,
173
+ I :: Item : Copy + Debug ,
174
+ {
175
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
176
+ f. debug_tuple ( "MergeIterInner" )
177
+ . field ( & self . a )
178
+ . field ( & self . b )
179
+ . finish ( )
180
+ }
181
+ }
182
+
112
183
/// A lazy iterator producing elements in the difference of `BTreeSet`s.
113
184
///
114
185
/// This `struct` is created by the [`difference`] method on [`BTreeSet`].
@@ -120,6 +191,7 @@ pub struct Range<'a, T: 'a> {
120
191
pub struct Difference < ' a , T : ' a > {
121
192
inner : DifferenceInner < ' a , T > ,
122
193
}
194
+ #[ derive( Debug ) ]
123
195
enum DifferenceInner < ' a , T : ' a > {
124
196
Stitch {
125
197
// iterate all of self and some of other, spotting matches along the way
@@ -137,21 +209,7 @@ enum DifferenceInner<'a, T: 'a> {
137
209
#[ stable( feature = "collection_debug" , since = "1.17.0" ) ]
138
210
impl < T : fmt:: Debug > fmt:: Debug for Difference < ' _ , T > {
139
211
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
140
- match & self . inner {
141
- DifferenceInner :: Stitch {
142
- self_iter,
143
- other_iter,
144
- } => f
145
- . debug_tuple ( "Difference" )
146
- . field ( & self_iter)
147
- . field ( & other_iter)
148
- . finish ( ) ,
149
- DifferenceInner :: Search {
150
- self_iter,
151
- other_set : _,
152
- } => f. debug_tuple ( "Difference" ) . field ( & self_iter) . finish ( ) ,
153
- DifferenceInner :: Iterate ( iter) => f. debug_tuple ( "Difference" ) . field ( & iter) . finish ( ) ,
154
- }
212
+ f. debug_tuple ( "Difference" ) . field ( & self . inner ) . finish ( )
155
213
}
156
214
}
157
215
@@ -163,18 +221,12 @@ impl<T: fmt::Debug> fmt::Debug for Difference<'_, T> {
163
221
/// [`BTreeSet`]: struct.BTreeSet.html
164
222
/// [`symmetric_difference`]: struct.BTreeSet.html#method.symmetric_difference
165
223
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
166
- pub struct SymmetricDifference < ' a , T : ' a > {
167
- a : Peekable < Iter < ' a , T > > ,
168
- b : Peekable < Iter < ' a , T > > ,
169
- }
224
+ pub struct SymmetricDifference < ' a , T : ' a > ( MergeIterInner < Iter < ' a , T > > ) ;
170
225
171
226
#[ stable( feature = "collection_debug" , since = "1.17.0" ) ]
172
227
impl < T : fmt:: Debug > fmt:: Debug for SymmetricDifference < ' _ , T > {
173
228
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
174
- f. debug_tuple ( "SymmetricDifference" )
175
- . field ( & self . a )
176
- . field ( & self . b )
177
- . finish ( )
229
+ f. debug_tuple ( "SymmetricDifference" ) . field ( & self . 0 ) . finish ( )
178
230
}
179
231
}
180
232
@@ -189,6 +241,7 @@ impl<T: fmt::Debug> fmt::Debug for SymmetricDifference<'_, T> {
189
241
pub struct Intersection < ' a , T : ' a > {
190
242
inner : IntersectionInner < ' a , T > ,
191
243
}
244
+ #[ derive( Debug ) ]
192
245
enum IntersectionInner < ' a , T : ' a > {
193
246
Stitch {
194
247
// iterate similarly sized sets jointly, spotting matches along the way
@@ -206,23 +259,7 @@ enum IntersectionInner<'a, T: 'a> {
206
259
#[ stable( feature = "collection_debug" , since = "1.17.0" ) ]
207
260
impl < T : fmt:: Debug > fmt:: Debug for Intersection < ' _ , T > {
208
261
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
209
- match & self . inner {
210
- IntersectionInner :: Stitch {
211
- a,
212
- b,
213
- } => f
214
- . debug_tuple ( "Intersection" )
215
- . field ( & a)
216
- . field ( & b)
217
- . finish ( ) ,
218
- IntersectionInner :: Search {
219
- small_iter,
220
- large_set : _,
221
- } => f. debug_tuple ( "Intersection" ) . field ( & small_iter) . finish ( ) ,
222
- IntersectionInner :: Answer ( answer) => {
223
- f. debug_tuple ( "Intersection" ) . field ( & answer) . finish ( )
224
- }
225
- }
262
+ f. debug_tuple ( "Intersection" ) . field ( & self . inner ) . finish ( )
226
263
}
227
264
}
228
265
@@ -234,18 +271,12 @@ impl<T: fmt::Debug> fmt::Debug for Intersection<'_, T> {
234
271
/// [`BTreeSet`]: struct.BTreeSet.html
235
272
/// [`union`]: struct.BTreeSet.html#method.union
236
273
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
237
- pub struct Union < ' a , T : ' a > {
238
- a : Peekable < Iter < ' a , T > > ,
239
- b : Peekable < Iter < ' a , T > > ,
240
- }
274
+ pub struct Union < ' a , T : ' a > ( MergeIterInner < Iter < ' a , T > > ) ;
241
275
242
276
#[ stable( feature = "collection_debug" , since = "1.17.0" ) ]
243
277
impl < T : fmt:: Debug > fmt:: Debug for Union < ' _ , T > {
244
278
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
245
- f. debug_tuple ( "Union" )
246
- . field ( & self . a )
247
- . field ( & self . b )
248
- . finish ( )
279
+ f. debug_tuple ( "Union" ) . field ( & self . 0 ) . finish ( )
249
280
}
250
281
}
251
282
@@ -355,19 +386,16 @@ impl<T: Ord> BTreeSet<T> {
355
386
self_iter. next_back ( ) ;
356
387
DifferenceInner :: Iterate ( self_iter)
357
388
}
358
- _ => {
359
- if self . len ( ) <= other. len ( ) / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
360
- DifferenceInner :: Search {
361
- self_iter : self . iter ( ) ,
362
- other_set : other,
363
- }
364
- } else {
365
- DifferenceInner :: Stitch {
366
- self_iter : self . iter ( ) ,
367
- other_iter : other. iter ( ) . peekable ( ) ,
368
- }
389
+ _ if self . len ( ) <= other. len ( ) / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
390
+ DifferenceInner :: Search {
391
+ self_iter : self . iter ( ) ,
392
+ other_set : other,
369
393
}
370
394
}
395
+ _ => DifferenceInner :: Stitch {
396
+ self_iter : self . iter ( ) ,
397
+ other_iter : other. iter ( ) . peekable ( ) ,
398
+ } ,
371
399
} ,
372
400
}
373
401
}
@@ -396,10 +424,7 @@ impl<T: Ord> BTreeSet<T> {
396
424
pub fn symmetric_difference < ' a > ( & ' a self ,
397
425
other : & ' a BTreeSet < T > )
398
426
-> SymmetricDifference < ' a , T > {
399
- SymmetricDifference {
400
- a : self . iter ( ) . peekable ( ) ,
401
- b : other. iter ( ) . peekable ( ) ,
402
- }
427
+ SymmetricDifference ( MergeIterInner :: new ( self . iter ( ) , other. iter ( ) ) )
403
428
}
404
429
405
430
/// Visits the values representing the intersection,
@@ -447,24 +472,22 @@ impl<T: Ord> BTreeSet<T> {
447
472
( Greater , _) | ( _, Less ) => IntersectionInner :: Answer ( None ) ,
448
473
( Equal , _) => IntersectionInner :: Answer ( Some ( self_min) ) ,
449
474
( _, Equal ) => IntersectionInner :: Answer ( Some ( self_max) ) ,
450
- _ => {
451
- if self . len ( ) <= other. len ( ) / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
452
- IntersectionInner :: Search {
453
- small_iter : self . iter ( ) ,
454
- large_set : other,
455
- }
456
- } else if other. len ( ) <= self . len ( ) / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
457
- IntersectionInner :: Search {
458
- small_iter : other. iter ( ) ,
459
- large_set : self ,
460
- }
461
- } else {
462
- IntersectionInner :: Stitch {
463
- a : self . iter ( ) ,
464
- b : other. iter ( ) ,
465
- }
475
+ _ if self . len ( ) <= other. len ( ) / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
476
+ IntersectionInner :: Search {
477
+ small_iter : self . iter ( ) ,
478
+ large_set : other,
479
+ }
480
+ }
481
+ _ if other. len ( ) <= self . len ( ) / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
482
+ IntersectionInner :: Search {
483
+ small_iter : other. iter ( ) ,
484
+ large_set : self ,
466
485
}
467
486
}
487
+ _ => IntersectionInner :: Stitch {
488
+ a : self . iter ( ) ,
489
+ b : other. iter ( ) ,
490
+ } ,
468
491
} ,
469
492
}
470
493
}
@@ -489,10 +512,7 @@ impl<T: Ord> BTreeSet<T> {
489
512
/// ```
490
513
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
491
514
pub fn union < ' a > ( & ' a self , other : & ' a BTreeSet < T > ) -> Union < ' a , T > {
492
- Union {
493
- a : self . iter ( ) . peekable ( ) ,
494
- b : other. iter ( ) . peekable ( ) ,
495
- }
515
+ Union ( MergeIterInner :: new ( self . iter ( ) , other. iter ( ) ) )
496
516
}
497
517
498
518
/// Clears the set, removing all values.
@@ -1166,15 +1186,6 @@ impl<'a, T> DoubleEndedIterator for Range<'a, T> {
1166
1186
#[ stable( feature = "fused" , since = "1.26.0" ) ]
1167
1187
impl < T > FusedIterator for Range < ' _ , T > { }
1168
1188
1169
- /// Compares `x` and `y`, but return `short` if x is None and `long` if y is None
1170
- fn cmp_opt < T : Ord > ( x : Option < & T > , y : Option < & T > , short : Ordering , long : Ordering ) -> Ordering {
1171
- match ( x, y) {
1172
- ( None , _) => short,
1173
- ( _, None ) => long,
1174
- ( Some ( x1) , Some ( y1) ) => x1. cmp ( y1) ,
1175
- }
1176
- }
1177
-
1178
1189
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1179
1190
impl < T > Clone for Difference < ' _ , T > {
1180
1191
fn clone ( & self ) -> Self {
@@ -1261,10 +1272,7 @@ impl<T: Ord> FusedIterator for Difference<'_, T> {}
1261
1272
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1262
1273
impl < T > Clone for SymmetricDifference < ' _ , T > {
1263
1274
fn clone ( & self ) -> Self {
1264
- SymmetricDifference {
1265
- a : self . a . clone ( ) ,
1266
- b : self . b . clone ( ) ,
1267
- }
1275
+ SymmetricDifference ( self . 0 . clone ( ) )
1268
1276
}
1269
1277
}
1270
1278
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -1273,19 +1281,19 @@ impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> {
1273
1281
1274
1282
fn next ( & mut self ) -> Option < & ' a T > {
1275
1283
loop {
1276
- match cmp_opt ( self . a . peek ( ) , self . b . peek ( ) , Greater , Less ) {
1277
- Less => return self . a . next ( ) ,
1278
- Equal => {
1279
- self . a . next ( ) ;
1280
- self . b . next ( ) ;
1281
- }
1282
- Greater => return self . b . next ( ) ,
1284
+ let ( a_next, b_next) = self . 0 . nexts ( ) ;
1285
+ if a_next. and ( b_next) . is_none ( ) {
1286
+ return a_next. or ( b_next) ;
1283
1287
}
1284
1288
}
1285
1289
}
1286
1290
1287
1291
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
1288
- ( 0 , Some ( self . a . len ( ) + self . b . len ( ) ) )
1292
+ let ( a_len, b_len) = self . 0 . lens ( ) ;
1293
+ // No checked_add, because even if a and b refer to the same set,
1294
+ // and T is an empty type, the storage overhead of sets limits
1295
+ // the number of elements to less than half the range of usize.
1296
+ ( 0 , Some ( a_len + b_len) )
1289
1297
}
1290
1298
}
1291
1299
@@ -1311,7 +1319,7 @@ impl<T> Clone for Intersection<'_, T> {
1311
1319
small_iter : small_iter. clone ( ) ,
1312
1320
large_set,
1313
1321
} ,
1314
- IntersectionInner :: Answer ( answer) => IntersectionInner :: Answer ( answer. clone ( ) ) ,
1322
+ IntersectionInner :: Answer ( answer) => IntersectionInner :: Answer ( * answer) ,
1315
1323
} ,
1316
1324
}
1317
1325
}
@@ -1365,30 +1373,21 @@ impl<T: Ord> FusedIterator for Intersection<'_, T> {}
1365
1373
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1366
1374
impl < T > Clone for Union < ' _ , T > {
1367
1375
fn clone ( & self ) -> Self {
1368
- Union {
1369
- a : self . a . clone ( ) ,
1370
- b : self . b . clone ( ) ,
1371
- }
1376
+ Union ( self . 0 . clone ( ) )
1372
1377
}
1373
1378
}
1374
1379
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1375
1380
impl < ' a , T : Ord > Iterator for Union < ' a , T > {
1376
1381
type Item = & ' a T ;
1377
1382
1378
1383
fn next ( & mut self ) -> Option < & ' a T > {
1379
- match cmp_opt ( self . a . peek ( ) , self . b . peek ( ) , Greater , Less ) {
1380
- Less => self . a . next ( ) ,
1381
- Equal => {
1382
- self . b . next ( ) ;
1383
- self . a . next ( )
1384
- }
1385
- Greater => self . b . next ( ) ,
1386
- }
1384
+ let ( a_next, b_next) = self . 0 . nexts ( ) ;
1385
+ a_next. or ( b_next)
1387
1386
}
1388
1387
1389
1388
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
1390
- let a_len = self . a . len ( ) ;
1391
- let b_len = self . b . len ( ) ;
1389
+ let ( a_len, b_len ) = self . 0 . lens ( ) ;
1390
+ // No checked_add - see SymmetricDifference::size_hint.
1392
1391
( max ( a_len, b_len) , Some ( a_len + b_len) )
1393
1392
}
1394
1393
}
0 commit comments