Skip to main content

subtr_actor/util/
search.rs

1use serde::Serialize;
2
3/// Enum to define the direction of searching within a collection.
4#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
5pub enum SearchDirection {
6    Forward,
7    Backward,
8}
9
10/// Searches for an item in a slice in a specified direction and returns the
11/// first item that matches the provided predicate.
12///
13/// # Arguments
14///
15/// * `items` - The list of items to search.
16/// * `current_index` - The index to start the search from.
17/// * `direction` - The direction to search in.
18/// * `predicate` - A function that takes an item and returns an [`Option<R>`].
19///   When this function returns `Some(R)`, the item is considered a match.
20///
21/// # Returns
22///
23/// Returns a tuple of the index and the result `R` of the predicate for the first item that matches.
24pub fn find_in_direction<T, F, R>(
25    items: &[T],
26    current_index: usize,
27    direction: SearchDirection,
28    predicate: F,
29) -> Option<(usize, R)>
30where
31    F: Fn(&T) -> Option<R>,
32{
33    match direction {
34        SearchDirection::Forward => current_index.checked_add(1).and_then(|start| {
35            items
36                .iter()
37                .enumerate()
38                .skip(start)
39                .find_map(|(i, item)| predicate(item).map(|res| (i, res)))
40        }),
41        SearchDirection::Backward => items[..current_index.min(items.len())]
42            .iter()
43            .enumerate()
44            .rev()
45            .find_map(|(i, item)| predicate(item).map(|res| (i, res))),
46    }
47}
48
49#[cfg(test)]
50#[path = "search_tests.rs"]
51mod tests;