summaryrefslogtreecommitdiffstats
path: root/intl/l10n/rust/l10nregistry-rs/src/solver/serial.rs
blob: 9368c12c9e329ab101a641594ea1933835931a4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use super::ProblemSolver;
use std::ops::{Deref, DerefMut};

pub trait SyncTester {
    fn test_sync(&self, res_idx: usize, source_idx: usize) -> bool;
}

pub struct SerialProblemSolver(ProblemSolver);

impl Deref for SerialProblemSolver {
    type Target = ProblemSolver;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for SerialProblemSolver {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl SerialProblemSolver {
    pub fn new(width: usize, depth: usize) -> Self {
        Self(ProblemSolver::new(width, depth))
    }
}

impl SerialProblemSolver {
    fn test_current_cell<T>(&mut self, tester: &T) -> bool
    where
        T: SyncTester,
    {
        let res_idx = self.idx;
        let source_idx = self.solution[res_idx];
        let cell = &mut self.cache[res_idx][source_idx];
        *cell.get_or_insert_with(|| tester.test_sync(res_idx, source_idx))
    }

    pub fn try_next<T>(&mut self, tester: &T, prefetch: bool) -> Result<Option<&[usize]>, usize>
    where
        T: SyncTester,
    {
        if self.width == 0 || self.depth == 0 {
            return Ok(None);
        }
        if self.dirty {
            if !self.bail() {
                return Ok(None);
            }
            self.dirty = false;
        }
        loop {
            if !self.test_current_cell(tester) {
                if !self.bail() {
                    if let Some(res_idx) = self.has_missing_cell() {
                        return Err(res_idx);
                    } else {
                        return Ok(None);
                    }
                }
                continue;
            }
            if self.is_complete() {
                if !prefetch {
                    self.dirty = true;
                }
                return Ok(Some(&self.solution));
            }
            if !self.try_advance_resource() {
                return Ok(None);
            }
        }
    }
}