use crate::core::change::ChangeType;
use crate::core::fact::StoredFact;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IngestionOutcome {
pub created: Vec<String>,
pub updated: Vec<String>,
pub consolidated: Vec<String>,
pub operations: Vec<FactOperation>,
}
impl IngestionOutcome {
pub fn new() -> Self {
Self {
created: Vec::new(),
updated: Vec::new(),
consolidated: Vec::new(),
operations: Vec::new(),
}
}
pub fn add_created(&mut self, fact_id: String, operation: FactOperation) {
self.created.push(fact_id.clone());
self.operations.push(operation);
}
pub fn add_updated(&mut self, fact_id: String, operation: FactOperation) {
self.updated.push(fact_id.clone());
self.operations.push(operation);
}
pub fn add_consolidated(&mut self, fact_id: String, operation: FactOperation) {
self.consolidated.push(fact_id.clone());
self.operations.push(operation);
}
pub fn is_empty(&self) -> bool {
self.created.is_empty() && self.updated.is_empty() && self.consolidated.is_empty()
}
}
impl Default for IngestionOutcome {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RetrievalResult {
pub facts: Vec<StoredFact>,
pub total_matches: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub related: Option<Vec<StoredFact>>,
}
impl RetrievalResult {
pub fn new(facts: Vec<StoredFact>) -> Self {
let total_matches = facts.len();
Self {
facts,
total_matches,
related: None,
}
}
pub fn with_related(mut self, related: Vec<StoredFact>) -> Self {
self.related = Some(related);
self
}
pub fn with_total(mut self, total: usize) -> Self {
self.total_matches = total;
self
}
}
impl IntoIterator for RetrievalResult {
type Item = StoredFact;
type IntoIter = std::vec::IntoIter<StoredFact>;
fn into_iter(self) -> Self::IntoIter {
self.facts.into_iter()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModificationResult {
pub fact_id: String,
pub previous_content: String,
pub new_content: String,
pub timestamp: chrono::DateTime<chrono::Utc>,
}
impl ModificationResult {
pub fn new(
fact_id: impl Into<String>,
previous_content: impl Into<String>,
new_content: impl Into<String>,
) -> Self {
Self {
fact_id: fact_id.into(),
previous_content: previous_content.into(),
new_content: new_content.into(),
timestamp: chrono::Utc::now(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FactOperation {
pub fact_id: String,
pub content: String,
pub change_type: ChangeType,
#[serde(skip_serializing_if = "Option::is_none")]
pub previous_content: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub actor_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub role: Option<String>,
}
impl FactOperation {
pub fn new(
fact_id: impl Into<String>,
content: impl Into<String>,
change_type: ChangeType,
) -> Self {
Self {
fact_id: fact_id.into(),
content: content.into(),
change_type,
previous_content: None,
actor_id: None,
role: None,
}
}
pub fn with_previous_content(mut self, previous: impl Into<String>) -> Self {
self.previous_content = Some(previous.into());
self
}
pub fn with_actor_id(mut self, actor_id: impl Into<String>) -> Self {
self.actor_id = Some(actor_id.into());
self
}
pub fn with_role(mut self, role: impl Into<String>) -> Self {
self.role = Some(role.into());
self
}
}