@@ -4,8 +4,9 @@ use std::{fs, path};
44
55use glob:: Pattern ;
66
7+ use crate :: config:: CaseSensitivity ;
78use crate :: db:: { Database , Dir , Epoch } ;
8- use crate :: util:: { self , MONTH } ;
9+ use crate :: util:: MONTH ;
910
1011pub struct Stream < ' a > {
1112 db : & ' a mut Database ,
@@ -48,13 +49,18 @@ impl<'a> Stream<'a> {
4849 }
4950
5051 fn filter_by_keywords ( & self , path : & str ) -> bool {
51- let ( keywords_last, keywords) = match self . options . keywords . split_last ( ) {
52+ let keywords: Vec < String > = self
53+ . options
54+ . keywords
55+ . iter ( )
56+ . map ( |s| self . options . case_sensitivity . convert_case ( s) )
57+ . collect ( ) ;
58+
59+ let ( keywords_last, keywords) = match keywords. split_last ( ) {
5260 Some ( split) => split,
5361 None => return true ,
5462 } ;
55-
56- let path = util:: to_lowercase ( path) ;
57- let mut path = path. as_str ( ) ;
63+ let mut path = & self . options . case_sensitivity . convert_case ( path) [ ..] ;
5864 match path. rfind ( keywords_last) {
5965 Some ( idx) => {
6066 if path[ idx + keywords_last. len ( ) ..] . contains ( path:: is_separator) {
@@ -112,6 +118,9 @@ pub struct StreamOptions {
112118 /// Directories that do not exist and haven't been accessed since TTL will
113119 /// be lazily removed.
114120 ttl : Epoch ,
121+
122+ /// Whether searching should be perform case sensitively.
123+ case_sensitivity : CaseSensitivity ,
115124}
116125
117126impl StreamOptions {
@@ -123,6 +132,7 @@ impl StreamOptions {
123132 exists : false ,
124133 resolve_symlinks : false ,
125134 ttl : now. saturating_sub ( 3 * MONTH ) ,
135+ case_sensitivity : CaseSensitivity :: CaseInsensitive ,
126136 }
127137 }
128138
@@ -131,7 +141,12 @@ impl StreamOptions {
131141 I : IntoIterator ,
132142 I :: Item : AsRef < str > ,
133143 {
134- self . keywords = keywords. into_iter ( ) . map ( util:: to_lowercase) . collect ( ) ;
144+ self . keywords = keywords. into_iter ( ) . map ( |s| s. as_ref ( ) . into ( ) ) . collect ( ) ;
145+ self
146+ }
147+
148+ pub fn with_case_sensitivity ( mut self , case_sensitivity : CaseSensitivity ) -> Self {
149+ self . case_sensitivity = case_sensitivity;
135150 self
136151 }
137152
@@ -185,4 +200,16 @@ mod tests {
185200 let stream = Stream :: new ( db, options) ;
186201 assert_eq ! ( is_match, stream. filter_by_keywords( path) ) ;
187202 }
203+
204+ #[ rstest]
205+ // Case normalization
206+ #[ case( & [ "fOo" , "bAr" ] , "/foo/bar" , false ) ]
207+ fn query_case_sensitive ( #[ case] keywords : & [ & str ] , #[ case] path : & str , #[ case] is_match : bool ) {
208+ let db = & mut Database :: new ( PathBuf :: new ( ) , Vec :: new ( ) , |_| Vec :: new ( ) , false ) ;
209+ let options = StreamOptions :: new ( 0 )
210+ . with_keywords ( keywords. iter ( ) )
211+ . with_case_sensitivity ( CaseSensitivity :: CaseSensitive ) ;
212+ let stream = Stream :: new ( db, options) ;
213+ assert_eq ! ( is_match, stream. filter_by_keywords( path) ) ;
214+ }
188215}
0 commit comments