use crate::{depth::Depth, engine::error::EngineError};
use std::{convert::Infallible, fmt::Display, io, ops::Deref};
pub mod count;
pub mod empty;
pub mod index;
pub mod nodes;
pub type MatchCount = u64;
pub type MatchIndex = usize;
pub struct MatchSpan {
pub start_idx: MatchIndex,
pub end_idx: MatchIndex,
}
pub struct Match {
pub bytes: Vec<u8>,
pub span: MatchSpan,
}
impl Display for Match {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let display = String::from_utf8_lossy(&self.bytes);
write!(f, "{display}")
}
}
pub trait Sink<D> {
type Error: std::error::Error + Send + Sync + 'static;
fn add_match(&mut self, data: D) -> Result<(), Self::Error>;
}
impl<D> Sink<D> for Vec<D> {
type Error = Infallible;
#[inline(always)]
fn add_match(&mut self, data: D) -> Result<(), Infallible> {
self.push(data);
Ok(())
}
}
pub struct NullSink;
impl<D> Sink<D> for NullSink {
type Error = Infallible;
#[inline(always)]
fn add_match(&mut self, _data: D) -> Result<(), Infallible> {
Ok(())
}
}
pub struct MatchWriter<W>(W);
impl<W> From<W> for MatchWriter<W>
where
W: io::Write,
{
#[inline(always)]
fn from(value: W) -> Self {
Self(value)
}
}
impl<D, W> Sink<D> for MatchWriter<W>
where
D: Display,
W: io::Write,
{
type Error = io::Error;
#[inline(always)]
fn add_match(&mut self, data: D) -> Result<(), io::Error> {
writeln!(self.0, "{data}")
}
}
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum MatchedNodeType {
Atomic,
Complex,
}
pub trait InputRecorder<B: Deref<Target = [u8]>> {
fn record_block_start(&self, new_block: B);
}
pub trait Recorder<B: Deref<Target = [u8]>>: InputRecorder<B> {
fn record_match(&self, idx: usize, depth: Depth, ty: MatchedNodeType) -> Result<(), EngineError>;
fn record_value_terminator(&self, idx: usize, depth: Depth) -> Result<(), EngineError>;
}