use crate::core::errors::OCRError;
use image::RgbImage;
use std::path::Path;
pub trait Sampler<T> {
type BatchData;
fn sample(&self, data: Vec<T>) -> Vec<Self::BatchData>;
fn sample_slice(&self, data: &[T]) -> Vec<Self::BatchData>
where
T: Clone,
{
self.sample(data.to_vec())
}
fn sample_iter<I>(&self, data: I) -> Vec<Self::BatchData>
where
I: IntoIterator<Item = T>,
{
self.sample(data.into_iter().collect())
}
}
pub trait ImageReader {
type Error;
fn apply<P: AsRef<Path> + Send + Sync>(
&self,
imgs: impl IntoIterator<Item = P>,
) -> Result<Vec<RgbImage>, Self::Error>;
fn read_single<P: AsRef<Path> + Send + Sync>(
&self,
img_path: P,
) -> Result<RgbImage, Self::Error>
where
Self::Error: From<OCRError>,
{
let mut results = self.apply(std::iter::once(img_path))?;
results.pop().ok_or_else(|| {
OCRError::invalid_input("ImageReader::apply returned empty result for single image")
.into()
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::OCRError;
use image::RgbImage;
use std::path::Path;
struct MockEmptyImageReader;
impl ImageReader for MockEmptyImageReader {
type Error = OCRError;
fn apply<P: AsRef<Path> + Send + Sync>(
&self,
_imgs: impl IntoIterator<Item = P>,
) -> Result<Vec<RgbImage>, Self::Error> {
Ok(Vec::new())
}
}
#[test]
fn test_read_single_handles_empty_result_properly() {
let reader = MockEmptyImageReader;
let result = reader.read_single("test_path.jpg");
assert!(result.is_err());
let err = result.unwrap_err();
if let OCRError::InvalidInput { message } = err {
assert!(message.contains("ImageReader::apply returned empty result for single image"));
} else {
panic!("Expected InvalidInput error, got {:?}", err);
}
}
}