use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ExtractContactRequest {
pub message_ids: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtractContactResponse {
pub contacts: HashMap<String, Vec<ExtractedContact>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtractedContact {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub phone: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub company: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub address: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub confidence: Option<f64>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ExtractSignatureRequest {
pub message_ids: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parse_contacts: Option<bool>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtractSignatureResponse {
pub signatures: HashMap<String, ExtractedSignature>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtractedSignature {
pub text: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub contact: Option<ExtractedContact>,
#[serde(skip_serializing_if = "Option::is_none")]
pub confidence: Option<f64>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ExtractOrderRequest {
pub message_ids: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtractOrderResponse {
pub orders: HashMap<String, Vec<ExtractedOrder>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtractedOrder {
#[serde(skip_serializing_if = "Option::is_none")]
pub order_number: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub order_date: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub total: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub currency: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub merchant: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub items: Option<Vec<OrderItem>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub shipping: Option<ShippingInfo>,
#[serde(skip_serializing_if = "Option::is_none")]
pub confidence: Option<f64>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct OrderItem {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub quantity: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub price: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub total: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sku: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ShippingInfo {
#[serde(skip_serializing_if = "Option::is_none")]
pub tracking_number: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub carrier: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub address: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub delivery_date: Option<i64>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ExtractEntitiesRequest {
pub message_ids: Vec<String>,
pub entity_types: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtractEntitiesResponse {
pub entities: HashMap<String, Vec<ExtractedEntity>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtractedEntity {
pub entity_type: String,
pub value: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub text: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub position: Option<EntityPosition>,
#[serde(skip_serializing_if = "Option::is_none")]
pub confidence: Option<f64>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EntityPosition {
pub start: usize,
pub end: usize,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_extract_contact_request() {
let request = ExtractContactRequest {
message_ids: vec!["msg_123".to_string()],
};
let json = serde_json::to_string(&request).unwrap();
let deserialized: ExtractContactRequest = serde_json::from_str(&json).unwrap();
assert_eq!(request, deserialized);
}
#[test]
fn test_extracted_contact() {
let contact = ExtractedContact {
name: Some("John Doe".to_string()),
email: Some("john@example.com".to_string()),
phone: Some("+1-555-0100".to_string()),
company: Some("Acme Corp".to_string()),
title: Some("CEO".to_string()),
address: Some("123 Main St".to_string()),
confidence: Some(0.95),
};
let json = serde_json::to_string(&contact).unwrap();
let deserialized: ExtractedContact = serde_json::from_str(&json).unwrap();
assert_eq!(contact, deserialized);
}
#[test]
fn test_extract_signature_request() {
let request = ExtractSignatureRequest {
message_ids: vec!["msg_123".to_string()],
parse_contacts: Some(true),
};
let json = serde_json::to_string(&request).unwrap();
let deserialized: ExtractSignatureRequest = serde_json::from_str(&json).unwrap();
assert_eq!(request, deserialized);
}
#[test]
fn test_extracted_order() {
let order = ExtractedOrder {
order_number: Some("ORD-12345".to_string()),
order_date: Some(1735689600),
total: Some(99.99),
currency: Some("USD".to_string()),
merchant: Some("Example Store".to_string()),
status: Some("shipped".to_string()),
items: Some(vec![OrderItem {
name: "Product A".to_string(),
quantity: Some(2),
price: Some(49.99),
total: Some(99.98),
sku: Some("SKU-001".to_string()),
}]),
shipping: Some(ShippingInfo {
tracking_number: Some("1Z999AA10123456784".to_string()),
carrier: Some("UPS".to_string()),
address: Some("456 Oak Ave".to_string()),
delivery_date: Some(1735776000),
}),
confidence: Some(0.92),
};
let json = serde_json::to_string(&order).unwrap();
let deserialized: ExtractedOrder = serde_json::from_str(&json).unwrap();
assert_eq!(order, deserialized);
}
#[test]
fn test_extract_entities_request() {
let request = ExtractEntitiesRequest {
message_ids: vec!["msg_123".to_string()],
entity_types: vec!["date".to_string(), "location".to_string()],
};
let json = serde_json::to_string(&request).unwrap();
let deserialized: ExtractEntitiesRequest = serde_json::from_str(&json).unwrap();
assert_eq!(request, deserialized);
}
#[test]
fn test_extracted_entity() {
let entity = ExtractedEntity {
entity_type: "date".to_string(),
value: "2025-01-01".to_string(),
text: Some("January 1st, 2025".to_string()),
position: Some(EntityPosition { start: 10, end: 27 }),
confidence: Some(0.98),
};
let json = serde_json::to_string(&entity).unwrap();
let deserialized: ExtractedEntity = serde_json::from_str(&json).unwrap();
assert_eq!(entity, deserialized);
}
}