use std::path::PathBuf;
use serde::{Deserialize, Serialize};
use car_vision::ocr::{self, OcrConfig};
use car_vision::Observation;
#[derive(Debug, Deserialize)]
pub struct OcrArgs {
pub image_path: String,
#[serde(default)]
pub fast_path: bool,
#[serde(default)]
pub languages: Vec<String>,
#[serde(default = "default_true")]
pub language_correction: bool,
#[serde(default)]
pub minimum_text_height: f32,
}
fn default_true() -> bool {
true
}
#[derive(Debug, Serialize)]
pub struct OcrResponseJson {
pub available: bool,
pub observations: Vec<Observation>,
}
pub async fn ocr(args_json: &str) -> Result<String, String> {
let args: OcrArgs =
serde_json::from_str(args_json).map_err(|e| format!("invalid args: {e}"))?;
let config = OcrConfig {
fast_path: args.fast_path,
languages: args.languages,
language_correction: args.language_correction,
minimum_text_height: args.minimum_text_height,
};
let path = PathBuf::from(&args.image_path);
let response = if !car_vision::is_available() {
OcrResponseJson {
available: false,
observations: Vec::new(),
}
} else {
let observations = tokio::task::spawn_blocking(move || ocr::recognize(&path, &config))
.await
.map_err(|e| format!("ocr task panicked: {e}"))?
.map_err(|e| format!("{e}"))?;
OcrResponseJson {
available: true,
observations,
}
};
serde_json::to_string(&response).map_err(|e| format!("serialize: {e}"))
}