@@ -166,6 +166,31 @@ impl Data {
166
166
Some ( self . rows [ real_index] . as_slice ( common_fields) )
167
167
}
168
168
169
+ pub fn selected_row_data_as_slice_with_filter_matching_fields (
170
+ & mut self ,
171
+ common_fields : & BTreeSet < String > ,
172
+ ) -> Option < ( & [ ( String , String ) ] , Vec < usize > ) > {
173
+ // Collect other needed info before taking mutable borrow to appease the borrow checker (couldn't find another readable way)
174
+ let is_filtered = self . is_filtered ( ) ;
175
+ let filter = if is_filtered {
176
+ self . filter . clone ( )
177
+ } else {
178
+ None
179
+ } ;
180
+ let row_slice = self . selected_row_data_as_slice ( common_fields) ?;
181
+ let matching_fields = if is_filtered {
182
+ if let Some ( filter) = filter. as_ref ( ) {
183
+ matching_fields ( row_slice, filter) . unwrap_or_default ( )
184
+ } else {
185
+ debug_assert ! ( false , "No filter but is_filtered is true?" ) ;
186
+ Vec :: new ( )
187
+ }
188
+ } else {
189
+ Vec :: new ( )
190
+ } ;
191
+ Some ( ( row_slice, matching_fields) )
192
+ }
193
+
169
194
pub fn move_selected_to_next ( & mut self ) {
170
195
let n = self . len ( ) ;
171
196
if let Some ( selected) = self . selected_row . as_mut ( ) {
@@ -229,7 +254,7 @@ impl Data {
229
254
. iter_mut ( )
230
255
. enumerate ( )
231
256
. filter_map ( |( i, row) | {
232
- if is_included ( row, filter, common_fields ) {
257
+ if matching_fields ( row. as_slice ( common_fields ) , filter) . is_some ( ) {
233
258
Some ( i)
234
259
} else {
235
260
None
@@ -261,45 +286,54 @@ impl Data {
261
286
}
262
287
}
263
288
264
- fn is_included (
265
- row : & mut LogRow ,
266
- filter : & filter :: FilterConfig ,
267
- common_fields : & BTreeSet < String > ,
268
- ) -> bool {
289
+ /// If the slice of fields and values matches the filter then the indices of the fields that match are returned or None if it does not match
290
+ fn matching_fields (
291
+ fields_and_values : & [ ( String , String ) ] ,
292
+ filter : & FilterConfig ,
293
+ ) -> Option < Vec < usize > > {
269
294
let FilterConfig {
270
295
search_key,
271
296
filter_on,
272
297
comparator,
273
298
is_case_sensitive,
274
299
} = filter;
275
- let fields_and_values = row. as_slice ( common_fields) ;
276
300
let search_key = if * is_case_sensitive {
277
301
search_key
278
302
} else {
279
303
& search_key. to_lowercase ( )
280
304
} ;
281
- let mut iter = fields_and_values. iter ( ) . map ( |( k, v) | {
282
- if * is_case_sensitive {
283
- ( Cow :: Borrowed ( k) , Cow :: Borrowed ( v) )
284
- } else {
285
- ( Cow :: Owned ( k. to_lowercase ( ) ) , Cow :: Owned ( v. to_lowercase ( ) ) )
286
- }
287
- } ) ;
288
-
289
- match filter_on {
290
- filter:: FilterOn :: Any => {
291
- iter. any ( |( _, value) | comparator. apply ( search_key, value. as_str ( ) ) )
292
- }
305
+ let iter = fields_and_values
306
+ . iter ( )
307
+ . map ( |( k, v) | {
308
+ if * is_case_sensitive {
309
+ ( Cow :: Borrowed ( k) , Cow :: Borrowed ( v) )
310
+ } else {
311
+ ( Cow :: Owned ( k. to_lowercase ( ) ) , Cow :: Owned ( v. to_lowercase ( ) ) )
312
+ }
313
+ } )
314
+ . enumerate ( ) ;
315
+ let result: Vec < usize > = match filter_on {
316
+ filter:: FilterOn :: Any => iter
317
+ . filter_map ( |( i, ( _, value) ) | comparator. apply ( search_key, value. as_str ( ) ) . then_some ( i) )
318
+ . collect ( ) ,
293
319
filter:: FilterOn :: Field ( FieldSpecifier { name } ) => {
294
320
let name = if * is_case_sensitive {
295
321
name
296
322
} else {
297
323
& name. to_lowercase ( )
298
324
} ;
299
- iter. any ( |( field_name, value) | {
300
- name == field_name. as_str ( ) && comparator. apply ( search_key, value. as_str ( ) )
325
+ iter. filter_map ( |( i, ( field_name, value) ) | {
326
+ ( name == field_name. as_str ( ) && comparator. apply ( search_key, value. as_str ( ) ) )
327
+ . then_some ( i)
301
328
} )
329
+ . collect ( )
302
330
}
331
+ } ;
332
+
333
+ if result. is_empty ( ) {
334
+ None
335
+ } else {
336
+ Some ( result)
303
337
}
304
338
}
305
339
0 commit comments