pub fn find_boundary(s: &str, max: usize) -> usize {
let max = max.min(s.len());
let mut end = max;
while end > 0 && !s.is_char_boundary(end) {
end -= 1;
}
end
}
pub fn truncate_bytes(s: &str, max: usize) -> &str {
if s.len() <= max {
return s;
}
let end = find_boundary(s, max);
&s[..end]
}
pub fn truncate_with_suffix(s: &str, max: usize) -> String {
if s.len() <= max {
return s.to_string();
}
let suffix = "...";
let suffix_len = suffix.len();
let end = find_boundary(s, max.saturating_sub(suffix_len));
format!("{}{}", &s[..end], suffix)
}
pub fn truncate_chars(s: &str, max_chars: usize) -> String {
let char_count = s.chars().count();
if char_count <= max_chars {
return s.to_string();
}
let suffix = "...";
let take_chars = max_chars.saturating_sub(suffix.chars().count());
s.chars().take(take_chars).collect::<String>() + suffix
}
pub fn truncate_string_in_place(s: &mut String, max: usize) {
if s.len() <= max {
return;
}
let end = find_boundary(s, max);
s.truncate(end);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_find_boundary_ascii() {
let s = "hello world";
assert_eq!(find_boundary(s, 5), 5);
assert_eq!(find_boundary(s, 100), 11);
}
#[test]
fn test_find_boundary_multibyte() {
let s = "你好世界";
assert_eq!(find_boundary(s, 4), 3); assert_eq!(find_boundary(s, 6), 6); assert_eq!(find_boundary(s, 7), 6); }
#[test]
fn test_truncate_bytes() {
let s = "hello";
assert_eq!(truncate_bytes(s, 10), "hello");
assert_eq!(truncate_bytes(s, 3), "hel");
}
#[test]
fn test_truncate_bytes_chinese() {
let s = "你好世界";
assert_eq!(truncate_bytes(s, 100), "你好世界");
assert_eq!(truncate_bytes(s, 5), "你"); }
#[test]
fn test_truncate_with_suffix() {
let s = "hello world";
assert_eq!(truncate_with_suffix(s, 100), "hello world");
assert_eq!(truncate_with_suffix(s, 8), "hello...");
assert_eq!(truncate_with_suffix(s, 5), "he...");
}
#[test]
fn test_truncate_chars() {
let s = "你好世界hello";
assert_eq!(truncate_chars(s, 10), "你好世界hello");
assert_eq!(truncate_chars(s, 4), "你...");
assert_eq!(truncate_chars(s, 6), "你好世...");
assert_eq!(truncate_chars(s, 7), "你好世界...");
}
#[test]
fn test_truncate_in_place() {
let mut s = "hello world".to_string();
truncate_string_in_place(&mut s, 5);
assert_eq!(s, "hello");
let mut s2 = "你好世界".to_string();
truncate_string_in_place(&mut s2, 5);
assert_eq!(s2, "你"); }
}