lb_rs/model/text/
unicode_segs.rs

1use super::offset_types::{DocByteOffset, DocCharOffset};
2use unicode_segmentation::UnicodeSegmentation;
3
4#[derive(Clone, Default, Debug)]
5pub struct UnicodeSegs {
6    pub grapheme_indexes: Vec<DocByteOffset>,
7}
8
9pub fn calc(text: &str) -> UnicodeSegs {
10    let mut result = UnicodeSegs::default();
11    if !text.is_empty() {
12        result
13            .grapheme_indexes
14            .extend(text.grapheme_indices(true).map(|t| DocByteOffset(t.0)));
15    }
16    result.grapheme_indexes.push(DocByteOffset(text.len()));
17    result
18}
19
20impl UnicodeSegs {
21    pub fn offset_to_byte(&self, i: DocCharOffset) -> DocByteOffset {
22        if self.grapheme_indexes.is_empty() && i.0 == 0 {
23            return DocByteOffset(0);
24        }
25        self.grapheme_indexes[i.0]
26    }
27
28    pub fn range_to_byte(
29        &self, i: (DocCharOffset, DocCharOffset),
30    ) -> (DocByteOffset, DocByteOffset) {
31        (self.offset_to_byte(i.0), self.offset_to_byte(i.1))
32    }
33
34    pub fn offset_to_char(&self, i: DocByteOffset) -> DocCharOffset {
35        if self.grapheme_indexes.is_empty() && i.0 == 0 {
36            return DocCharOffset(0);
37        }
38
39        DocCharOffset(self.grapheme_indexes.binary_search(&i).unwrap())
40    }
41
42    pub fn range_to_char(
43        &self, i: (DocByteOffset, DocByteOffset),
44    ) -> (DocCharOffset, DocCharOffset) {
45        (self.offset_to_char(i.0), self.offset_to_char(i.1))
46    }
47
48    pub fn last_cursor_position(&self) -> DocCharOffset {
49        DocCharOffset(self.grapheme_indexes.len() - 1)
50    }
51}