pub fn formatted_truncate(content: &str, max_bytes: usize) -> String {
if content.len() <= max_bytes {
return content.to_string();
}
let total_lines = content.lines().count();
let truncated = truncate_middle(content, max_bytes);
format!(
"[TRUNCATED: total lines: {}]\n{}\n[... middle truncated to fit budget ...]\n{}",
total_lines, truncated.head, truncated.tail
)
}
pub struct TruncatedOutput {
pub head: String,
pub tail: String,
}
pub fn truncate_middle(content: &str, max_bytes: usize) -> TruncatedOutput {
if content.len() <= max_bytes {
return TruncatedOutput {
head: content.to_string(),
tail: String::new(),
};
}
let head_size = (max_bytes as f32 * 0.4) as usize;
let tail_size = (max_bytes as f32 * 0.4) as usize;
let head_boundary = find_valid_boundary_forward(content, head_size);
let tail_boundary = find_valid_boundary_backward(content, content.len() - tail_size);
TruncatedOutput {
head: content[..head_boundary].to_string(),
tail: content[tail_boundary..].to_string(),
}
}
pub fn safe_head(s: &str, max_bytes: usize) -> &str {
let end = find_valid_boundary_forward(s, max_bytes.min(s.len()));
&s[..end]
}
pub fn safe_tail(s: &str, max_bytes: usize) -> &str {
if s.len() <= max_bytes {
return s;
}
let offset = s.len() - max_bytes;
let start = (offset..=s.len())
.find(|&i| s.is_char_boundary(i))
.unwrap_or(s.len());
&s[start..]
}
fn find_valid_boundary_forward(content: &str, target: usize) -> usize {
let mut pos = target;
while pos > 0 && !content.is_char_boundary(pos) {
pos -= 1;
}
pos
}
fn find_valid_boundary_backward(content: &str, target: usize) -> usize {
let mut pos = target;
while pos < content.len() && !content.is_char_boundary(pos) {
pos += 1;
}
pos
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_middle_truncation() {
let input = "1234567890";
let result = truncate_middle(input, 4);
assert_eq!(result.head, "1");
assert_eq!(result.tail, "0");
}
#[test]
fn test_utf8_boundary_safety() {
let input = "π¦π¦π¦π¦π¦"; let result = truncate_middle(input, 10);
assert_eq!(result.head, "π¦");
assert_eq!(result.tail, "π¦");
}
}