use dcbor::prelude::*;
use super::{
backtrack::{
AssignmentBacktrackState, BooleanBacktrackState, GenericBacktracker,
},
helpers::has_repeat_patterns_in_slice,
};
use crate::pattern::{Matcher, Pattern};
pub struct SequenceAssigner<'a> {
patterns: &'a [Pattern],
arr: &'a [CBOR],
}
impl<'a> SequenceAssigner<'a> {
pub fn new(patterns: &'a [Pattern], arr: &'a [CBOR]) -> Self {
Self { patterns, arr }
}
pub fn can_match(&self) -> bool {
if self.patterns.is_empty() {
return self.arr.is_empty();
}
let has_repeat_patterns = has_repeat_patterns_in_slice(self.patterns);
if self.patterns.len() == self.arr.len() && !has_repeat_patterns {
return self
.patterns
.iter()
.enumerate()
.all(|(i, pattern)| pattern.matches(&self.arr[i]));
}
let backtracker = GenericBacktracker::new(self.patterns, self.arr);
let mut state = BooleanBacktrackState;
backtracker.backtrack(&mut state, 0, 0)
}
pub fn find_assignments(&self) -> Option<Vec<(usize, usize)>> {
if self.patterns.is_empty() {
return if self.arr.is_empty() {
Some(Vec::new())
} else {
None
};
}
let has_repeat_patterns = has_repeat_patterns_in_slice(self.patterns);
if self.patterns.len() == self.arr.len() && !has_repeat_patterns {
let mut assignments = Vec::new();
for (pattern_idx, pattern) in self.patterns.iter().enumerate() {
let element = &self.arr[pattern_idx];
if pattern.matches(element) {
assignments.push((pattern_idx, pattern_idx));
} else {
return None; }
}
return Some(assignments);
}
let backtracker = GenericBacktracker::new(self.patterns, self.arr);
let mut state = AssignmentBacktrackState::new();
if backtracker.backtrack(&mut state, 0, 0) {
Some(state.assignments)
} else {
None
}
}
}