use std::collections::HashMap;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use std::sync::Mutex;
use crate::core::config::{Config, ProseRanker};
use crate::core::extractive::{self, RankMode};
use crate::core::web::distill::squeeze_prose;
const MEMO_CAP: usize = 8192;
static MEMO: Mutex<Option<HashMap<u64, String>>> = Mutex::new(None);
#[must_use]
pub fn squeeze(content: &str, budget: usize) -> String {
let ranker = Config::load().proxy.resolved_prose_ranker();
if ranker == ProseRanker::Truncate {
return squeeze_prose(content, budget);
}
let key = memo_key(content, budget);
if let Some(hit) = memo_get(key) {
return hit;
}
let out = compute(content, budget);
memo_put(key, &out);
out
}
fn compute(content: &str, budget: usize) -> String {
if let Some(ranked) = extractive::rank_and_squeeze(content, budget, RankMode::Centrality, None)
{
return ranked;
}
squeeze_prose(content, budget)
}
fn memo_key(content: &str, budget: usize) -> u64 {
let mut h = DefaultHasher::new();
content.hash(&mut h);
budget.hash(&mut h);
h.finish()
}
fn memo_get(key: u64) -> Option<String> {
let guard = MEMO.lock().ok()?;
guard.as_ref()?.get(&key).cloned()
}
fn memo_put(key: u64, value: &str) {
if let Ok(mut guard) = MEMO.lock() {
let map = guard.get_or_insert_with(HashMap::new);
if map.len() >= MEMO_CAP {
map.clear();
}
map.insert(key, value.to_string());
}
}
#[cfg(test)]
mod tests {
use super::*;
fn long_unique_prose() -> String {
(0..50)
.map(|i| format!("Distinct sentence number {i} about handling case {i} carefully."))
.collect::<Vec<_>>()
.join(" ")
}
#[test]
fn squeeze_is_stable_across_calls() {
let _lock = crate::core::data_dir::test_env_lock();
crate::test_env::remove_var("LEAN_CTX_PROXY_PROSE_RANKER");
let text = long_unique_prose();
let a = squeeze(&text, 200);
let b = squeeze(&text, 200);
assert_eq!(a, b, "wire squeeze must be byte-stable across turns");
assert!(a.len() <= text.len());
}
#[test]
fn truncate_mode_bypasses_memo_and_matches_squeeze_prose() {
let _lock = crate::core::data_dir::test_env_lock();
crate::test_env::set_var("LEAN_CTX_PROXY_PROSE_RANKER", "truncate");
let text = long_unique_prose();
assert_eq!(squeeze(&text, 200), squeeze_prose(&text, 200));
crate::test_env::remove_var("LEAN_CTX_PROXY_PROSE_RANKER");
}
}