mcfly/
fixed_length_grapheme_string.rs

1use std::io::Write;
2use unicode_segmentation::UnicodeSegmentation;
3
4#[derive(Debug)]
5pub struct FixedLengthGraphemeString {
6    pub string: String,
7    pub grapheme_length: u16,
8    pub max_grapheme_length: u16,
9}
10
11impl Write for FixedLengthGraphemeString {
12    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
13        let s = String::from_utf8(buf.to_vec()).unwrap();
14        self.push_str(&s);
15        Ok(s.len())
16    }
17
18    fn flush(&mut self) -> std::io::Result<()> {
19        Ok(())
20    }
21}
22
23impl FixedLengthGraphemeString {
24    #[must_use]
25    pub fn empty(max_grapheme_length: u16) -> FixedLengthGraphemeString {
26        FixedLengthGraphemeString {
27            string: String::new(),
28            grapheme_length: 0,
29            max_grapheme_length,
30        }
31    }
32
33    pub fn new<S: Into<String>>(s: S, max_grapheme_length: u16) -> FixedLengthGraphemeString {
34        let mut fixed_length_grapheme_string =
35            FixedLengthGraphemeString::empty(max_grapheme_length);
36        fixed_length_grapheme_string.push_grapheme_str(s);
37        fixed_length_grapheme_string
38    }
39
40    pub fn push_grapheme_str<S: Into<String>>(&mut self, s: S) {
41        for grapheme in s.into().graphemes(true) {
42            if self.grapheme_length >= self.max_grapheme_length {
43                return;
44            }
45            self.string.push_str(grapheme);
46            self.grapheme_length += 1;
47        }
48    }
49
50    pub fn push_str(&mut self, s: &str) {
51        self.string.push_str(s);
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::FixedLengthGraphemeString;
58
59    #[test]
60    fn length_works() {
61        let input = FixedLengthGraphemeString::new("こんにちは世界", 20);
62        assert_eq!(input.grapheme_length, 7);
63    }
64
65    #[test]
66    fn max_length_works() {
67        let mut input = FixedLengthGraphemeString::new("こんにちは世界", 5);
68        assert_eq!(input.string, "こんにちは");
69        input.push_grapheme_str("世界");
70        assert_eq!(input.string, "こんにちは");
71        input.max_grapheme_length = 7;
72        input.push_grapheme_str("世界");
73        assert_eq!(input.string, "こんにちは世界");
74    }
75}