@@ -3,7 +3,9 @@ use crate::{Node, SetTrie};
33/// Iterator for [subset](SetTrie::subset) method.
44#[ derive( Debug , Clone ) ]
55pub struct Subset < ' a , ' b , K , T > {
6- current : & ' a Node < K , T > ,
6+ current : Option < & ' a Node < K , T > > ,
7+
8+ /// Buffer of next nodes to visit.
79 next : Vec < ( & ' a K , & ' a Node < K , T > ) > ,
810 idx : usize ,
911 keys : & ' b [ K ] ,
@@ -13,9 +15,33 @@ impl<'a, 'b, K, T> Subset<'a, 'b, K, T>
1315where
1416 K : Ord ,
1517{
18+ #[ must_use]
1619 pub ( crate ) fn new ( trie : & ' a SetTrie < K , T > , keys : & ' b [ K ] ) -> Self {
20+ // There might be a cleaner way to accomplish this. Right now we're doing
21+ // computation in the subset iterator, which means it's not fully lazy.
22+ let current = match keys. len ( ) {
23+ // Empty keys has it's own leaves as childeren as items.
24+ 0 => Some ( & trie. 0 ) ,
25+ _ => {
26+ if let Some ( first) = keys. first ( ) {
27+ if trie
28+ . 0
29+ . children
30+ . binary_search_by ( |( child, _) | child. cmp ( first) )
31+ . is_ok ( )
32+ {
33+ Some ( & trie. 0 )
34+ } else {
35+ None
36+ }
37+ } else {
38+ Some ( & trie. 0 )
39+ }
40+ }
41+ } ;
42+
1743 Subset {
18- current : & trie . 0 ,
44+ current,
1945 next : vec ! [ ] ,
2046 idx : 0 ,
2147 keys,
@@ -30,15 +56,20 @@ where
3056 type Item = & ' a T ;
3157
3258 fn next ( & mut self ) -> Option < Self :: Item > {
33- if self . idx < self . current . leaves . len ( ) {
59+ if self . current . is_none ( ) {
60+ return None ;
61+ }
62+
63+ if self . idx < self . current . unwrap ( ) . leaves . len ( ) {
3464 self . idx += 1 ;
35- Some ( & self . current . leaves [ self . idx - 1 ] )
65+ Some ( & self . current . unwrap ( ) . leaves [ self . idx - 1 ] )
3666 } else {
3767 if let ( Some ( from) , Some ( to) ) = ( self . keys . first ( ) , self . keys . last ( ) ) {
3868 self . next . extend (
3969 self . current
70+ . unwrap ( )
4071 // technically, between inclusive is only necessary on the first iteration,
41- // where we check handle the root node. Every subsequent iter may use up-to,
72+ // where we handle the root node. Every subsequent iter may use up-to,
4273 // which saves a single binary search. For long key lengths this may matter.
4374 . between_inclusive ( from, to)
4475 . iter ( )
4980 while let Some ( ( k, node) ) = self . next . pop ( ) {
5081 if self . keys . binary_search ( k) . is_ok ( ) {
5182 self . idx = 0 ;
52- self . current = node;
83+ self . current = Some ( node) ;
5384 return self . next ( ) ;
5485 }
5586 self . next . extend (
6495 }
6596
6697 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
67- ( self . current . leaves . len ( ) - self . idx , None )
98+ if let Some ( current) = self . current {
99+ ( current. leaves . len ( ) - self . idx , None )
100+ } else {
101+ ( 0 , None )
102+ }
68103 }
69104}
70105
@@ -94,11 +129,11 @@ mod tests {
94129 // A set is its own subset.
95130 assert_eq ! ( v. subsets( & [ ] ) . collect:: <Vec <_>>( ) , vec![ & 'f' ] ) ;
96131
97- // Quite a specific match should work.
132+ // // Quite a specific match should work.
98133 assert_eq ! ( v. subsets( & [ & 5 ] ) . collect:: <Vec <_>>( ) , vec![ & 'f' , & 'i' ] ) ;
99134
100- // Non-existing key should match nothing
101- assert_eq ! ( v. subsets( & [ & 6 ] ) . collect:: <Vec <_ >>( ) , vec! [ & 'f' ] ) ;
135+ // // Non-existing key should match nothing
136+ assert_eq ! ( v. subsets( & [ & 6 ] ) . collect:: <Vec <& char >>( ) . len ( ) , 0 ) ;
102137 }
103138
104139 mod proptest {
0 commit comments