msg_tool\utils/
str.rs

1//! String Utilities
2use crate::types::*;
3use crate::utils::encoding::*;
4use anyhow::Result;
5use unicode_segmentation::UnicodeSegmentation;
6
7/// Truncate a string to a specified length, encoding it with the given encoding.
8/// Output size may less than or equal to the specified length.
9pub fn truncate_string(s: &str, length: usize, encoding: Encoding, check: bool) -> Result<Vec<u8>> {
10    let vec: Vec<_> = UnicodeSegmentation::graphemes(s, true).collect();
11    let mut result = Vec::new();
12    for graphemes in vec {
13        let data = encode_string(encoding, graphemes, check)?;
14        if result.len() + data.len() > length {
15            break;
16        }
17        result.extend(data);
18    }
19    return Ok(result);
20}
21
22/// Truncate a string to a specified length, encoding it with the given encoding.
23/// Output size may less than or equal to the specified length.
24/// Returns the encoded bytes and the remaining string.
25pub fn truncate_string2(
26    s: &str,
27    length: usize,
28    encoding: Encoding,
29) -> Result<(Vec<u8>, Option<&str>)> {
30    let vec: Vec<_> = UnicodeSegmentation::graphemes(s, true).collect();
31    let mut result = Vec::new();
32    let mut used = 0;
33    for graphemes in vec {
34        let data = encode_string(encoding, graphemes, false)?;
35        if result.len() + data.len() > length {
36            break;
37        }
38        result.extend(data);
39        used += graphemes.len();
40    }
41    let remaining = if used < s.len() {
42        Some(&s[used..])
43    } else {
44        None
45    };
46    return Ok((result, remaining));
47}
48
49/// Truncate a string to a specified length, encoding it with the given encoding.
50/// Output size may less than or equal to the specified length.
51/// Returns the encoded bytes and the remaining string.
52/// Will try splitting at line breaks first.
53pub fn truncate_string_with_enter(
54    s: &str,
55    length: usize,
56    encoding: Encoding,
57) -> Result<(Vec<u8>, Option<&str>)> {
58    if let Some(pos) = s.find('\n') {
59        let (first, rest) = s.split_at(pos + 1);
60        // Try encoding the first part with line break
61        let data = encode_string(encoding, &first[..pos], false)?;
62        if data.len() <= length {
63            return Ok((data, if rest.is_empty() { None } else { Some(rest) }));
64        }
65    }
66    truncate_string2(s, length, encoding)
67}