pub fn chunk_text(text: &str, max_chars: usize, overlap: usize) -> Vec<String> {
if text.trim().is_empty() {
return vec![];
}
if max_chars == 0 {
return vec![text.to_string()];
}
let mut chunks = Vec::new();
let chars: Vec<char> = text.chars().collect();
let mut start = 0;
while start < chars.len() {
let end = (start + max_chars).min(chars.len());
let chunk: String = chars[start..end].iter().collect();
chunks.push(chunk);
if end == chars.len() {
break;
}
start += max_chars - overlap.min(max_chars - 1);
}
chunks
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_short_text_is_one_chunk() {
let text = "Hello world.";
let chunks = chunk_text(text, 100, 10);
assert_eq!(chunks.len(), 1);
assert_eq!(chunks[0], text);
}
#[test]
fn test_long_text_splits() {
let text = "abcdefghij"; let chunks = chunk_text(text, 4, 2);
assert_eq!(chunks.len(), 4);
assert_eq!(chunks[0], "abcd");
assert_eq!(chunks[1], "cdef");
assert_eq!(chunks[2], "efgh");
assert_eq!(chunks[3], "ghij");
}
#[test]
fn test_zero_overlap_abuts() {
let text = "abcdefgh"; let chunks = chunk_text(text, 4, 0);
assert_eq!(chunks.len(), 2);
assert_eq!(chunks[0], "abcd");
assert_eq!(chunks[1], "efgh");
}
}