use std::sync::Arc;
use rapid_structure_rs::{
EngineConfig, OcrEngine, OcrOutput, OcrRequest, PipelineProviderResolutions, RapidOcrEngine,
RapidOcrError, ResolvedExecutionProvider,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub(super) struct BackendProvider {
pub selected_ep: String,
pub fallback_to_cpu: bool,
}
pub(super) trait OcrBackend: Send {
fn recognize(&mut self, request: OcrRequest) -> Result<OcrOutput, RapidOcrError>;
fn provider(&self) -> BackendProvider;
}
pub(super) type EngineFactory =
Arc<dyn Fn(&EngineConfig) -> Result<Box<dyn OcrBackend>, RapidOcrError> + Send + Sync>;
pub(super) fn real_engine_factory() -> EngineFactory {
Arc::new(|config| Ok(Box::new(RealEngine::new(config)?)))
}
struct RealEngine(RapidOcrEngine);
impl RealEngine {
fn new(config: &EngineConfig) -> Result<Self, RapidOcrError> {
Ok(Self(RapidOcrEngine::new(config.clone())?))
}
fn resolutions(&self) -> PipelineProviderResolutions {
self.0.provider_resolutions()
}
}
impl OcrBackend for RealEngine {
fn recognize(&mut self, request: OcrRequest) -> Result<OcrOutput, RapidOcrError> {
OcrEngine::recognize(&mut self.0, request)
}
fn provider(&self) -> BackendProvider {
let resolutions = self.resolutions();
let primary = resolutions.rec;
debug_assert_eq!(
resolutions.det.selected_ep, primary.selected_ep,
"detector and recognizer must resolve to the same execution provider"
);
debug_assert_eq!(
resolutions.det.fallback_used, primary.fallback_used,
"detector and recognizer must agree on the fallback decision"
);
BackendProvider {
selected_ep: provider_label(primary.selected_ep),
fallback_to_cpu: primary.fallback_used,
}
}
}
pub(super) fn provider_label(provider: ResolvedExecutionProvider) -> String {
match provider {
ResolvedExecutionProvider::Cpu => "cpu".to_string(),
ResolvedExecutionProvider::Cuda => "cuda".to_string(),
ResolvedExecutionProvider::DirectMl => "directml".to_string(),
}
}
#[cfg(test)]
mod tests {
use super::provider_label;
use rapid_structure_rs::ResolvedExecutionProvider;
#[test]
fn every_execution_provider_has_a_stable_label() {
assert_eq!(provider_label(ResolvedExecutionProvider::Cpu), "cpu");
assert_eq!(provider_label(ResolvedExecutionProvider::Cuda), "cuda");
assert_eq!(
provider_label(ResolvedExecutionProvider::DirectMl),
"directml"
);
}
}