use crate::scan::engine::MatchScan;
#[cfg(any(test, feature = "cpu-parity"))]
use crate::scan::post_process::try_reference_post_process;
use crate::scan::post_process::{PostProcessError, PostProcessedMatch};
use vyre::{BackendError, VyreBackend};
use vyre_foundation::match_result::Match;
pub type PostProcessFn = fn(&[Match], &[u8]) -> Result<Vec<PostProcessedMatch>, PostProcessError>;
pub struct Pipeline<E> {
pub engine: E,
pub post_process: PostProcessFn,
}
impl<E: MatchScan> Pipeline<E> {
#[must_use]
#[cfg(any(test, feature = "cpu-parity"))]
pub const fn new(engine: E) -> Self {
Self {
engine,
post_process: try_reference_post_process,
}
}
#[must_use]
pub const fn with_post_process(engine: E, post_process: PostProcessFn) -> Self {
Self {
engine,
post_process,
}
}
#[must_use]
#[cfg(any(test, feature = "cpu-parity"))]
pub fn reference_scan_processed(&self, haystack: &[u8]) -> Vec<PostProcessedMatch> {
let raw = self.engine.reference_scan(haystack);
(self.post_process)(&raw, haystack).unwrap_or_else(|error| {
panic!("vyre-libs scan Reference oracle post-process contract failed: {error}")
})
}
#[cfg(any(test, feature = "cpu-parity"))]
pub fn try_reference_scan_processed(
&self,
haystack: &[u8],
) -> Result<Vec<PostProcessedMatch>, PostProcessError> {
let raw = self.engine.reference_scan(haystack);
(self.post_process)(&raw, haystack)
}
pub fn scan_processed(
&self,
backend: &dyn VyreBackend,
haystack: &[u8],
max_matches: u32,
) -> Result<Vec<PostProcessedMatch>, BackendError> {
let raw = self.engine.scan(backend, haystack, max_matches)?;
(self.post_process)(&raw, haystack).map_err(|error| BackendError::new(error.to_string()))
}
}
impl<E: Clone> Clone for Pipeline<E> {
fn clone(&self) -> Self {
Self {
engine: self.engine.clone(),
post_process: self.post_process,
}
}
}
impl<E: std::fmt::Debug> std::fmt::Debug for Pipeline<E> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Pipeline")
.field("engine", &self.engine)
.field("post_process", &"fn(_, _) -> Vec<_>")
.finish()
}
}