aster_forge_utils/
text.rs1pub fn char_count(value: &str) -> usize {
14 value.chars().count()
15}
16
17pub fn truncate_utf8_to_max_bytes(value: &str, max_bytes: usize) -> String {
22 if value.len() <= max_bytes {
23 return value.to_string();
24 }
25
26 let mut end = max_bytes;
27 while end > 0 && !value.is_char_boundary(end) {
28 end -= 1;
29 }
30 value[..end].to_string()
31}
32
33#[cfg(test)]
34mod tests {
35 use super::{char_count, truncate_utf8_to_max_bytes};
36
37 #[test]
38 fn char_count_counts_unicode_scalars() {
39 assert_eq!(char_count("Aster"), 5);
40 assert_eq!(char_count("你好世界"), 4);
41 assert_eq!(char_count("e\u{301}"), 2);
42 }
43
44 #[test]
45 fn truncate_utf8_to_max_bytes_keeps_short_ascii_unchanged() {
46 assert_eq!(
47 truncate_utf8_to_max_bytes("AsterYggdrasil", 32),
48 "AsterYggdrasil"
49 );
50 }
51
52 #[test]
53 fn truncate_utf8_to_max_bytes_truncates_ascii_by_bytes() {
54 assert_eq!(truncate_utf8_to_max_bytes("AsterYggdrasil", 5), "Aster");
55 }
56
57 #[test]
58 fn truncate_utf8_to_max_bytes_preserves_char_boundaries() {
59 assert_eq!(truncate_utf8_to_max_bytes("你好世界", 7), "你好");
60 assert_eq!(truncate_utf8_to_max_bytes("éclair", 1), "");
61 assert_eq!(truncate_utf8_to_max_bytes("éclair", 2), "é");
62 }
63
64 #[test]
65 fn truncate_utf8_to_max_bytes_handles_zero_limit() {
66 assert_eq!(truncate_utf8_to_max_bytes("AsterYggdrasil", 0), "");
67 assert_eq!(truncate_utf8_to_max_bytes("你好", 0), "");
68 }
69}