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