use serde::{Deserialize, Serialize};
use crate::error::EngineError;
use crate::types::{DetectionSource, Entity, Span};
pub struct TierB {
analyzer_url: String,
client: reqwest::Client,
}
#[derive(Serialize)]
struct AnalyzeRequest<'a> {
text: &'a str,
language: &'a str,
}
#[derive(Deserialize)]
struct AnalyzeResponseItem {
entity_type: String,
start: usize,
end: usize,
score: f32,
}
const DEFAULT_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5);
pub const ANALYZER_URL_ENV: &str = "PRESIDIO_ANALYZER_URL";
impl TierB {
pub fn new(analyzer_url: impl Into<String>) -> Self {
Self {
analyzer_url: analyzer_url.into(),
client: reqwest::Client::builder()
.timeout(DEFAULT_TIMEOUT)
.build()
.expect("static timeout-only client config is always valid"),
}
}
pub fn from_env() -> Self {
let url =
std::env::var(ANALYZER_URL_ENV).unwrap_or_else(|_| "http://localhost:5002".to_string());
Self::new(url)
}
pub fn with_timeout(mut self, timeout: std::time::Duration) -> Self {
self.client = reqwest::Client::builder()
.timeout(timeout)
.build()
.expect("static timeout-only client config is always valid");
self
}
pub async fn analyze(&self, text: &str, language: &str) -> Result<Vec<Entity>, EngineError> {
let response: Vec<AnalyzeResponseItem> = self
.client
.post(format!("{}/analyze", self.analyzer_url))
.json(&AnalyzeRequest { text, language })
.send()
.await?
.json()
.await?;
Ok(response
.into_iter()
.map(|item| Entity {
entity_type: item.entity_type,
span: Span {
start: item.start,
end: item.end,
},
score: item.score,
bbox: None,
source: DetectionSource::TierB,
})
.collect())
}
}