use std::path::Path;
use super::stores::StoreAdmission;
use crate::core::consolidation::{CacheableProviderResult, ConsolidationArtifacts};
use crate::core::content_chunk::ContentChunk;
use crate::core::graph_index::IndexEdge;
use crate::core::knowledge_provider_extract::ExtractedFact;
#[must_use]
pub fn admit_chunk(chunk: &ContentChunk, admission: &StoreAdmission) -> Option<ContentChunk> {
let content = admission.admit(&chunk.content, Path::new(&chunk.file_path))?;
let symbol_name = admission.admit_text(&chunk.symbol_name)?;
let references = chunk
.references
.iter()
.map(|reference| admission.admit_text(reference))
.collect::<Option<Vec<_>>>()?;
let metadata = match &chunk.metadata {
Some(metadata) => Some(admit_json(metadata, admission)?),
None => None,
};
let mut admitted = chunk.clone();
if content != chunk.content {
admitted.tokens = crate::core::bm25_index::tokenize_for_index(&content);
admitted.token_count = admitted.tokens.len();
admitted.content = content;
}
admitted.symbol_name = symbol_name;
admitted.references = references;
admitted.metadata = metadata;
Some(admitted)
}
#[must_use]
pub fn admit_artifacts(
artifacts: &ConsolidationArtifacts,
admission: &StoreAdmission,
) -> (ConsolidationArtifacts, usize) {
let mut dropped = 0usize;
let bm25_chunks = admit_all(&artifacts.bm25_chunks, &mut dropped, |chunk| {
admit_chunk(chunk, admission)
});
let edges = admit_all(&artifacts.edges, &mut dropped, |edge| {
admit_edge(edge, admission)
});
let facts = admit_all(&artifacts.facts, &mut dropped, |fact| {
admit_fact(fact, admission)
});
let cache_entries = admit_all(&artifacts.cache_entries, &mut dropped, |entry| {
admit_cache_entry(entry, admission)
});
(
ConsolidationArtifacts {
bm25_chunks,
edges,
facts,
cache_entries,
},
dropped,
)
}
fn admit_all<T>(items: &[T], dropped: &mut usize, admit: impl Fn(&T) -> Option<T>) -> Vec<T> {
let admitted: Vec<T> = items.iter().filter_map(admit).collect();
*dropped += items.len() - admitted.len();
admitted
}
fn admit_edge(edge: &IndexEdge, admission: &StoreAdmission) -> Option<IndexEdge> {
Some(IndexEdge {
from: admission.admit_text(&edge.from)?,
to: admission.admit_text(&edge.to)?,
kind: edge.kind.clone(),
weight: edge.weight,
})
}
fn admit_fact(fact: &ExtractedFact, admission: &StoreAdmission) -> Option<ExtractedFact> {
Some(ExtractedFact {
origin: fact.origin.clone(),
category: admission.admit_text(&fact.category)?,
key: admission.admit_text(&fact.key)?,
value: admission.admit_text(&fact.value)?,
confidence: fact.confidence,
})
}
fn admit_cache_entry(
entry: &CacheableProviderResult,
admission: &StoreAdmission,
) -> Option<CacheableProviderResult> {
let content = admission.admit(&entry.content, Path::new(&entry.uri))?;
let token_count = if content == entry.content {
entry.token_count
} else {
crate::core::tokens::count_tokens(&content)
};
Some(CacheableProviderResult {
uri: admission.admit_text(&entry.uri)?,
content,
token_count,
})
}
fn admit_json(value: &serde_json::Value, admission: &StoreAdmission) -> Option<serde_json::Value> {
let text = serde_json::to_string(value).ok()?;
let admitted = admission.admit_text(&text)?;
if admitted == text {
return Some(value.clone());
}
serde_json::from_str(&admitted).ok()
}