lb_rs/model/text/
unicode_segs.rs1use 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}