pub fn stop_prefix_holdback(text: &str, stop_strs: &[String]) -> usize {
let bytes = text.as_bytes();
let longest = stop_strs
.iter()
.map(|s| s.len().saturating_sub(1))
.max()
.unwrap_or(0);
let max_k = longest.min(bytes.len());
(1..=max_k)
.rev()
.find(|&k| {
let tail = &bytes[bytes.len() - k..];
stop_strs
.iter()
.any(|s| s.len() > k && s.as_bytes().starts_with(tail))
})
.unwrap_or(0)
}
pub fn floor_char_boundary(text: &str, at: usize) -> usize {
let mut idx = at.min(text.len());
while idx > 0 && !text.is_char_boundary(idx) {
idx -= 1;
}
idx
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn holdback_covers_only_proper_prefixes() {
let stops = vec!["<|end|>".to_string(), "STOP".to_string()];
assert_eq!(stop_prefix_holdback("hello <|en", &stops), 4);
assert_eq!(stop_prefix_holdback("hello ST", &stops), 2);
assert_eq!(stop_prefix_holdback("hello", &stops), 0);
assert_eq!(stop_prefix_holdback("hello STOP", &stops), 0);
}
#[test]
fn a_split_point_is_floored_to_a_char_boundary() {
let text = "hi \u{e9}";
assert_eq!(floor_char_boundary(text, text.len()), text.len());
assert_eq!(floor_char_boundary(text, 4), 3);
assert_eq!(floor_char_boundary(text, 0), 0);
assert_eq!(floor_char_boundary(text, 99), text.len());
}
}