1use crate::grapheme::Grapheme;
2use crate::{upos_type, Cursor, TextError, TextPosition, TextRange};
3use std::borrow::Cow;
4use std::ops::Range;
5
6pub trait TextStore {
8 fn is_multi_line(&self) -> bool;
10
11 fn string(&self) -> String;
13
14 fn set_string(&mut self, t: &str);
16
17 fn byte_range_at(&self, pos: TextPosition) -> Result<Range<usize>, TextError>;
22
23 fn byte_range(&self, range: TextRange) -> Result<Range<usize>, TextError>;
27
28 fn byte_to_pos(&self, byte: usize) -> Result<TextPosition, TextError>;
33
34 fn bytes_to_range(&self, bytes: Range<usize>) -> Result<TextRange, TextError>;
38
39 fn str_slice(&self, range: TextRange) -> Result<Cow<'_, str>, TextError>;
44
45 fn str_slice_byte(&self, range: Range<usize>) -> Result<Cow<'_, str>, TextError>;
49
50 fn graphemes(
55 &self,
56 range: TextRange,
57 pos: TextPosition,
58 ) -> Result<impl Cursor<Item = Grapheme<'_>>, TextError>;
59
60 fn line_at(&self, row: upos_type) -> Result<Cow<'_, str>, TextError>;
64
65 fn lines_at(&self, row: upos_type) -> Result<impl Iterator<Item = Cow<'_, str>>, TextError>;
69
70 fn line_graphemes(&self, row: upos_type)
75 -> Result<impl Cursor<Item = Grapheme<'_>>, TextError>;
76
77 fn line_width(&self, row: upos_type) -> Result<upos_type, TextError>;
82
83 fn len_lines(&self) -> upos_type;
85
86 fn insert_char(
90 &mut self,
91 pos: TextPosition,
92 c: char,
93 ) -> Result<(TextRange, Range<usize>), TextError>;
94
95 fn insert_str(
99 &mut self,
100 pos: TextPosition,
101 t: &str,
102 ) -> Result<(TextRange, Range<usize>), TextError>;
103
104 fn remove(
108 &mut self,
109 range: TextRange,
110 ) -> Result<(String, (TextRange, Range<usize>)), TextError>;
111
112 fn insert_b(&mut self, byte_pos: usize, t: &str) -> Result<(), TextError>;
117
118 fn remove_b(&mut self, byte_range: Range<usize>) -> Result<(), TextError>;
123}
124
125pub(crate) mod text_rope {
126 use crate::grapheme::{Grapheme, RopeGraphemes};
127 use crate::text_store::{Cursor, TextStore};
128 use crate::{upos_type, TextError, TextPosition, TextRange};
129 use ropey::{Rope, RopeSlice};
130 use std::borrow::Cow;
131 use std::mem;
132 use std::ops::Range;
133 use unicode_segmentation::UnicodeSegmentation;
134
135 #[derive(Debug, Clone, Default)]
137 pub struct TextRope {
138 text: Rope,
139 buf: String,
141 }
142
143 #[inline]
145 fn rope_line_len(r: RopeSlice<'_>) -> upos_type {
146 let it = RopeGraphemes::new(0, r);
147 it.filter(|g| !g.is_line_break()).count() as upos_type
148 }
149
150 #[inline]
152 fn str_line_len(s: &str) -> upos_type {
153 let it = s.graphemes(true);
154 it.filter(|c| *c != "\n" && *c != "\r\n").count() as upos_type
155 }
156
157 impl TextRope {
158 #[inline]
160 fn char_at(&self, pos: TextPosition) -> Result<usize, TextError> {
161 let byte_range = self.byte_range_at(pos)?;
162 Ok(self
163 .text
164 .try_byte_to_char(byte_range.start)
165 .expect("valid_bytes"))
166 }
167
168 #[inline]
170 fn line_chars(&self, row: upos_type) -> Result<impl Iterator<Item = char> + '_, TextError> {
171 let Some(line) = self.text.get_line(row as usize) else {
172 return Err(TextError::LineIndexOutOfBounds(
173 row,
174 self.text.len_lines() as upos_type,
175 ));
176 };
177 Ok(line.chars())
178 }
179 }
180
181 impl TextRope {
182 pub fn new() -> Self {
184 Self::default()
185 }
186
187 pub fn new_text(t: &str) -> Self {
189 Self {
190 text: Rope::from_str(t),
191 buf: Default::default(),
192 }
193 }
194
195 pub fn new_rope(r: Rope) -> Self {
197 Self {
198 text: r,
199 buf: Default::default(),
200 }
201 }
202
203 pub fn rope(&self) -> &Rope {
205 &self.text
206 }
207
208 #[inline]
210 pub fn rope_slice(&self, range: TextRange) -> Result<RopeSlice<'_>, TextError> {
211 let s = self.char_at(range.start)?;
212 let e = self.char_at(range.end)?;
213 Ok(self.text.get_slice(s..e).expect("valid_range"))
214 }
215 }
216
217 impl TextStore for TextRope {
218 fn is_multi_line(&self) -> bool {
223 true
224 }
225
226 fn string(&self) -> String {
228 self.text.to_string()
229 }
230
231 fn set_string(&mut self, t: &str) {
233 self.text = Rope::from_str(t);
234 }
235
236 fn byte_range_at(&self, pos: TextPosition) -> Result<Range<usize>, TextError> {
241 let it_line = self.line_graphemes(pos.y)?;
242
243 let mut col = 0;
244 let mut byte_end = it_line.text_offset();
245 for grapheme in it_line {
246 if col == pos.x {
247 return Ok(grapheme.text_bytes());
248 }
249 col += 1;
250 byte_end = grapheme.text_bytes().end;
251 }
252 if col == pos.x {
254 Ok(byte_end..byte_end)
255 } else {
256 Err(TextError::ColumnIndexOutOfBounds(pos.x, col))
257 }
258 }
259
260 fn byte_range(&self, range: TextRange) -> Result<Range<usize>, TextError> {
264 if range.start.y == range.end.y {
265 let it_line = self.line_graphemes(range.start.y)?;
266
267 let mut range_start = None;
268 let mut range_end = None;
269 let mut col = 0;
270 let mut byte_end = it_line.text_offset();
271 for grapheme in it_line {
272 if col == range.start.x {
273 range_start = Some(grapheme.text_bytes().start);
274 }
275 if col == range.end.x {
276 range_end = Some(grapheme.text_bytes().end);
277 }
278 if range_start.is_some() && range_end.is_some() {
279 break;
280 }
281 col += 1;
282 byte_end = grapheme.text_bytes().end;
283 }
284 if col == range.start.x {
286 range_start = Some(byte_end);
287 }
288 if col == range.end.x {
289 range_end = Some(byte_end);
290 }
291
292 let Some(range_start) = range_start else {
293 return Err(TextError::ColumnIndexOutOfBounds(range.start.x, col));
294 };
295 let Some(range_end) = range_end else {
296 return Err(TextError::ColumnIndexOutOfBounds(range.end.x, col));
297 };
298
299 Ok(range_start..range_end)
300 } else {
301 let range_start = self.byte_range_at(range.start)?;
302 let range_end = self.byte_range_at(range.end)?;
303
304 Ok(range_start.start..range_end.start)
305 }
306 }
307
308 fn byte_to_pos(&self, byte_pos: usize) -> Result<TextPosition, TextError> {
313 let Ok(row) = self.text.try_byte_to_line(byte_pos) else {
314 return Err(TextError::ByteIndexOutOfBounds(
315 byte_pos,
316 self.text.len_bytes(),
317 ));
318 };
319 let row = row as upos_type;
320
321 let mut col = 0;
322 let it_line = self.line_graphemes(row)?;
323 for grapheme in it_line {
324 if byte_pos < grapheme.text_bytes().end {
325 break;
326 }
327 col += 1;
328 }
329
330 Ok(TextPosition::new(col, row))
331 }
332
333 fn bytes_to_range(&self, bytes: Range<usize>) -> Result<TextRange, TextError> {
337 let Ok(start_row) = self.text.try_byte_to_line(bytes.start) else {
338 return Err(TextError::ByteIndexOutOfBounds(
339 bytes.start,
340 self.text.len_bytes(),
341 ));
342 };
343 let start_row = start_row as upos_type;
344 let Ok(end_row) = self.text.try_byte_to_line(bytes.end) else {
345 return Err(TextError::ByteIndexOutOfBounds(
346 bytes.end,
347 self.text.len_bytes(),
348 ));
349 };
350 let end_row = end_row as upos_type;
351
352 if start_row == end_row {
353 let mut col = 0;
354 let mut start = None;
355 let mut end = None;
356 let it_line = self.line_graphemes(start_row)?;
357 for grapheme in it_line {
358 if bytes.start < grapheme.text_bytes().end {
359 if start.is_none() {
360 start = Some(col);
361 }
362 }
363 if bytes.end < grapheme.text_bytes().end {
364 if end.is_none() {
365 end = Some(col);
366 }
367 }
368 if start.is_some() && end.is_some() {
369 break;
370 }
371 col += 1;
372 }
373 if bytes.start == self.text.len_bytes() {
374 start = Some(col);
375 }
376 if bytes.end == self.text.len_bytes() {
377 end = Some(col);
378 }
379
380 let Some(start) = start else {
381 return Err(TextError::ByteIndexOutOfBounds(
382 bytes.start,
383 self.text.len_bytes(),
384 ));
385 };
386 let Some(end) = end else {
387 return Err(TextError::ByteIndexOutOfBounds(
388 bytes.end,
389 self.text.len_bytes(),
390 ));
391 };
392
393 Ok(TextRange::new((start, start_row), (end, end_row)))
394 } else {
395 let start = self.byte_to_pos(bytes.start)?;
396 let end = self.byte_to_pos(bytes.end)?;
397
398 Ok(TextRange::new(start, end))
399 }
400 }
401
402 fn str_slice(&self, range: TextRange) -> Result<Cow<'_, str>, TextError> {
407 let start_char = self.char_at(range.start)?;
408 let end_char = self.char_at(range.end)?;
409 let v = self
410 .text
411 .get_slice(start_char..end_char)
412 .expect("valid_slice");
413 match v.as_str() {
414 Some(v) => Ok(Cow::Borrowed(v)),
415 None => Ok(Cow::Owned(v.to_string())),
416 }
417 }
418
419 fn str_slice_byte(&self, range: Range<usize>) -> Result<Cow<'_, str>, TextError> {
423 let Some(v) = self.text.get_byte_slice(range.clone()) else {
424 return Err(TextError::ByteRangeOutOfBounds(
425 Some(range.start),
426 Some(range.end),
427 self.text.len_bytes(),
428 ));
429 };
430 match v.as_str() {
431 Some(v) => Ok(Cow::Borrowed(v)),
432 None => Ok(Cow::Owned(v.to_string())),
433 }
434 }
435
436 fn graphemes(
441 &self,
442 range: TextRange,
443 pos: TextPosition,
444 ) -> Result<impl Cursor<Item = Grapheme<'_>>, TextError> {
445 if !range.contains_pos(pos) && range.end != pos {
446 return Err(TextError::TextPositionOutOfBounds(pos));
447 }
448
449 let range_bytes = self.byte_range(range)?;
450 let pos_byte = self.byte_range_at(pos)?.start;
451
452 let s = self
453 .text
454 .get_byte_slice(range_bytes.clone())
455 .expect("valid_range");
456
457 Ok(
458 RopeGraphemes::new_offset(range_bytes.start, s, pos_byte - range_bytes.start)
459 .expect("valid_bytes"),
460 )
461 }
462
463 fn line_at(&self, row: upos_type) -> Result<Cow<'_, str>, TextError> {
467 let len = self.text.len_lines() as upos_type;
468 if row > len {
469 Err(TextError::LineIndexOutOfBounds(row, len))
470 } else if row == len {
471 Ok(Cow::Borrowed(""))
472 } else {
473 let v = self.text.get_line(row as usize).expect("valid_row");
474 match v.as_str() {
475 Some(v) => Ok(Cow::Borrowed(v)),
476 None => Ok(Cow::Owned(v.to_string())),
477 }
478 }
479 }
480
481 fn lines_at(
485 &self,
486 row: upos_type,
487 ) -> Result<impl Iterator<Item = Cow<'_, str>>, TextError> {
488 let len = self.text.len_lines() as upos_type;
489 if row > len {
490 Err(TextError::LineIndexOutOfBounds(row, len))
491 } else {
492 let it = self.text.get_lines_at(row as usize).expect("valid_row");
493 Ok(it.map(|v| match v.as_str() {
494 Some(v) => Cow::Borrowed(v),
495 None => Cow::Owned(v.to_string()),
496 }))
497 }
498 }
499
500 #[inline]
505 fn line_graphemes(
506 &self,
507 row: upos_type,
508 ) -> Result<impl Cursor<Item = Grapheme<'_>>, TextError> {
509 let line_byte = self.text.try_line_to_byte(row as usize)?;
510 if let Some(line) = self.text.get_line(row as usize) {
514 Ok(RopeGraphemes::new(line_byte, line))
515 } else {
516 Ok(RopeGraphemes::new(line_byte, RopeSlice::from("")))
517 }
518 }
519
520 #[inline]
525 fn line_width(&self, row: upos_type) -> Result<upos_type, TextError> {
526 let len = self.text.len_lines() as upos_type;
527 if row > len {
528 Err(TextError::LineIndexOutOfBounds(row, len))
529 } else if row == len {
530 Ok(0)
531 } else {
532 let v = self.text.get_line(row as usize).expect("valid_row");
533 Ok(rope_line_len(v))
534 }
535 }
536
537 fn len_lines(&self) -> upos_type {
538 self.text.len_lines() as upos_type
539 }
540
541 fn insert_char(
545 &mut self,
546 pos: TextPosition,
547 ch: char,
548 ) -> Result<(TextRange, Range<usize>), TextError> {
549 let pos_byte = self.byte_range_at(pos)?;
550 let pos_char = self
551 .text
552 .try_byte_to_char(pos_byte.start)
553 .expect("valid_bytes");
554
555 let mut it_gr = RopeGraphemes::new_offset(0, self.text.slice(..), pos_byte.start)
556 .expect("valid_bytes");
557
558 let prev = it_gr.prev();
559 it_gr.next();
560 let next = it_gr.next();
561
562 let insert_range = if ch == '\n' {
563 if let Some(prev) = prev {
564 if prev == "\r" {
565 TextRange::new(pos, pos)
566 } else {
567 TextRange::new(pos, (0, pos.y + 1))
568 }
569 } else {
570 TextRange::new(pos, (0, pos.y + 1))
571 }
572 } else if ch == '\r' {
573 if let Some(next) = next {
574 if next == "\n" {
575 TextRange::new(pos, pos)
576 } else {
577 TextRange::new(pos, (0, pos.y + 1))
578 }
579 } else {
580 TextRange::new(pos, (0, pos.y + 1))
581 }
582 } else {
583 let mut len = 0;
584 self.buf.clear();
585 if let Some(prev) = prev {
586 len += 1;
587 self.buf.push_str(prev.grapheme());
588 }
589 len += 1;
590 self.buf.push(ch);
591 if let Some(next) = next {
592 len += 1;
593 self.buf.push_str(next.grapheme());
594 }
595
596 let n = len - self.buf.graphemes(true).count();
597 if n == 0 {
598 TextRange::new(pos, (pos.x + 1, pos.y))
599 } else if n == 1 {
600 TextRange::new(pos, pos)
602 } else if n == 2 {
603 TextRange::new(pos, pos)
605 } else {
606 unreachable!("insert_char {:?}", self.buf);
607 }
608 };
609
610 self.text
611 .try_insert_char(pos_char, ch)
612 .expect("valid_chars");
613
614 Ok((insert_range, pos_byte.start..pos_byte.start + ch.len_utf8()))
615 }
616
617 fn insert_str(
621 &mut self,
622 pos: TextPosition,
623 txt: &str,
624 ) -> Result<(TextRange, Range<usize>), TextError> {
625 let pos_byte = self.byte_range_at(pos)?;
626 let pos_char = self
627 .text
628 .try_byte_to_char(pos_byte.start)
629 .expect("valid_bytes");
630
631 let mut line_count = 0;
632 let mut last_linebreak_idx = 0;
633 for (p, c) in txt.char_indices() {
634 if c == '\n' {
635 line_count += 1;
636 last_linebreak_idx = p + 1;
637 }
638 }
639
640 let insert_range = if line_count > 0 {
641 let mut buf = mem::take(&mut self.buf);
642
643 let split = self.char_at(pos).expect("valid_pos");
645 let line = self.line_chars(pos.y).expect("valid_pos");
646 buf.clear();
647 for c in line.skip(split) {
648 buf.push(c);
649 }
650 let old_len = str_line_len(&buf);
651 buf.clear();
652
653 buf.push_str(&txt[last_linebreak_idx..]);
655 let line = self.line_chars(pos.y).expect("valid_pos");
656 for c in line.skip(split) {
657 buf.push(c);
658 }
659 let new_len = str_line_len(&buf);
660 buf.clear();
661 self.buf = buf;
662
663 self.text.try_insert(pos_char, txt).expect("valid_pos");
664
665 TextRange::new(pos, (new_len - old_len, pos.y + line_count))
666 } else {
667 let old_len = self.line_width(pos.y).expect("valid_line");
670
671 self.text.try_insert(pos_char, txt).expect("valid_pos");
672
673 let new_len = self.line_width(pos.y).expect("valid_line");
674
675 TextRange::new(pos, (pos.x + new_len - old_len, pos.y))
676 };
677
678 Ok((insert_range, pos_byte.start..pos_byte.start + txt.len()))
679 }
680
681 fn remove(
685 &mut self,
686 range: TextRange,
687 ) -> Result<(String, (TextRange, Range<usize>)), TextError> {
688 let start_byte_pos = self.byte_range_at(range.start)?;
689 let end_byte_pos = self.byte_range_at(range.end)?;
690
691 let start_pos = self
692 .text
693 .try_byte_to_char(start_byte_pos.start)
694 .expect("valid_bytes");
695 let end_pos = self
696 .text
697 .try_byte_to_char(end_byte_pos.start)
698 .expect("valid_bytes");
699
700 let old_text = self
701 .text
702 .get_slice(start_pos..end_pos)
703 .expect("valid_bytes");
704 let old_text = old_text.to_string();
705
706 self.text.try_remove(start_pos..end_pos).expect("valid_pos");
707
708 Ok((old_text, (range, start_byte_pos.start..end_byte_pos.start)))
709 }
710
711 fn insert_b(&mut self, byte_pos: usize, t: &str) -> Result<(), TextError> {
716 let pos_char = self.text.try_byte_to_char(byte_pos)?;
717 self.text.try_insert(pos_char, t).expect("valid_pos");
718 Ok(())
719 }
720
721 fn remove_b(&mut self, byte_range: Range<usize>) -> Result<(), TextError> {
726 let start_char = self.text.try_byte_to_char(byte_range.start)?;
727 let end_char = self.text.try_byte_to_char(byte_range.end)?;
728 self.text
729 .try_remove(start_char..end_char)
730 .expect("valid_range");
731 Ok(())
732 }
733 }
734
735 impl From<ropey::Error> for TextError {
736 fn from(err: ropey::Error) -> Self {
737 use ropey::Error;
738 match err {
739 Error::ByteIndexOutOfBounds(i, l) => TextError::ByteIndexOutOfBounds(i, l),
740 Error::CharIndexOutOfBounds(i, l) => TextError::CharIndexOutOfBounds(i, l),
741 Error::LineIndexOutOfBounds(i, l) => {
742 TextError::LineIndexOutOfBounds(i as upos_type, l as upos_type)
743 }
744 Error::Utf16IndexOutOfBounds(_, _) => {
745 unreachable!("{:?}", err)
746 }
747 Error::ByteIndexNotCharBoundary(i) => TextError::ByteIndexNotCharBoundary(i),
748 Error::ByteRangeNotCharBoundary(s, e) => TextError::ByteRangeNotCharBoundary(s, e),
749 Error::ByteRangeInvalid(s, e) => TextError::ByteRangeInvalid(s, e),
750 Error::CharRangeInvalid(s, e) => TextError::CharRangeInvalid(s, e),
751 Error::ByteRangeOutOfBounds(s, e, l) => TextError::ByteRangeOutOfBounds(s, e, l),
752 Error::CharRangeOutOfBounds(s, e, l) => TextError::CharRangeOutOfBounds(s, e, l),
753 _ => {
754 unreachable!("{:?}", err)
755 }
756 }
757 }
758 }
759}
760
761pub(crate) mod text_string {
762 use crate::grapheme::{Grapheme, StrGraphemes};
763 use crate::text_store::{Cursor, TextStore};
764 use crate::{upos_type, TextError, TextPosition, TextRange};
765 use std::borrow::Cow;
766 use std::iter::once;
767 use std::mem;
768 use std::ops::Range;
769 use unicode_segmentation::UnicodeSegmentation;
770
771 #[derive(Debug, Default, Clone)]
773 pub struct TextString {
774 text: String,
776 len: upos_type,
778 buf: String,
780 }
781
782 #[inline]
784 fn str_len(s: &str) -> upos_type {
785 s.graphemes(true).count() as upos_type
786 }
787
788 impl TextString {
789 pub fn new() -> Self {
791 Self {
792 text: Default::default(),
793 len: 0,
794 buf: Default::default(),
795 }
796 }
797
798 pub fn new_text(t: &str) -> Self {
800 Self {
801 text: t.into(),
802 len: str_len(t),
803 buf: Default::default(),
804 }
805 }
806
807 pub fn new_string(t: String) -> Self {
809 let len = str_len(&t);
810 Self {
811 text: t,
812 len,
813 buf: Default::default(),
814 }
815 }
816
817 pub fn as_str(&self) -> &str {
819 self.text.as_str()
820 }
821 }
822
823 impl TextStore for TextString {
824 fn is_multi_line(&self) -> bool {
828 false
829 }
830
831 fn string(&self) -> String {
833 self.text.to_string()
834 }
835
836 fn set_string(&mut self, t: &str) {
838 self.text = t.to_string();
839 self.len = str_len(&self.text);
840 }
841
842 fn byte_range_at(&self, pos: TextPosition) -> Result<Range<usize>, TextError> {
847 if pos.y != 0 && pos != TextPosition::new(0, 1) {
848 return Err(TextError::LineIndexOutOfBounds(pos.y, 1));
849 };
850
851 if pos == TextPosition::new(0, 1) {
852 let len = self.text.len();
853 return Ok(len..len);
854 }
855
856 let mut byte_range = None;
857 for (cidx, (idx, c)) in self
858 .text
859 .grapheme_indices(true)
860 .chain(once((self.text.len(), "")))
861 .enumerate()
862 {
863 if cidx == pos.x as usize {
864 byte_range = Some(idx..idx + c.len());
865 break;
866 }
867 }
868
869 if let Some(byte_range) = byte_range {
870 Ok(byte_range)
871 } else {
872 Err(TextError::ColumnIndexOutOfBounds(
873 pos.x,
874 str_len(&self.text),
875 ))
876 }
877 }
878
879 fn byte_range(&self, range: TextRange) -> Result<Range<usize>, TextError> {
883 if range.start.y != 0 && range.start != TextPosition::new(0, 1) {
884 return Err(TextError::LineIndexOutOfBounds(range.start.y, 1));
885 };
886 if range.end.y != 0 && range.end != TextPosition::new(0, 1) {
887 return Err(TextError::LineIndexOutOfBounds(range.end.y, 1));
888 };
889
890 let mut byte_start = None;
891 let mut byte_end = None;
892
893 if range.start == TextPosition::new(0, 1) {
894 byte_start = Some(self.text.len());
895 }
896 if range.end == TextPosition::new(0, 1) {
897 byte_end = Some(self.text.len());
898 }
899
900 if byte_start.is_none() || byte_end.is_none() {
901 for (cidx, (idx, _)) in self
902 .text
903 .grapheme_indices(true)
904 .chain(once((self.text.len(), "")))
905 .enumerate()
906 {
907 if TextPosition::new(cidx as upos_type, 0) == range.start {
908 byte_start = Some(idx);
909 }
910 if TextPosition::new(cidx as upos_type, 0) == range.end {
911 byte_end = Some(idx);
912 }
913 if byte_start.is_some() && byte_end.is_some() {
914 break;
915 }
916 }
917 }
918
919 let Some(byte_start) = byte_start else {
920 return Err(TextError::ColumnIndexOutOfBounds(
921 range.start.x,
922 str_len(&self.text),
923 ));
924 };
925 let Some(byte_end) = byte_end else {
926 return Err(TextError::ColumnIndexOutOfBounds(
927 range.end.x,
928 str_len(&self.text),
929 ));
930 };
931
932 Ok(byte_start..byte_end)
933 }
934
935 fn byte_to_pos(&self, byte_pos: usize) -> Result<TextPosition, TextError> {
940 let mut pos = None;
941
942 for (cidx, (c_start, c)) in self
943 .text
944 .grapheme_indices(true)
945 .chain(once((self.text.len(), " ")))
946 .enumerate()
947 {
948 if byte_pos < c_start + c.len() {
949 pos = Some(cidx);
950 break;
951 }
952 }
953
954 if let Some(pos) = pos {
955 Ok(TextPosition::new(pos as upos_type, 0))
956 } else {
957 Err(TextError::ByteIndexOutOfBounds(byte_pos, self.text.len()))
958 }
959 }
960
961 fn bytes_to_range(&self, bytes: Range<usize>) -> Result<TextRange, TextError> {
965 let mut start = None;
966 let mut end = None;
967 for (cidx, (c_start, c)) in self
968 .text
969 .grapheme_indices(true)
970 .chain(once((self.text.len(), " ")))
971 .enumerate()
972 {
973 if bytes.start < c_start + c.len() {
974 if start.is_none() {
975 start = Some(cidx as upos_type);
976 }
977 }
978 if bytes.end < c_start + c.len() {
979 if end.is_none() {
980 end = Some(cidx as upos_type);
981 }
982 }
983 if start.is_some() && end.is_some() {
984 break;
985 }
986 }
987
988 let Some(start) = start else {
989 return Err(TextError::ByteIndexOutOfBounds(
990 bytes.start,
991 self.text.len(),
992 ));
993 };
994 let Some(end) = end else {
995 return Err(TextError::ByteIndexOutOfBounds(bytes.end, self.text.len()));
996 };
997
998 Ok(TextRange::new((start, 0), (end, 0)))
999 }
1000
1001 fn str_slice(&self, range: TextRange) -> Result<Cow<'_, str>, TextError> {
1006 let range = self.byte_range(range)?;
1007 Ok(Cow::Borrowed(&self.text[range.start..range.end]))
1008 }
1009
1010 fn str_slice_byte(&self, range: Range<usize>) -> Result<Cow<'_, str>, TextError> {
1014 Ok(Cow::Borrowed(&self.text[range.start..range.end]))
1015 }
1016
1017 fn graphemes(
1022 &self,
1023 range: TextRange,
1024 pos: TextPosition,
1025 ) -> Result<impl Cursor<Item = Grapheme<'_>>, TextError> {
1026 let range_byte = self.byte_range(range)?;
1027 let pos_byte = self.byte_range_at(pos)?;
1028 Ok(StrGraphemes::new_offset(
1029 range_byte.start,
1030 &self.text[range_byte.clone()],
1031 pos_byte.start - range_byte.start,
1032 ))
1033 }
1034
1035 fn line_at(&self, row: upos_type) -> Result<Cow<'_, str>, TextError> {
1039 if row == 0 {
1040 Ok(Cow::Borrowed(&self.text))
1041 } else if row == 1 {
1042 Ok(Cow::Borrowed(""))
1043 } else {
1044 Err(TextError::LineIndexOutOfBounds(row, 1))
1045 }
1046 }
1047
1048 fn lines_at(
1052 &self,
1053 row: upos_type,
1054 ) -> Result<impl Iterator<Item = Cow<'_, str>>, TextError> {
1055 if row == 0 {
1056 Ok(once(Cow::Borrowed(self.text.as_str())))
1057 } else if row == 1 {
1058 Ok(once(Cow::Borrowed("")))
1059 } else {
1060 Err(TextError::LineIndexOutOfBounds(row, 1))
1061 }
1062 }
1063
1064 fn line_graphemes(
1069 &self,
1070 row: upos_type,
1071 ) -> Result<impl Cursor<Item = Grapheme<'_>>, TextError> {
1072 if row == 0 {
1073 Ok(StrGraphemes::new(0, &self.text))
1074 } else if row == 1 {
1075 Ok(StrGraphemes::new(self.text.len(), ""))
1076 } else {
1077 Err(TextError::LineIndexOutOfBounds(row, 1))
1078 }
1079 }
1080
1081 fn line_width(&self, row: upos_type) -> Result<upos_type, TextError> {
1086 if row == 0 {
1087 Ok(self.len)
1088 } else if row == 1 {
1089 Ok(0)
1090 } else {
1091 Err(TextError::LineIndexOutOfBounds(row, 1))
1092 }
1093 }
1094
1095 fn len_lines(&self) -> upos_type {
1097 1
1098 }
1099
1100 fn insert_char(
1104 &mut self,
1105 pos: TextPosition,
1106 c: char,
1107 ) -> Result<(TextRange, Range<usize>), TextError> {
1108 if pos.y != 0 && pos != TextPosition::new(0, 1) {
1109 return Err(TextError::TextPositionOutOfBounds(pos));
1110 }
1111
1112 let byte_pos = self.byte_range_at(pos)?;
1113 let (before, after) = self.text.split_at(byte_pos.start);
1114
1115 let old_len = self.len;
1116 self.buf.clear();
1117 self.buf.push_str(before);
1118 self.buf.push(c);
1119 self.buf.push_str(after);
1120
1121 let before_bytes = before.len();
1122 let new_len = str_len(&self.buf);
1123
1124 mem::swap(&mut self.text, &mut self.buf);
1125 self.len = new_len;
1126
1127 Ok((
1128 TextRange::new((pos.x, 0), (pos.x + (new_len - old_len), 0)),
1129 before_bytes..before_bytes + c.len_utf8(),
1130 ))
1131 }
1132
1133 fn insert_str(
1135 &mut self,
1136 pos: TextPosition,
1137 t: &str,
1138 ) -> Result<(TextRange, Range<usize>), TextError> {
1139 if pos.y != 0 && pos != TextPosition::new(0, 1) {
1140 return Err(TextError::TextPositionOutOfBounds(pos));
1141 }
1142
1143 let byte_pos = self.byte_range_at(pos)?;
1144 let (before, after) = self.text.split_at(byte_pos.start);
1145
1146 let old_len = self.len;
1147 self.buf.clear();
1148 self.buf.push_str(before);
1149 self.buf.push_str(t);
1150 self.buf.push_str(after);
1151
1152 let before_bytes = before.len();
1153 let new_len = str_len(&self.buf);
1154
1155 mem::swap(&mut self.text, &mut self.buf);
1156 self.len = new_len;
1157
1158 Ok((
1159 TextRange::new((pos.x, 0), (pos.x + (new_len - old_len), 0)),
1160 before_bytes..before_bytes + t.len(),
1161 ))
1162 }
1163
1164 fn remove(
1166 &mut self,
1167 range: TextRange,
1168 ) -> Result<(String, (TextRange, Range<usize>)), TextError> {
1169 if range.start.y != 0 && range.start != TextPosition::new(0, 1) {
1170 return Err(TextError::TextRangeOutOfBounds(range));
1171 }
1172 if range.end.y != 0 && range.end != TextPosition::new(0, 1) {
1173 return Err(TextError::TextRangeOutOfBounds(range));
1174 }
1175
1176 let bytes = self.byte_range(range)?;
1177
1178 let (before, remove, after) = (
1179 &self.text[..bytes.start],
1180 &self.text[bytes.start..bytes.end],
1181 &self.text[bytes.end..],
1182 );
1183
1184 self.buf.clear();
1185 self.buf.push_str(before);
1186 self.buf.push_str(after);
1187
1188 let remove_str = remove.to_string();
1189 let before_bytes = before.len();
1190 let remove_bytes = remove.len();
1191 let new_len = str_len(&self.buf);
1192
1193 mem::swap(&mut self.text, &mut self.buf);
1194 self.len = new_len;
1195
1196 Ok((
1197 remove_str,
1198 (range, before_bytes..before_bytes + remove_bytes),
1199 ))
1200 }
1201
1202 fn insert_b(&mut self, byte_pos: usize, t: &str) -> Result<(), TextError> {
1204 let Some((before, after)) = self.text.split_at_checked(byte_pos) else {
1205 return Err(TextError::ByteIndexNotCharBoundary(byte_pos));
1206 };
1207
1208 self.buf.clear();
1209 self.buf.push_str(before);
1210 self.buf.push_str(t);
1211 self.buf.push_str(after);
1212 let new_len = str_len(&self.buf);
1213
1214 mem::swap(&mut self.text, &mut self.buf);
1215 self.len = new_len;
1216
1217 Ok(())
1218 }
1219
1220 fn remove_b(&mut self, byte_range: Range<usize>) -> Result<(), TextError> {
1222 let Some((before, after)) = self.text.split_at_checked(byte_range.start) else {
1223 return Err(TextError::ByteIndexNotCharBoundary(byte_range.start));
1224 };
1225 let Some((_remove, after)) = after.split_at_checked(byte_range.end - byte_range.start)
1226 else {
1227 return Err(TextError::ByteIndexNotCharBoundary(byte_range.end));
1228 };
1229
1230 self.buf.clear();
1231 self.buf.push_str(before);
1232 self.buf.push_str(after);
1233 let new_len = str_len(&self.buf);
1234
1235 mem::swap(&mut self.text, &mut self.buf);
1236 self.len = new_len;
1237
1238 Ok(())
1239 }
1240 }
1241}