Signed-off-by: toyamagu2021@gmail.com <toyamagu2021@gmail.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/// Safely truncate a string at character boundaries, not byte boundaries
|
||||
///
|
||||
/// This function ensures that multi-byte UTF-8 characters (like Japanese, emoji, etc.)
|
||||
/// are not split in the middle, which would cause a panic.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `s` - The string to truncate
|
||||
/// * `max_chars` - Maximum number of characters to keep
|
||||
///
|
||||
/// # Returns
|
||||
/// A truncated string with "..." appended if truncation occurred
|
||||
pub fn safe_truncate(s: &str, max_chars: usize) -> String {
|
||||
if s.chars().count() <= max_chars {
|
||||
s.to_string()
|
||||
} else {
|
||||
let truncated: String = s.chars().take(max_chars.saturating_sub(3)).collect();
|
||||
format!("{}...", truncated)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_safe_truncate_ascii() {
|
||||
assert_eq!(safe_truncate("hello world", 20), "hello world");
|
||||
assert_eq!(safe_truncate("hello world", 8), "hello...");
|
||||
assert_eq!(safe_truncate("hello", 5), "hello");
|
||||
assert_eq!(safe_truncate("hello", 3), "...");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_safe_truncate_japanese() {
|
||||
// Japanese characters: "こんにちは世界" (Hello World)
|
||||
let japanese = "こんにちは世界";
|
||||
assert_eq!(safe_truncate(japanese, 10), japanese);
|
||||
assert_eq!(safe_truncate(japanese, 5), "こん...");
|
||||
assert_eq!(safe_truncate(japanese, 7), japanese);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_safe_truncate_mixed() {
|
||||
// Mixed ASCII and Japanese
|
||||
let mixed = "Hello こんにちは";
|
||||
assert_eq!(safe_truncate(mixed, 20), mixed);
|
||||
assert_eq!(safe_truncate(mixed, 8), "Hello...");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user