#[derive(Debug)]
pub struct Expression<'a> {
pub(crate) input: &'a str,
pub(crate) nodes: Vec<Node>,
pub(crate) root: u32,
}
#[derive(Debug, Clone, Copy)]
pub enum Node {
Key {
start: u32,
end: u32,
},
QuotedKey {
start: u32,
end: u32,
},
Or {
children_start: u32,
children_count: u16,
},
And {
children_start: u32,
children_count: u16,
},
}
impl<'a> Expression<'a> {
#[inline]
pub(crate) fn new(input: &'a str, nodes: Vec<Node>, root: u32) -> Self {
Self { input, nodes, root }
}
#[inline]
#[allow(dead_code)]
pub fn input(&self) -> &'a str {
self.input
}
#[inline]
#[allow(dead_code)]
pub fn node_count(&self) -> usize {
self.nodes.len()
}
#[inline]
pub fn matches<K: AsRef<str>>(&self, keys: &[K]) -> bool {
self.eval_node(self.root as usize, keys)
}
#[inline]
fn eval_node<K: AsRef<str>>(&self, node_idx: usize, keys: &[K]) -> bool {
match self.nodes[node_idx] {
Node::Key { start, end } => {
let key_str = &self.input[start as usize..end as usize];
keys.iter().any(|k| k.as_ref() == key_str)
}
Node::QuotedKey { start, end } => {
let key_str = &self.input[start as usize..end as usize];
keys.iter().any(|k| k.as_ref() == key_str)
}
Node::Or {
children_start,
children_count,
} => {
let start = children_start as usize;
let count = children_count as usize;
(0..count).any(|i| self.eval_node(start + i, keys))
}
Node::And {
children_start,
children_count,
} => {
let start = children_start as usize;
let count = children_count as usize;
(0..count).all(|i| self.eval_node(start + i, keys))
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_expression_simple_key() {
let input = "test";
let nodes = vec![Node::Key { start: 0, end: 4 }];
let expr = Expression::new(input, nodes, 0);
assert!(expr.matches(&["test"]));
assert!(!expr.matches(&["other"]));
assert!(expr.matches(&["test", "other"]));
}
#[test]
fn test_expression_or() {
let input = "a || b";
let nodes = vec![
Node::Key { start: 0, end: 1 }, Node::Key { start: 5, end: 6 }, Node::Or {
children_start: 0,
children_count: 2,
}, ];
let expr = Expression::new(input, nodes, 2);
assert!(expr.matches(&["a"]));
assert!(expr.matches(&["b"]));
assert!(expr.matches(&["a", "b"]));
assert!(!expr.matches(&["c"]));
}
#[test]
fn test_expression_and() {
let input = "a && b";
let nodes = vec![
Node::Key { start: 0, end: 1 }, Node::Key { start: 5, end: 6 }, Node::And {
children_start: 0,
children_count: 2,
}, ];
let expr = Expression::new(input, nodes, 2);
assert!(!expr.matches(&["a"]));
assert!(!expr.matches(&["b"]));
assert!(expr.matches(&["a", "b"]));
assert!(!expr.matches(&["c"]));
}
#[test]
fn test_expression_quoted_key() {
let input = "'test key'";
let nodes = vec![Node::QuotedKey { start: 1, end: 9 }];
let expr = Expression::new(input, nodes, 0);
assert!(expr.matches(&["test key"]));
assert!(!expr.matches(&["test"]));
assert!(!expr.matches(&["'test key'"]));
}
}