use redact_core::AnonymizationStrategy;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnalyzeRequest {
pub text: String,
#[serde(default = "default_language")]
pub language: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub entities: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub min_score: Option<f32>,
}
fn default_language() -> String {
"en".to_string()
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnalyzeResponse {
#[serde(skip_serializing_if = "Option::is_none")]
pub original_text: Option<String>,
pub results: Vec<EntityResult>,
pub metadata: AnalysisMetadata,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EntityResult {
pub entity_type: String,
pub start: usize,
pub end: usize,
pub score: f32,
#[serde(skip_serializing_if = "Option::is_none")]
pub text: Option<String>,
pub recognizer_name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnalysisMetadata {
pub recognizers_used: usize,
pub processing_time_ms: u64,
pub language: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub model_version: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnonymizeRequest {
pub text: String,
#[serde(default = "default_language")]
pub language: String,
#[serde(default)]
pub config: AnonymizationConfig,
#[serde(skip_serializing_if = "Option::is_none")]
pub entities: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnonymizationConfig {
#[serde(default)]
pub strategy: AnonymizationStrategy,
#[serde(default = "default_mask_char")]
pub mask_char: String,
#[serde(default)]
pub mask_start_chars: usize,
#[serde(default)]
pub mask_end_chars: usize,
#[serde(default)]
pub preserve_format: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub encryption_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub hash_salt: Option<String>,
}
impl Default for AnonymizationConfig {
fn default() -> Self {
Self {
strategy: AnonymizationStrategy::Replace,
mask_char: default_mask_char(),
mask_start_chars: 0,
mask_end_chars: 0,
preserve_format: false,
encryption_key: None,
hash_salt: None,
}
}
}
fn default_mask_char() -> String {
"*".to_string()
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnonymizeResponse {
pub text: String,
pub results: Vec<EntityResult>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tokens: Option<Vec<TokenInfo>>,
pub metadata: AnalysisMetadata,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TokenInfo {
pub token_id: String,
pub entity_type: String,
pub start: usize,
pub end: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub expires_at: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthResponse {
pub status: String,
pub version: String,
pub recognizers: usize,
pub entity_types: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ErrorResponse {
pub error: String,
pub message: String,
}
impl ErrorResponse {
pub fn new(error: impl Into<String>, message: impl Into<String>) -> Self {
Self {
error: error.into(),
message: message.into(),
}
}
}
impl From<redact_core::RecognizerResult> for EntityResult {
fn from(result: redact_core::RecognizerResult) -> Self {
Self {
entity_type: result.entity_type.as_str().to_string(),
start: result.start,
end: result.end,
score: result.score,
text: result.text,
recognizer_name: result.recognizer_name,
}
}
}
impl From<redact_core::AnalysisMetadata> for AnalysisMetadata {
fn from(metadata: redact_core::AnalysisMetadata) -> Self {
Self {
recognizers_used: metadata.recognizers_used,
processing_time_ms: metadata.processing_time_ms,
language: metadata.language,
model_version: metadata.model_version,
}
}
}
impl From<redact_core::Token> for TokenInfo {
fn from(token: redact_core::Token) -> Self {
Self {
token_id: token.token_id,
entity_type: token.entity_type.as_str().to_string(),
start: token.start,
end: token.end,
expires_at: token.expires_at.map(|dt| dt.to_rfc3339()),
}
}
}