1use crate::{
2 grid::config::Entity,
3 grid::{
4 config::Position,
5 records::{ExactRecords, PeekableRecords, Records},
6 },
7 settings::location::Location,
8 settings::object::Object,
9};
10
11/// The structure is an implementation of [`Location`] to search for cells with a specified condition.
12#[derive(Debug, Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
13pub struct ByCondition<F>(F);
14
15impl<F> ByCondition<F> {
16 /// Constructs a new object of the structure.
17 pub fn new(search: F) -> Self
18 where
19 F: Fn(&str) -> bool,
20 {
21 Self(search)
22 }
23}
24
25impl<F, R> Location<R> for ByCondition<F>
26where
27 F: Fn(&str) -> bool,
28 R: Records + ExactRecords + PeekableRecords,
29{
30 type Coordinate = Position;
31 type IntoIter = Vec<Position>;
32
33 fn locate(&mut self, records: &R) -> Self::IntoIter {
34 // todo: can be optimized by creating Iterator
35 let cond: &F = &self.0;
36
37 let mut out: Vec<(usize, usize)> = vec![];
38 for row: usize in 0..records.count_rows() {
39 for col: usize in 0..records.count_columns() {
40 let text: &str = records.get_text((row, col));
41 if cond(text) {
42 out.push((row, col));
43 }
44 }
45 }
46
47 out
48 }
49}
50
51impl<F, R> Object<R> for ByCondition<F>
52where
53 F: Fn(&str) -> bool,
54 R: Records + ExactRecords + PeekableRecords,
55{
56 type Iter = std::vec::IntoIter<Entity>;
57
58 fn cells(&self, records: &R) -> Self::Iter {
59 // todo: can be optimized by creating Iterator
60 let cond: &F = &self.0;
61
62 let mut out: Vec = vec![];
63 for row: usize in 0..records.count_rows() {
64 for col: usize in 0..records.count_columns() {
65 let text: &str = records.get_text((row, col));
66 if cond(text) {
67 out.push(Entity::Cell(row, col));
68 }
69 }
70 }
71
72 out.into_iter()
73 }
74}
75