use dcbor::prelude::*;
use crate::pattern::{Matcher, Path, Pattern, vm::Instr};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CapturePattern {
name: String,
pattern: Box<Pattern>,
}
impl CapturePattern {
pub fn new(name: impl AsRef<str>, pattern: Pattern) -> Self {
CapturePattern {
name: name.as_ref().to_string(),
pattern: Box::new(pattern),
}
}
pub fn name(&self) -> &str { &self.name }
pub fn pattern(&self) -> &Pattern { &self.pattern }
}
impl Matcher for CapturePattern {
fn paths(&self, haystack: &CBOR) -> Vec<Path> {
self.pattern.paths(haystack)
}
fn compile(
&self,
code: &mut Vec<Instr>,
literals: &mut Vec<Pattern>,
captures: &mut Vec<String>,
) {
let capture_idx = captures.len();
captures.push(self.name.clone());
code.push(Instr::CaptureStart(capture_idx));
self.pattern.compile(code, literals, captures);
code.push(Instr::CaptureEnd(capture_idx));
}
fn collect_capture_names(&self, names: &mut Vec<String>) {
names.push(self.name.clone());
self.pattern.collect_capture_names(names);
}
fn is_complex(&self) -> bool {
self.pattern.is_complex()
}
fn paths_with_captures(
&self,
haystack: &CBOR,
) -> (Vec<Path>, std::collections::HashMap<String, Vec<Path>>) {
let (paths, mut captures) = self.pattern.paths_with_captures(haystack);
if !paths.is_empty() {
captures.insert(self.name.clone(), paths.clone());
}
(paths, captures)
}
}
impl std::fmt::Display for CapturePattern {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "@{}({})", self.name, self.pattern)
}
}