use foundation::TokenId;
#[derive(Debug, Default)]
pub(crate) struct KvPrefix {
fed: Vec<TokenId>,
tainted: bool,
}
impl KvPrefix {
pub(crate) fn clear(&mut self) {
self.fed.clear();
self.tainted = false;
}
pub(crate) fn taint(&mut self) {
self.tainted = true;
}
pub(crate) fn record(&mut self, tokens: &[TokenId], pos0: usize) {
if pos0 != self.fed.len() {
if pos0 < self.fed.len() {
self.fed.truncate(pos0);
} else {
self.fed.clear();
self.tainted = true;
return;
}
}
self.fed.extend_from_slice(tokens);
}
pub(crate) fn rewind_to(&mut self, position: usize) {
if position < self.fed.len() {
self.fed.truncate(position);
}
}
pub(crate) fn common_prefix(&self, prompt_ids: &[TokenId]) -> usize {
if self.tainted || self.fed.is_empty() || prompt_ids.is_empty() {
return 0;
}
let ceiling = self.fed.len().min(prompt_ids.len() - 1);
(0..ceiling)
.take_while(|&i| self.fed[i] == prompt_ids[i])
.count()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn built(ids: &[TokenId]) -> KvPrefix {
let mut p = KvPrefix::default();
p.record(ids, 0);
p
}
#[test]
fn a_strict_prefix_reports_its_whole_length() {
assert_eq!(built(&[1, 2, 3]).common_prefix(&[1, 2, 3, 4]), 3);
}
#[test]
fn divergence_truncates_rather_than_refusing() {
assert_eq!(
built(&[1, 2, 3, 9, 9]).common_prefix(&[1, 2, 3, 7, 7, 8]),
3
);
assert_eq!(built(&[1, 2, 3]).common_prefix(&[9, 2, 3, 4]), 0);
}
#[test]
fn at_least_one_token_is_always_left_to_feed() {
assert_eq!(built(&[1, 2, 3]).common_prefix(&[1, 2, 3]), 2);
assert_eq!(built(&[1, 2, 3]).common_prefix(&[1, 2]), 1);
assert_eq!(built(&[1]).common_prefix(&[1]), 0);
}
#[test]
fn taint_refuses_everything_and_only_clear_lifts_it() {
let mut p = built(&[1, 2, 3]);
p.taint();
p.record(&[4], 3);
assert_eq!(p.common_prefix(&[1, 2, 3, 4, 5]), 0);
p.clear();
p.record(&[1, 2, 3], 0);
assert_eq!(p.common_prefix(&[1, 2, 3, 4]), 3);
}
#[test]
fn a_gap_in_the_positions_taints_rather_than_claiming_coverage() {
let mut p = built(&[1, 2, 3]);
p.record(&[9], 5);
assert_eq!(p.common_prefix(&[1, 2, 3, 9, 0, 0, 7]), 0);
}
#[test]
fn re_recording_over_the_same_span_replaces_it() {
let mut p = built(&[1, 2, 3]);
p.record(&[7, 8], 1);
assert_eq!(p.common_prefix(&[1, 7, 8, 4]), 3);
}
#[test]
fn a_rewind_shortens_what_is_reusable() {
let mut p = built(&[1, 2, 3, 4]);
p.rewind_to(2);
assert_eq!(p.common_prefix(&[1, 2, 3, 4]), 2);
p.rewind_to(99);
assert_eq!(p.common_prefix(&[1, 2, 3, 4]), 2);
}
#[test]
fn an_empty_record_reuses_nothing() {
assert_eq!(KvPrefix::default().common_prefix(&[1, 2, 3]), 0);
assert_eq!(built(&[1, 2, 3]).common_prefix(&[]), 0);
}
}