tabled/settings/location/
by_value.rs

1use crate::{
2    grid::{
3        config::Position,
4        records::{ExactRecords, PeekableRecords, Records},
5    },
6    settings::object::{EntityOnce, Object},
7};
8
9/// The structure is an implementation of [`Location`] to search for cells with a given content.
10///
11/// [`Location`]: crate::settings::location::Location
12#[derive(Debug, Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
13pub struct ByValue<O, F> {
14    search: O,
15    f: F,
16}
17
18impl<O, F> ByValue<O, F> {
19    /// Constructs a new object of the structure.
20    pub fn new(search: O, f: F) -> Self
21    where
22        F: Fn(&str, &str) -> bool,
23    {
24        Self { search, f }
25    }
26}
27
28impl<O, F, R> Object<R> for ByValue<O, F>
29where
30    O: Object<R>,
31    F: Fn(&str, &str) -> bool,
32    R: Records + PeekableRecords + ExactRecords,
33{
34    type Iter = EntityOnce;
35
36    fn cells(&self, records: &R) -> Self::Iter {
37        let count_rows = records.count_rows();
38        let count_cols = records.count_columns();
39        let cells = self.search.cells(records);
40
41        let mut last: Option<&str> = None;
42        let mut last_pos: Option<Position> = None;
43
44        for e in cells.into_iter() {
45            for pos in e.iter(count_rows, count_cols) {
46                let text = records.get_text(pos);
47                match last {
48                    Some(last_value) => {
49                        let take = (self.f)(text, last_value);
50                        if take {
51                            last = Some(text);
52                            last_pos = Some(pos);
53                        }
54                    }
55                    None => {
56                        last = Some(text);
57                        last_pos = Some(pos);
58                    }
59                }
60            }
61        }
62
63        let pos = last_pos.map(|pos| pos.into());
64
65        EntityOnce::new(pos)
66    }
67}