1
- use std:: collections:: BTreeMap ;
2
- use std:: ops:: Bound ;
3
1
use std:: path:: { Path , PathBuf } ;
4
2
use std:: sync:: Arc ;
5
3
@@ -18,36 +16,45 @@ pub struct SearchPath {
18
16
19
17
/// [FilesIndex] contains paths that can be efficiently looked up with (prefix, suffix) pairs.
20
18
#[ derive( Clone , Debug ) ]
21
- pub struct FilesIndex ( BTreeMap < Arc < str > , Arc < SearchPathFile > > ) ;
19
+ pub struct FilesIndex ( Vec < ( Arc < str > , SearchPathFile ) > ) ;
22
20
23
21
impl FilesIndex {
24
22
/// Look up [SearchPathFile] by (prefix, suffix) pair.
25
23
pub fn query < ' this , ' prefix , ' suffix > (
26
24
& ' this self ,
27
25
prefix : & ' prefix str ,
28
26
suffix : & ' suffix str ,
29
- ) -> Option < impl Iterator < Item = ( String , Arc < SearchPathFile > ) > + use < ' this , ' prefix , ' suffix > >
27
+ ) -> Option < impl Iterator < Item = ( String , & ' this SearchPathFile ) > + use < ' this , ' prefix , ' suffix > >
30
28
{
31
- let start = prefix;
32
- let end = format ! ( "{prefix}\u{FFFF} " ) ;
33
- let mut ret = self
34
- . 0
35
- . range :: < str , _ > ( ( Bound :: Included ( start) , Bound :: Excluded ( end. as_str ( ) ) ) )
36
- . filter_map ( move |( k, v) | {
37
- k. ends_with ( suffix) . then ( || {
38
- (
39
- String :: from (
40
- & v. file_name_str [ prefix. len ( ) ..v. file_name_str . len ( ) - suffix. len ( ) ] ,
41
- ) ,
42
- Arc :: clone ( v) ,
43
- )
44
- } )
29
+ let start = self . 0 . partition_point ( |( k, _) | {
30
+ let k: & str = & k;
31
+ k < prefix
32
+ } ) ;
33
+ if start == self . 0 . len ( ) {
34
+ return None ;
35
+ }
36
+ let prefixed_items;
37
+ let end = self . 0 [ start..] . partition_point ( |( k, _) | k. starts_with ( prefix) ) ;
38
+ if end + start == self . 0 . len ( ) {
39
+ prefixed_items = & self . 0 [ start..] ;
40
+ } else {
41
+ prefixed_items = & self . 0 [ start..start + end] ;
42
+ }
43
+
44
+ let ret = prefixed_items. into_iter ( ) . filter_map ( move |( k, v) | {
45
+ k. ends_with ( suffix) . then ( || {
46
+ (
47
+ String :: from (
48
+ & v. file_name_str [ prefix. len ( ) ..v. file_name_str . len ( ) - suffix. len ( ) ] ,
49
+ ) ,
50
+ v,
51
+ )
45
52
} )
46
- . peekable ( ) ;
47
- ret . peek ( ) . is_some ( ) . then ( || ret)
53
+ } ) ;
54
+ Some ( ret)
48
55
}
49
56
pub fn retain ( & mut self , prefixes : & [ & str ] ) {
50
- self . 0 . retain ( |k, _| prefixes. iter ( ) . any ( |prefix| k. starts_with ( prefix) ) ) ;
57
+ self . 0 . retain ( |( k, _) | prefixes. iter ( ) . any ( |prefix| k. starts_with ( prefix) ) ) ;
51
58
}
52
59
}
53
60
/// The obvious implementation of `SearchPath::files` is a `Vec<PathBuf>`. But
@@ -135,23 +142,24 @@ impl SearchPath {
135
142
136
143
pub fn new ( kind : PathKind , dir : PathBuf ) -> Self {
137
144
// Get the files within the directory.
138
- let files = match std:: fs:: read_dir ( & dir) {
145
+ let mut files = match std:: fs:: read_dir ( & dir) {
139
146
Ok ( files) => files
140
147
. filter_map ( |e| {
141
148
e. ok ( ) . and_then ( |e| {
142
149
e. file_name ( ) . to_str ( ) . map ( |s| {
143
150
let file_name_str: Arc < str > = s. into ( ) ;
144
- (
145
- Arc :: clone ( & file_name_str ) ,
146
- Arc :: new ( SearchPathFile { path : e . path ( ) . into ( ) , file_name_str } ) ,
147
- )
151
+ ( Arc :: clone ( & file_name_str ) , SearchPathFile {
152
+ path : e . path ( ) . into ( ) ,
153
+ file_name_str,
154
+ } )
148
155
} )
149
156
} )
150
157
} )
151
- . collect :: < BTreeMap < _ , _ > > ( ) ,
158
+ . collect :: < Vec < _ > > ( ) ,
152
159
153
160
Err ( ..) => Default :: default ( ) ,
154
161
} ;
162
+ files. sort_by ( |( lhs, _) , ( rhs, _) | lhs. cmp ( rhs) ) ;
155
163
let files = FilesIndex ( files) ;
156
164
SearchPath { kind, dir, files }
157
165
}
0 commit comments