1mod anchor;
2pub mod locator;
3#[cfg(any(test, feature = "test-support"))]
4pub mod network;
5pub mod operation_queue;
6mod patch;
7mod selection;
8pub mod subscription;
9#[cfg(test)]
10mod tests;
11mod undo_map;
12
13pub use anchor::*;
14use anyhow::{Context as _, Result};
15use clock::Lamport;
16pub use clock::ReplicaId;
17use collections::{HashMap, HashSet};
18use locator::Locator;
19use operation_queue::OperationQueue;
20pub use patch::Patch;
21use postage::{oneshot, prelude::*};
22
23use regex::Regex;
24pub use rope::*;
25pub use selection::*;
26use std::{
27 borrow::Cow,
28 cmp::{self, Ordering, Reverse},
29 fmt::Display,
30 future::Future,
31 iter::Iterator,
32 num::NonZeroU64,
33 ops::{self, Deref, Range, Sub},
34 str,
35 sync::{Arc, LazyLock},
36 time::{Duration, Instant},
37};
38pub use subscription::*;
39pub use sum_tree::Bias;
40use sum_tree::{Dimensions, FilterCursor, SumTree, TreeMap, TreeSet};
41use undo_map::UndoMap;
42use util::debug_panic;
43
44#[cfg(any(test, feature = "test-support"))]
45use util::RandomCharIter;
46
47static LINE_SEPARATORS_REGEX: LazyLock<Regex> =
48 LazyLock::new(|| Regex::new(r"\r\n|\r").expect("Failed to create LINE_SEPARATORS_REGEX"));
49
50pub type TransactionId = clock::Lamport;
51
52pub struct Buffer {
53 snapshot: BufferSnapshot,
54 history: History,
55 deferred_ops: OperationQueue<Operation>,
56 deferred_replicas: HashSet<ReplicaId>,
57 pub lamport_clock: clock::Lamport,
58 subscriptions: Topic<usize>,
59 edit_id_resolvers: HashMap<clock::Lamport, Vec<oneshot::Sender<()>>>,
60 wait_for_version_txs: Vec<(clock::Global, oneshot::Sender<()>)>,
61}
62
63#[repr(transparent)]
64#[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Ord, Eq)]
65pub struct BufferId(NonZeroU64);
66
67impl Display for BufferId {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 write!(f, "{}", self.0)
70 }
71}
72
73impl From<NonZeroU64> for BufferId {
74 fn from(id: NonZeroU64) -> Self {
75 BufferId(id)
76 }
77}
78
79impl BufferId {
80 /// Returns Err if `id` is outside of BufferId domain.
81 pub fn new(id: u64) -> anyhow::Result<Self> {
82 let id = NonZeroU64::new(id).context("Buffer id cannot be 0.")?;
83 Ok(Self(id))
84 }
85
86 /// Increments this buffer id, returning the old value.
87 /// So that's a post-increment operator in disguise.
88 pub fn next(&mut self) -> Self {
89 let old = *self;
90 self.0 = self.0.saturating_add(1);
91 old
92 }
93
94 pub fn to_proto(self) -> u64 {
95 self.into()
96 }
97}
98
99impl From<BufferId> for u64 {
100 fn from(id: BufferId) -> Self {
101 id.0.get()
102 }
103}
104
105#[derive(Clone)]
106pub struct BufferSnapshot {
107 visible_text: Rope,
108 deleted_text: Rope,
109 fragments: SumTree<Fragment>,
110 insertions: SumTree<InsertionFragment>,
111 insertion_slices: TreeSet<InsertionSlice>,
112 undo_map: UndoMap,
113 pub version: clock::Global,
114 remote_id: BufferId,
115 replica_id: ReplicaId,
116 line_ending: LineEnding,
117}
118
119#[derive(Clone, Debug)]
120pub struct HistoryEntry {
121 transaction: Transaction,
122 first_edit_at: Instant,
123 last_edit_at: Instant,
124 suppress_grouping: bool,
125}
126
127#[derive(Clone, Debug)]
128pub struct Transaction {
129 pub id: TransactionId,
130 pub edit_ids: Vec<clock::Lamport>,
131 pub start: clock::Global,
132}
133
134impl Transaction {
135 pub fn merge_in(&mut self, other: Transaction) {
136 self.edit_ids.extend(other.edit_ids);
137 }
138}
139
140impl HistoryEntry {
141 pub fn transaction_id(&self) -> TransactionId {
142 self.transaction.id
143 }
144}
145
146struct History {
147 base_text: Rope,
148 operations: TreeMap<clock::Lamport, Operation>,
149 undo_stack: Vec<HistoryEntry>,
150 redo_stack: Vec<HistoryEntry>,
151 transaction_depth: usize,
152 group_interval: Duration,
153}
154
155#[derive(Clone, Debug, Eq, PartialEq)]
156struct InsertionSlice {
157 edit_id: clock::Lamport,
158 insertion_id: clock::Lamport,
159 range: Range<usize>,
160}
161
162impl Ord for InsertionSlice {
163 fn cmp(&self, other: &Self) -> Ordering {
164 self.edit_id
165 .cmp(&other.edit_id)
166 .then_with(|| self.insertion_id.cmp(&other.insertion_id))
167 .then_with(|| self.range.start.cmp(&other.range.start))
168 .then_with(|| self.range.end.cmp(&other.range.end))
169 }
170}
171
172impl PartialOrd for InsertionSlice {
173 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
174 Some(self.cmp(other))
175 }
176}
177
178impl InsertionSlice {
179 fn from_fragment(edit_id: clock::Lamport, fragment: &Fragment) -> Self {
180 Self {
181 edit_id,
182 insertion_id: fragment.timestamp,
183 range: fragment.insertion_offset..fragment.insertion_offset + fragment.len,
184 }
185 }
186}
187
188impl History {
189 pub fn new(base_text: Rope) -> Self {
190 Self {
191 base_text,
192 operations: Default::default(),
193 undo_stack: Vec::new(),
194 redo_stack: Vec::new(),
195 transaction_depth: 0,
196 // Don't group transactions in tests unless we opt in, because it's a footgun.
197 #[cfg(any(test, feature = "test-support"))]
198 group_interval: Duration::ZERO,
199 #[cfg(not(any(test, feature = "test-support")))]
200 group_interval: Duration::from_millis(300),
201 }
202 }
203
204 fn push(&mut self, op: Operation) {
205 self.operations.insert(op.timestamp(), op);
206 }
207
208 fn start_transaction(
209 &mut self,
210 start: clock::Global,
211 now: Instant,
212 clock: &mut clock::Lamport,
213 ) -> Option<TransactionId> {
214 self.transaction_depth += 1;
215 if self.transaction_depth == 1 {
216 let id = clock.tick();
217 self.undo_stack.push(HistoryEntry {
218 transaction: Transaction {
219 id,
220 start,
221 edit_ids: Default::default(),
222 },
223 first_edit_at: now,
224 last_edit_at: now,
225 suppress_grouping: false,
226 });
227 Some(id)
228 } else {
229 None
230 }
231 }
232
233 fn end_transaction(&mut self, now: Instant) -> Option<&HistoryEntry> {
234 assert_ne!(self.transaction_depth, 0);
235 self.transaction_depth -= 1;
236 if self.transaction_depth == 0 {
237 if self
238 .undo_stack
239 .last()
240 .unwrap()
241 .transaction
242 .edit_ids
243 .is_empty()
244 {
245 self.undo_stack.pop();
246 None
247 } else {
248 self.redo_stack.clear();
249 let entry = self.undo_stack.last_mut().unwrap();
250 entry.last_edit_at = now;
251 Some(entry)
252 }
253 } else {
254 None
255 }
256 }
257
258 fn group(&mut self) -> Option<TransactionId> {
259 let mut count = 0;
260 let mut entries = self.undo_stack.iter();
261 if let Some(mut entry) = entries.next_back() {
262 while let Some(prev_entry) = entries.next_back() {
263 if !prev_entry.suppress_grouping
264 && entry.first_edit_at - prev_entry.last_edit_at < self.group_interval
265 {
266 entry = prev_entry;
267 count += 1;
268 } else {
269 break;
270 }
271 }
272 }
273 self.group_trailing(count)
274 }
275
276 fn group_until(&mut self, transaction_id: TransactionId) {
277 let mut count = 0;
278 for entry in self.undo_stack.iter().rev() {
279 if entry.transaction_id() == transaction_id {
280 self.group_trailing(count);
281 break;
282 } else if entry.suppress_grouping {
283 break;
284 } else {
285 count += 1;
286 }
287 }
288 }
289
290 fn group_trailing(&mut self, n: usize) -> Option<TransactionId> {
291 let new_len = self.undo_stack.len() - n;
292 let (entries_to_keep, entries_to_merge) = self.undo_stack.split_at_mut(new_len);
293 if let Some(last_entry) = entries_to_keep.last_mut() {
294 for entry in &*entries_to_merge {
295 for edit_id in &entry.transaction.edit_ids {
296 last_entry.transaction.edit_ids.push(*edit_id);
297 }
298 }
299
300 if let Some(entry) = entries_to_merge.last_mut() {
301 last_entry.last_edit_at = entry.last_edit_at;
302 }
303 }
304
305 self.undo_stack.truncate(new_len);
306 self.undo_stack.last().map(|e| e.transaction.id)
307 }
308
309 fn finalize_last_transaction(&mut self) -> Option<&Transaction> {
310 self.undo_stack.last_mut().map(|entry| {
311 entry.suppress_grouping = true;
312 &entry.transaction
313 })
314 }
315
316 fn push_transaction(&mut self, transaction: Transaction, now: Instant) {
317 assert_eq!(self.transaction_depth, 0);
318 self.undo_stack.push(HistoryEntry {
319 transaction,
320 first_edit_at: now,
321 last_edit_at: now,
322 suppress_grouping: false,
323 });
324 }
325
326 /// Differs from `push_transaction` in that it does not clear the redo
327 /// stack. Intended to be used to create a parent transaction to merge
328 /// potential child transactions into.
329 ///
330 /// The caller is responsible for removing it from the undo history using
331 /// `forget_transaction` if no edits are merged into it. Otherwise, if edits
332 /// are merged into this transaction, the caller is responsible for ensuring
333 /// the redo stack is cleared. The easiest way to ensure the redo stack is
334 /// cleared is to create transactions with the usual `start_transaction` and
335 /// `end_transaction` methods and merging the resulting transactions into
336 /// the transaction created by this method
337 fn push_empty_transaction(
338 &mut self,
339 start: clock::Global,
340 now: Instant,
341 clock: &mut clock::Lamport,
342 ) -> TransactionId {
343 assert_eq!(self.transaction_depth, 0);
344 let id = clock.tick();
345 let transaction = Transaction {
346 id,
347 start,
348 edit_ids: Vec::new(),
349 };
350 self.undo_stack.push(HistoryEntry {
351 transaction,
352 first_edit_at: now,
353 last_edit_at: now,
354 suppress_grouping: false,
355 });
356 id
357 }
358
359 fn push_undo(&mut self, op_id: clock::Lamport) {
360 assert_ne!(self.transaction_depth, 0);
361 if let Some(Operation::Edit(_)) = self.operations.get(&op_id) {
362 let last_transaction = self.undo_stack.last_mut().unwrap();
363 last_transaction.transaction.edit_ids.push(op_id);
364 }
365 }
366
367 fn pop_undo(&mut self) -> Option<&HistoryEntry> {
368 assert_eq!(self.transaction_depth, 0);
369 if let Some(entry) = self.undo_stack.pop() {
370 self.redo_stack.push(entry);
371 self.redo_stack.last()
372 } else {
373 None
374 }
375 }
376
377 fn remove_from_undo(&mut self, transaction_id: TransactionId) -> Option<&HistoryEntry> {
378 assert_eq!(self.transaction_depth, 0);
379
380 let entry_ix = self
381 .undo_stack
382 .iter()
383 .rposition(|entry| entry.transaction.id == transaction_id)?;
384 let entry = self.undo_stack.remove(entry_ix);
385 self.redo_stack.push(entry);
386 self.redo_stack.last()
387 }
388
389 fn remove_from_undo_until(&mut self, transaction_id: TransactionId) -> &[HistoryEntry] {
390 assert_eq!(self.transaction_depth, 0);
391
392 let redo_stack_start_len = self.redo_stack.len();
393 if let Some(entry_ix) = self
394 .undo_stack
395 .iter()
396 .rposition(|entry| entry.transaction.id == transaction_id)
397 {
398 self.redo_stack
399 .extend(self.undo_stack.drain(entry_ix..).rev());
400 }
401 &self.redo_stack[redo_stack_start_len..]
402 }
403
404 fn forget(&mut self, transaction_id: TransactionId) -> Option<Transaction> {
405 assert_eq!(self.transaction_depth, 0);
406 if let Some(entry_ix) = self
407 .undo_stack
408 .iter()
409 .rposition(|entry| entry.transaction.id == transaction_id)
410 {
411 Some(self.undo_stack.remove(entry_ix).transaction)
412 } else if let Some(entry_ix) = self
413 .redo_stack
414 .iter()
415 .rposition(|entry| entry.transaction.id == transaction_id)
416 {
417 Some(self.redo_stack.remove(entry_ix).transaction)
418 } else {
419 None
420 }
421 }
422
423 fn transaction(&self, transaction_id: TransactionId) -> Option<&Transaction> {
424 let entry = self
425 .undo_stack
426 .iter()
427 .rfind(|entry| entry.transaction.id == transaction_id)
428 .or_else(|| {
429 self.redo_stack
430 .iter()
431 .rfind(|entry| entry.transaction.id == transaction_id)
432 })?;
433 Some(&entry.transaction)
434 }
435
436 fn transaction_mut(&mut self, transaction_id: TransactionId) -> Option<&mut Transaction> {
437 let entry = self
438 .undo_stack
439 .iter_mut()
440 .rfind(|entry| entry.transaction.id == transaction_id)
441 .or_else(|| {
442 self.redo_stack
443 .iter_mut()
444 .rfind(|entry| entry.transaction.id == transaction_id)
445 })?;
446 Some(&mut entry.transaction)
447 }
448
449 fn merge_transactions(&mut self, transaction: TransactionId, destination: TransactionId) {
450 if let Some(transaction) = self.forget(transaction)
451 && let Some(destination) = self.transaction_mut(destination)
452 {
453 destination.edit_ids.extend(transaction.edit_ids);
454 }
455 }
456
457 fn pop_redo(&mut self) -> Option<&HistoryEntry> {
458 assert_eq!(self.transaction_depth, 0);
459 if let Some(entry) = self.redo_stack.pop() {
460 self.undo_stack.push(entry);
461 self.undo_stack.last()
462 } else {
463 None
464 }
465 }
466
467 fn remove_from_redo(&mut self, transaction_id: TransactionId) -> &[HistoryEntry] {
468 assert_eq!(self.transaction_depth, 0);
469
470 let undo_stack_start_len = self.undo_stack.len();
471 if let Some(entry_ix) = self
472 .redo_stack
473 .iter()
474 .rposition(|entry| entry.transaction.id == transaction_id)
475 {
476 self.undo_stack
477 .extend(self.redo_stack.drain(entry_ix..).rev());
478 }
479 &self.undo_stack[undo_stack_start_len..]
480 }
481}
482
483struct Edits<'a, D: TextDimension, F: FnMut(&FragmentSummary) -> bool> {
484 visible_cursor: rope::Cursor<'a>,
485 deleted_cursor: rope::Cursor<'a>,
486 fragments_cursor: Option<FilterCursor<'a, 'static, F, Fragment, FragmentTextSummary>>,
487 undos: &'a UndoMap,
488 since: &'a clock::Global,
489 old_end: D,
490 new_end: D,
491 range: Range<(&'a Locator, usize)>,
492 buffer_id: BufferId,
493}
494
495#[derive(Clone, Debug, Default, Eq, PartialEq)]
496pub struct Edit<D> {
497 pub old: Range<D>,
498 pub new: Range<D>,
499}
500impl<D> Edit<D>
501where
502 D: PartialEq,
503{
504 pub fn is_empty(&self) -> bool {
505 self.old.start == self.old.end && self.new.start == self.new.end
506 }
507}
508
509impl<D, DDelta> Edit<D>
510where
511 D: Sub<D, Output = DDelta> + Copy,
512{
513 pub fn old_len(&self) -> DDelta {
514 self.old.end - self.old.start
515 }
516
517 pub fn new_len(&self) -> DDelta {
518 self.new.end - self.new.start
519 }
520}
521
522impl<D1, D2> Edit<(D1, D2)> {
523 pub fn flatten(self) -> (Edit<D1>, Edit<D2>) {
524 (
525 Edit {
526 old: self.old.start.0..self.old.end.0,
527 new: self.new.start.0..self.new.end.0,
528 },
529 Edit {
530 old: self.old.start.1..self.old.end.1,
531 new: self.new.start.1..self.new.end.1,
532 },
533 )
534 }
535}
536
537#[derive(Eq, PartialEq, Clone, Debug)]
538pub struct Fragment {
539 pub id: Locator,
540 pub timestamp: clock::Lamport,
541 pub insertion_offset: usize,
542 pub len: usize,
543 pub visible: bool,
544 pub deletions: HashSet<clock::Lamport>,
545 pub max_undos: clock::Global,
546}
547
548#[derive(Eq, PartialEq, Clone, Debug)]
549pub struct FragmentSummary {
550 text: FragmentTextSummary,
551 max_id: Locator,
552 max_version: clock::Global,
553 min_insertion_version: clock::Global,
554 max_insertion_version: clock::Global,
555}
556
557#[derive(Copy, Default, Clone, Debug, PartialEq, Eq)]
558struct FragmentTextSummary {
559 visible: usize,
560 deleted: usize,
561}
562
563impl<'a> sum_tree::Dimension<'a, FragmentSummary> for FragmentTextSummary {
564 fn zero(_: &Option<clock::Global>) -> Self {
565 Default::default()
566 }
567
568 fn add_summary(&mut self, summary: &'a FragmentSummary, _: &Option<clock::Global>) {
569 self.visible += summary.text.visible;
570 self.deleted += summary.text.deleted;
571 }
572}
573
574#[derive(Eq, PartialEq, Clone, Debug)]
575struct InsertionFragment {
576 timestamp: clock::Lamport,
577 split_offset: usize,
578 fragment_id: Locator,
579}
580
581#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
582struct InsertionFragmentKey {
583 timestamp: clock::Lamport,
584 split_offset: usize,
585}
586
587#[derive(Clone, Debug, Eq, PartialEq)]
588pub enum Operation {
589 Edit(EditOperation),
590 Undo(UndoOperation),
591}
592
593#[derive(Clone, Debug, Eq, PartialEq)]
594pub struct EditOperation {
595 pub timestamp: clock::Lamport,
596 pub version: clock::Global,
597 pub ranges: Vec<Range<FullOffset>>,
598 pub new_text: Vec<Arc<str>>,
599}
600
601#[derive(Clone, Debug, Eq, PartialEq)]
602pub struct UndoOperation {
603 pub timestamp: clock::Lamport,
604 pub version: clock::Global,
605 pub counts: HashMap<clock::Lamport, u32>,
606}
607
608/// Stores information about the indentation of a line (tabs and spaces).
609#[derive(Clone, Copy, Debug, Eq, PartialEq)]
610pub struct LineIndent {
611 pub tabs: u32,
612 pub spaces: u32,
613 pub line_blank: bool,
614}
615
616impl LineIndent {
617 pub fn from_chunks(chunks: &mut Chunks) -> Self {
618 let mut tabs = 0;
619 let mut spaces = 0;
620 let mut line_blank = true;
621
622 'outer: while let Some(chunk) = chunks.peek() {
623 for ch in chunk.chars() {
624 if ch == '\t' {
625 tabs += 1;
626 } else if ch == ' ' {
627 spaces += 1;
628 } else {
629 if ch != '\n' {
630 line_blank = false;
631 }
632 break 'outer;
633 }
634 }
635
636 chunks.next();
637 }
638
639 Self {
640 tabs,
641 spaces,
642 line_blank,
643 }
644 }
645
646 /// Constructs a new `LineIndent` which only contains spaces.
647 pub fn spaces(spaces: u32) -> Self {
648 Self {
649 tabs: 0,
650 spaces,
651 line_blank: true,
652 }
653 }
654
655 /// Constructs a new `LineIndent` which only contains tabs.
656 pub fn tabs(tabs: u32) -> Self {
657 Self {
658 tabs,
659 spaces: 0,
660 line_blank: true,
661 }
662 }
663
664 /// Indicates whether the line is empty.
665 pub fn is_line_empty(&self) -> bool {
666 self.tabs == 0 && self.spaces == 0 && self.line_blank
667 }
668
669 /// Indicates whether the line is blank (contains only whitespace).
670 pub fn is_line_blank(&self) -> bool {
671 self.line_blank
672 }
673
674 /// Returns the number of indentation characters (tabs or spaces).
675 pub fn raw_len(&self) -> u32 {
676 self.tabs + self.spaces
677 }
678
679 /// Returns the number of indentation characters (tabs or spaces), taking tab size into account.
680 pub fn len(&self, tab_size: u32) -> u32 {
681 self.tabs * tab_size + self.spaces
682 }
683}
684
685impl From<&str> for LineIndent {
686 fn from(value: &str) -> Self {
687 Self::from_iter(value.chars())
688 }
689}
690
691impl FromIterator<char> for LineIndent {
692 fn from_iter<T: IntoIterator<Item = char>>(chars: T) -> Self {
693 let mut tabs = 0;
694 let mut spaces = 0;
695 let mut line_blank = true;
696 for c in chars {
697 if c == '\t' {
698 tabs += 1;
699 } else if c == ' ' {
700 spaces += 1;
701 } else {
702 if c != '\n' {
703 line_blank = false;
704 }
705 break;
706 }
707 }
708 Self {
709 tabs,
710 spaces,
711 line_blank,
712 }
713 }
714}
715
716impl Buffer {
717 pub fn new(replica_id: ReplicaId, remote_id: BufferId, base_text: impl Into<String>) -> Buffer {
718 let mut base_text = base_text.into();
719 let line_ending = LineEnding::detect(&base_text);
720 LineEnding::normalize(&mut base_text);
721 Self::new_normalized(replica_id, remote_id, line_ending, Rope::from(&*base_text))
722 }
723
724 pub fn new_normalized(
725 replica_id: ReplicaId,
726 remote_id: BufferId,
727 line_ending: LineEnding,
728 normalized: Rope,
729 ) -> Buffer {
730 let history = History::new(normalized);
731 let mut fragments = SumTree::new(&None);
732 let mut insertions = SumTree::default();
733
734 let mut lamport_clock = clock::Lamport::new(replica_id);
735 let mut version = clock::Global::new();
736
737 let visible_text = history.base_text.clone();
738 if !visible_text.is_empty() {
739 let insertion_timestamp = clock::Lamport::new(ReplicaId::LOCAL);
740 lamport_clock.observe(insertion_timestamp);
741 version.observe(insertion_timestamp);
742 let fragment_id = Locator::between(&Locator::min(), &Locator::max());
743 let fragment = Fragment {
744 id: fragment_id,
745 timestamp: insertion_timestamp,
746 insertion_offset: 0,
747 len: visible_text.len(),
748 visible: true,
749 deletions: Default::default(),
750 max_undos: Default::default(),
751 };
752 insertions.push(InsertionFragment::new(&fragment), ());
753 fragments.push(fragment, &None);
754 }
755
756 Buffer {
757 snapshot: BufferSnapshot {
758 replica_id,
759 remote_id,
760 visible_text,
761 deleted_text: Rope::new(),
762 line_ending,
763 fragments,
764 insertions,
765 version,
766 undo_map: Default::default(),
767 insertion_slices: Default::default(),
768 },
769 history,
770 deferred_ops: OperationQueue::new(),
771 deferred_replicas: HashSet::default(),
772 lamport_clock,
773 subscriptions: Default::default(),
774 edit_id_resolvers: Default::default(),
775 wait_for_version_txs: Default::default(),
776 }
777 }
778
779 pub fn version(&self) -> clock::Global {
780 self.version.clone()
781 }
782
783 pub fn snapshot(&self) -> &BufferSnapshot {
784 &self.snapshot
785 }
786
787 pub fn into_snapshot(self) -> BufferSnapshot {
788 self.snapshot
789 }
790
791 pub fn branch(&self) -> Self {
792 Self {
793 snapshot: self.snapshot.clone(),
794 history: History::new(self.base_text().clone()),
795 deferred_ops: OperationQueue::new(),
796 deferred_replicas: HashSet::default(),
797 lamport_clock: clock::Lamport::new(ReplicaId::LOCAL_BRANCH),
798 subscriptions: Default::default(),
799 edit_id_resolvers: Default::default(),
800 wait_for_version_txs: Default::default(),
801 }
802 }
803
804 pub fn replica_id(&self) -> ReplicaId {
805 self.lamport_clock.replica_id
806 }
807
808 pub fn remote_id(&self) -> BufferId {
809 self.remote_id
810 }
811
812 pub fn deferred_ops_len(&self) -> usize {
813 self.deferred_ops.len()
814 }
815
816 pub fn transaction_group_interval(&self) -> Duration {
817 self.history.group_interval
818 }
819
820 pub fn edit<R, I, S, T>(&mut self, edits: R) -> Operation
821 where
822 R: IntoIterator<IntoIter = I>,
823 I: ExactSizeIterator<Item = (Range<S>, T)>,
824 S: ToOffset,
825 T: Into<Arc<str>>,
826 {
827 let edits = edits
828 .into_iter()
829 .map(|(range, new_text)| (range, new_text.into()));
830
831 self.start_transaction();
832 let timestamp = self.lamport_clock.tick();
833 let operation = Operation::Edit(self.apply_local_edit(edits, timestamp));
834
835 self.history.push(operation.clone());
836 self.history.push_undo(operation.timestamp());
837 self.snapshot.version.observe(operation.timestamp());
838 self.end_transaction();
839 operation
840 }
841
842 fn apply_local_edit<S: ToOffset, T: Into<Arc<str>>>(
843 &mut self,
844 edits: impl ExactSizeIterator<Item = (Range<S>, T)>,
845 timestamp: clock::Lamport,
846 ) -> EditOperation {
847 let mut edits_patch = Patch::default();
848 let mut edit_op = EditOperation {
849 timestamp,
850 version: self.version(),
851 ranges: Vec::with_capacity(edits.len()),
852 new_text: Vec::with_capacity(edits.len()),
853 };
854 let mut new_insertions = Vec::new();
855 let mut insertion_offset = 0;
856 let mut insertion_slices = Vec::new();
857
858 let mut edits = edits
859 .map(|(range, new_text)| (range.to_offset(&*self), new_text))
860 .peekable();
861
862 let mut new_ropes =
863 RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
864 let mut old_fragments = self.fragments.cursor::<FragmentTextSummary>(&None);
865 let mut new_fragments = old_fragments.slice(&edits.peek().unwrap().0.start, Bias::Right);
866 new_ropes.append(new_fragments.summary().text);
867
868 let mut fragment_start = old_fragments.start().visible;
869 for (range, new_text) in edits {
870 let new_text = LineEnding::normalize_arc(new_text.into());
871 let fragment_end = old_fragments.end().visible;
872
873 // If the current fragment ends before this range, then jump ahead to the first fragment
874 // that extends past the start of this range, reusing any intervening fragments.
875 if fragment_end < range.start {
876 // If the current fragment has been partially consumed, then consume the rest of it
877 // and advance to the next fragment before slicing.
878 if fragment_start > old_fragments.start().visible {
879 if fragment_end > fragment_start {
880 let mut suffix = old_fragments.item().unwrap().clone();
881 suffix.len = fragment_end - fragment_start;
882 suffix.insertion_offset += fragment_start - old_fragments.start().visible;
883 new_insertions.push(InsertionFragment::insert_new(&suffix));
884 new_ropes.push_fragment(&suffix, suffix.visible);
885 new_fragments.push(suffix, &None);
886 }
887 old_fragments.next();
888 }
889
890 let slice = old_fragments.slice(&range.start, Bias::Right);
891 new_ropes.append(slice.summary().text);
892 new_fragments.append(slice, &None);
893 fragment_start = old_fragments.start().visible;
894 }
895
896 let full_range_start = FullOffset(range.start + old_fragments.start().deleted);
897
898 // Preserve any portion of the current fragment that precedes this range.
899 if fragment_start < range.start {
900 let mut prefix = old_fragments.item().unwrap().clone();
901 prefix.len = range.start - fragment_start;
902 prefix.insertion_offset += fragment_start - old_fragments.start().visible;
903 prefix.id = Locator::between(&new_fragments.summary().max_id, &prefix.id);
904 new_insertions.push(InsertionFragment::insert_new(&prefix));
905 new_ropes.push_fragment(&prefix, prefix.visible);
906 new_fragments.push(prefix, &None);
907 fragment_start = range.start;
908 }
909
910 // Insert the new text before any existing fragments within the range.
911 if !new_text.is_empty() {
912 let new_start = new_fragments.summary().text.visible;
913
914 let fragment = Fragment {
915 id: Locator::between(
916 &new_fragments.summary().max_id,
917 old_fragments
918 .item()
919 .map_or(&Locator::max(), |old_fragment| &old_fragment.id),
920 ),
921 timestamp,
922 insertion_offset,
923 len: new_text.len(),
924 deletions: Default::default(),
925 max_undos: Default::default(),
926 visible: true,
927 };
928 edits_patch.push(Edit {
929 old: fragment_start..fragment_start,
930 new: new_start..new_start + new_text.len(),
931 });
932 insertion_slices.push(InsertionSlice::from_fragment(timestamp, &fragment));
933 new_insertions.push(InsertionFragment::insert_new(&fragment));
934 new_ropes.push_str(new_text.as_ref());
935 new_fragments.push(fragment, &None);
936 insertion_offset += new_text.len();
937 }
938
939 // Advance through every fragment that intersects this range, marking the intersecting
940 // portions as deleted.
941 while fragment_start < range.end {
942 let fragment = old_fragments.item().unwrap();
943 let fragment_end = old_fragments.end().visible;
944 let mut intersection = fragment.clone();
945 let intersection_end = cmp::min(range.end, fragment_end);
946 if fragment.visible {
947 intersection.len = intersection_end - fragment_start;
948 intersection.insertion_offset += fragment_start - old_fragments.start().visible;
949 intersection.id =
950 Locator::between(&new_fragments.summary().max_id, &intersection.id);
951 intersection.deletions.insert(timestamp);
952 intersection.visible = false;
953 }
954 if intersection.len > 0 {
955 if fragment.visible && !intersection.visible {
956 let new_start = new_fragments.summary().text.visible;
957 edits_patch.push(Edit {
958 old: fragment_start..intersection_end,
959 new: new_start..new_start,
960 });
961 insertion_slices
962 .push(InsertionSlice::from_fragment(timestamp, &intersection));
963 }
964 new_insertions.push(InsertionFragment::insert_new(&intersection));
965 new_ropes.push_fragment(&intersection, fragment.visible);
966 new_fragments.push(intersection, &None);
967 fragment_start = intersection_end;
968 }
969 if fragment_end <= range.end {
970 old_fragments.next();
971 }
972 }
973
974 let full_range_end = FullOffset(range.end + old_fragments.start().deleted);
975 edit_op.ranges.push(full_range_start..full_range_end);
976 edit_op.new_text.push(new_text);
977 }
978
979 // If the current fragment has been partially consumed, then consume the rest of it
980 // and advance to the next fragment before slicing.
981 if fragment_start > old_fragments.start().visible {
982 let fragment_end = old_fragments.end().visible;
983 if fragment_end > fragment_start {
984 let mut suffix = old_fragments.item().unwrap().clone();
985 suffix.len = fragment_end - fragment_start;
986 suffix.insertion_offset += fragment_start - old_fragments.start().visible;
987 new_insertions.push(InsertionFragment::insert_new(&suffix));
988 new_ropes.push_fragment(&suffix, suffix.visible);
989 new_fragments.push(suffix, &None);
990 }
991 old_fragments.next();
992 }
993
994 let suffix = old_fragments.suffix();
995 new_ropes.append(suffix.summary().text);
996 new_fragments.append(suffix, &None);
997 let (visible_text, deleted_text) = new_ropes.finish();
998 drop(old_fragments);
999
1000 self.snapshot.fragments = new_fragments;
1001 self.snapshot.insertions.edit(new_insertions, ());
1002 self.snapshot.visible_text = visible_text;
1003 self.snapshot.deleted_text = deleted_text;
1004 self.subscriptions.publish_mut(&edits_patch);
1005 self.snapshot.insertion_slices.extend(insertion_slices);
1006 edit_op
1007 }
1008
1009 pub fn set_line_ending(&mut self, line_ending: LineEnding) {
1010 self.snapshot.line_ending = line_ending;
1011 }
1012
1013 pub fn apply_ops<I: IntoIterator<Item = Operation>>(&mut self, ops: I) {
1014 let mut deferred_ops = Vec::new();
1015 for op in ops {
1016 self.history.push(op.clone());
1017 if self.can_apply_op(&op) {
1018 self.apply_op(op);
1019 } else {
1020 self.deferred_replicas.insert(op.replica_id());
1021 deferred_ops.push(op);
1022 }
1023 }
1024 self.deferred_ops.insert(deferred_ops);
1025 self.flush_deferred_ops();
1026 }
1027
1028 fn apply_op(&mut self, op: Operation) {
1029 match op {
1030 Operation::Edit(edit) => {
1031 if !self.version.observed(edit.timestamp) {
1032 self.apply_remote_edit(
1033 &edit.version,
1034 &edit.ranges,
1035 &edit.new_text,
1036 edit.timestamp,
1037 );
1038 self.snapshot.version.observe(edit.timestamp);
1039 self.lamport_clock.observe(edit.timestamp);
1040 self.resolve_edit(edit.timestamp);
1041 }
1042 }
1043 Operation::Undo(undo) => {
1044 if !self.version.observed(undo.timestamp) {
1045 self.apply_undo(&undo);
1046 self.snapshot.version.observe(undo.timestamp);
1047 self.lamport_clock.observe(undo.timestamp);
1048 }
1049 }
1050 }
1051 self.wait_for_version_txs.retain_mut(|(version, tx)| {
1052 if self.snapshot.version().observed_all(version) {
1053 tx.try_send(()).ok();
1054 false
1055 } else {
1056 true
1057 }
1058 });
1059 }
1060
1061 fn apply_remote_edit(
1062 &mut self,
1063 version: &clock::Global,
1064 ranges: &[Range<FullOffset>],
1065 new_text: &[Arc<str>],
1066 timestamp: clock::Lamport,
1067 ) {
1068 if ranges.is_empty() {
1069 return;
1070 }
1071
1072 let edits = ranges.iter().zip(new_text.iter());
1073 let mut edits_patch = Patch::default();
1074 let mut insertion_slices = Vec::new();
1075 let cx = Some(version.clone());
1076 let mut new_insertions = Vec::new();
1077 let mut insertion_offset = 0;
1078 let mut new_ropes =
1079 RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
1080 let mut old_fragments = self
1081 .fragments
1082 .cursor::<Dimensions<VersionedFullOffset, usize>>(&cx);
1083 let mut new_fragments =
1084 old_fragments.slice(&VersionedFullOffset::Offset(ranges[0].start), Bias::Left);
1085 new_ropes.append(new_fragments.summary().text);
1086
1087 let mut fragment_start = old_fragments.start().0.full_offset();
1088 for (range, new_text) in edits {
1089 let fragment_end = old_fragments.end().0.full_offset();
1090
1091 // If the current fragment ends before this range, then jump ahead to the first fragment
1092 // that extends past the start of this range, reusing any intervening fragments.
1093 if fragment_end < range.start {
1094 // If the current fragment has been partially consumed, then consume the rest of it
1095 // and advance to the next fragment before slicing.
1096 if fragment_start > old_fragments.start().0.full_offset() {
1097 if fragment_end > fragment_start {
1098 let mut suffix = old_fragments.item().unwrap().clone();
1099 suffix.len = fragment_end.0 - fragment_start.0;
1100 suffix.insertion_offset +=
1101 fragment_start - old_fragments.start().0.full_offset();
1102 new_insertions.push(InsertionFragment::insert_new(&suffix));
1103 new_ropes.push_fragment(&suffix, suffix.visible);
1104 new_fragments.push(suffix, &None);
1105 }
1106 old_fragments.next();
1107 }
1108
1109 let slice =
1110 old_fragments.slice(&VersionedFullOffset::Offset(range.start), Bias::Left);
1111 new_ropes.append(slice.summary().text);
1112 new_fragments.append(slice, &None);
1113 fragment_start = old_fragments.start().0.full_offset();
1114 }
1115
1116 // If we are at the end of a non-concurrent fragment, advance to the next one.
1117 let fragment_end = old_fragments.end().0.full_offset();
1118 if fragment_end == range.start && fragment_end > fragment_start {
1119 let mut fragment = old_fragments.item().unwrap().clone();
1120 fragment.len = fragment_end.0 - fragment_start.0;
1121 fragment.insertion_offset += fragment_start - old_fragments.start().0.full_offset();
1122 new_insertions.push(InsertionFragment::insert_new(&fragment));
1123 new_ropes.push_fragment(&fragment, fragment.visible);
1124 new_fragments.push(fragment, &None);
1125 old_fragments.next();
1126 fragment_start = old_fragments.start().0.full_offset();
1127 }
1128
1129 // Skip over insertions that are concurrent to this edit, but have a lower lamport
1130 // timestamp.
1131 while let Some(fragment) = old_fragments.item() {
1132 if fragment_start == range.start && fragment.timestamp > timestamp {
1133 new_ropes.push_fragment(fragment, fragment.visible);
1134 new_fragments.push(fragment.clone(), &None);
1135 old_fragments.next();
1136 debug_assert_eq!(fragment_start, range.start);
1137 } else {
1138 break;
1139 }
1140 }
1141 debug_assert!(fragment_start <= range.start);
1142
1143 // Preserve any portion of the current fragment that precedes this range.
1144 if fragment_start < range.start {
1145 let mut prefix = old_fragments.item().unwrap().clone();
1146 prefix.len = range.start.0 - fragment_start.0;
1147 prefix.insertion_offset += fragment_start - old_fragments.start().0.full_offset();
1148 prefix.id = Locator::between(&new_fragments.summary().max_id, &prefix.id);
1149 new_insertions.push(InsertionFragment::insert_new(&prefix));
1150 fragment_start = range.start;
1151 new_ropes.push_fragment(&prefix, prefix.visible);
1152 new_fragments.push(prefix, &None);
1153 }
1154
1155 // Insert the new text before any existing fragments within the range.
1156 if !new_text.is_empty() {
1157 let mut old_start = old_fragments.start().1;
1158 if old_fragments.item().is_some_and(|f| f.visible) {
1159 old_start += fragment_start.0 - old_fragments.start().0.full_offset().0;
1160 }
1161 let new_start = new_fragments.summary().text.visible;
1162 let fragment = Fragment {
1163 id: Locator::between(
1164 &new_fragments.summary().max_id,
1165 old_fragments
1166 .item()
1167 .map_or(&Locator::max(), |old_fragment| &old_fragment.id),
1168 ),
1169 timestamp,
1170 insertion_offset,
1171 len: new_text.len(),
1172 deletions: Default::default(),
1173 max_undos: Default::default(),
1174 visible: true,
1175 };
1176 edits_patch.push(Edit {
1177 old: old_start..old_start,
1178 new: new_start..new_start + new_text.len(),
1179 });
1180 insertion_slices.push(InsertionSlice::from_fragment(timestamp, &fragment));
1181 new_insertions.push(InsertionFragment::insert_new(&fragment));
1182 new_ropes.push_str(new_text);
1183 new_fragments.push(fragment, &None);
1184 insertion_offset += new_text.len();
1185 }
1186
1187 // Advance through every fragment that intersects this range, marking the intersecting
1188 // portions as deleted.
1189 while fragment_start < range.end {
1190 let fragment = old_fragments.item().unwrap();
1191 let fragment_end = old_fragments.end().0.full_offset();
1192 let mut intersection = fragment.clone();
1193 let intersection_end = cmp::min(range.end, fragment_end);
1194 if fragment.was_visible(version, &self.undo_map) {
1195 intersection.len = intersection_end.0 - fragment_start.0;
1196 intersection.insertion_offset +=
1197 fragment_start - old_fragments.start().0.full_offset();
1198 intersection.id =
1199 Locator::between(&new_fragments.summary().max_id, &intersection.id);
1200 intersection.deletions.insert(timestamp);
1201 intersection.visible = false;
1202 insertion_slices.push(InsertionSlice::from_fragment(timestamp, &intersection));
1203 }
1204 if intersection.len > 0 {
1205 if fragment.visible && !intersection.visible {
1206 let old_start = old_fragments.start().1
1207 + (fragment_start.0 - old_fragments.start().0.full_offset().0);
1208 let new_start = new_fragments.summary().text.visible;
1209 edits_patch.push(Edit {
1210 old: old_start..old_start + intersection.len,
1211 new: new_start..new_start,
1212 });
1213 }
1214 new_insertions.push(InsertionFragment::insert_new(&intersection));
1215 new_ropes.push_fragment(&intersection, fragment.visible);
1216 new_fragments.push(intersection, &None);
1217 fragment_start = intersection_end;
1218 }
1219 if fragment_end <= range.end {
1220 old_fragments.next();
1221 }
1222 }
1223 }
1224
1225 // If the current fragment has been partially consumed, then consume the rest of it
1226 // and advance to the next fragment before slicing.
1227 if fragment_start > old_fragments.start().0.full_offset() {
1228 let fragment_end = old_fragments.end().0.full_offset();
1229 if fragment_end > fragment_start {
1230 let mut suffix = old_fragments.item().unwrap().clone();
1231 suffix.len = fragment_end.0 - fragment_start.0;
1232 suffix.insertion_offset += fragment_start - old_fragments.start().0.full_offset();
1233 new_insertions.push(InsertionFragment::insert_new(&suffix));
1234 new_ropes.push_fragment(&suffix, suffix.visible);
1235 new_fragments.push(suffix, &None);
1236 }
1237 old_fragments.next();
1238 }
1239
1240 let suffix = old_fragments.suffix();
1241 new_ropes.append(suffix.summary().text);
1242 new_fragments.append(suffix, &None);
1243 let (visible_text, deleted_text) = new_ropes.finish();
1244 drop(old_fragments);
1245
1246 self.snapshot.fragments = new_fragments;
1247 self.snapshot.visible_text = visible_text;
1248 self.snapshot.deleted_text = deleted_text;
1249 self.snapshot.insertions.edit(new_insertions, ());
1250 self.snapshot.insertion_slices.extend(insertion_slices);
1251 self.subscriptions.publish_mut(&edits_patch)
1252 }
1253
1254 fn fragment_ids_for_edits<'a>(
1255 &'a self,
1256 edit_ids: impl Iterator<Item = &'a clock::Lamport>,
1257 ) -> Vec<&'a Locator> {
1258 // Get all of the insertion slices changed by the given edits.
1259 let mut insertion_slices = Vec::new();
1260 for edit_id in edit_ids {
1261 let insertion_slice = InsertionSlice {
1262 edit_id: *edit_id,
1263 insertion_id: clock::Lamport::MIN,
1264 range: 0..0,
1265 };
1266 let slices = self
1267 .snapshot
1268 .insertion_slices
1269 .iter_from(&insertion_slice)
1270 .take_while(|slice| slice.edit_id == *edit_id);
1271 insertion_slices.extend(slices)
1272 }
1273 insertion_slices
1274 .sort_unstable_by_key(|s| (s.insertion_id, s.range.start, Reverse(s.range.end)));
1275
1276 // Get all of the fragments corresponding to these insertion slices.
1277 let mut fragment_ids = Vec::new();
1278 let mut insertions_cursor = self.insertions.cursor::<InsertionFragmentKey>(());
1279 for insertion_slice in &insertion_slices {
1280 if insertion_slice.insertion_id != insertions_cursor.start().timestamp
1281 || insertion_slice.range.start > insertions_cursor.start().split_offset
1282 {
1283 insertions_cursor.seek_forward(
1284 &InsertionFragmentKey {
1285 timestamp: insertion_slice.insertion_id,
1286 split_offset: insertion_slice.range.start,
1287 },
1288 Bias::Left,
1289 );
1290 }
1291 while let Some(item) = insertions_cursor.item() {
1292 if item.timestamp != insertion_slice.insertion_id
1293 || item.split_offset >= insertion_slice.range.end
1294 {
1295 break;
1296 }
1297 fragment_ids.push(&item.fragment_id);
1298 insertions_cursor.next();
1299 }
1300 }
1301 fragment_ids.sort_unstable();
1302 fragment_ids
1303 }
1304
1305 fn apply_undo(&mut self, undo: &UndoOperation) {
1306 self.snapshot.undo_map.insert(undo);
1307
1308 let mut edits = Patch::default();
1309 let mut old_fragments = self
1310 .fragments
1311 .cursor::<Dimensions<Option<&Locator>, usize>>(&None);
1312 let mut new_fragments = SumTree::new(&None);
1313 let mut new_ropes =
1314 RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
1315
1316 for fragment_id in self.fragment_ids_for_edits(undo.counts.keys()) {
1317 let preceding_fragments = old_fragments.slice(&Some(fragment_id), Bias::Left);
1318 new_ropes.append(preceding_fragments.summary().text);
1319 new_fragments.append(preceding_fragments, &None);
1320
1321 if let Some(fragment) = old_fragments.item() {
1322 let mut fragment = fragment.clone();
1323 let fragment_was_visible = fragment.visible;
1324
1325 fragment.visible = fragment.is_visible(&self.undo_map);
1326 fragment.max_undos.observe(undo.timestamp);
1327
1328 let old_start = old_fragments.start().1;
1329 let new_start = new_fragments.summary().text.visible;
1330 if fragment_was_visible && !fragment.visible {
1331 edits.push(Edit {
1332 old: old_start..old_start + fragment.len,
1333 new: new_start..new_start,
1334 });
1335 } else if !fragment_was_visible && fragment.visible {
1336 edits.push(Edit {
1337 old: old_start..old_start,
1338 new: new_start..new_start + fragment.len,
1339 });
1340 }
1341 new_ropes.push_fragment(&fragment, fragment_was_visible);
1342 new_fragments.push(fragment, &None);
1343
1344 old_fragments.next();
1345 }
1346 }
1347
1348 let suffix = old_fragments.suffix();
1349 new_ropes.append(suffix.summary().text);
1350 new_fragments.append(suffix, &None);
1351
1352 drop(old_fragments);
1353 let (visible_text, deleted_text) = new_ropes.finish();
1354 self.snapshot.fragments = new_fragments;
1355 self.snapshot.visible_text = visible_text;
1356 self.snapshot.deleted_text = deleted_text;
1357 self.subscriptions.publish_mut(&edits);
1358 }
1359
1360 fn flush_deferred_ops(&mut self) {
1361 self.deferred_replicas.clear();
1362 let mut deferred_ops = Vec::new();
1363 for op in self.deferred_ops.drain().iter().cloned() {
1364 if self.can_apply_op(&op) {
1365 self.apply_op(op);
1366 } else {
1367 self.deferred_replicas.insert(op.replica_id());
1368 deferred_ops.push(op);
1369 }
1370 }
1371 self.deferred_ops.insert(deferred_ops);
1372 }
1373
1374 fn can_apply_op(&self, op: &Operation) -> bool {
1375 if self.deferred_replicas.contains(&op.replica_id()) {
1376 false
1377 } else {
1378 self.version.observed_all(match op {
1379 Operation::Edit(edit) => &edit.version,
1380 Operation::Undo(undo) => &undo.version,
1381 })
1382 }
1383 }
1384
1385 pub fn has_deferred_ops(&self) -> bool {
1386 !self.deferred_ops.is_empty()
1387 }
1388
1389 pub fn peek_undo_stack(&self) -> Option<&HistoryEntry> {
1390 self.history.undo_stack.last()
1391 }
1392
1393 pub fn peek_redo_stack(&self) -> Option<&HistoryEntry> {
1394 self.history.redo_stack.last()
1395 }
1396
1397 pub fn start_transaction(&mut self) -> Option<TransactionId> {
1398 self.start_transaction_at(Instant::now())
1399 }
1400
1401 pub fn start_transaction_at(&mut self, now: Instant) -> Option<TransactionId> {
1402 self.history
1403 .start_transaction(self.version.clone(), now, &mut self.lamport_clock)
1404 }
1405
1406 pub fn end_transaction(&mut self) -> Option<(TransactionId, clock::Global)> {
1407 self.end_transaction_at(Instant::now())
1408 }
1409
1410 pub fn end_transaction_at(&mut self, now: Instant) -> Option<(TransactionId, clock::Global)> {
1411 if let Some(entry) = self.history.end_transaction(now) {
1412 let since = entry.transaction.start.clone();
1413 let id = self.history.group().unwrap();
1414 Some((id, since))
1415 } else {
1416 None
1417 }
1418 }
1419
1420 pub fn finalize_last_transaction(&mut self) -> Option<&Transaction> {
1421 self.history.finalize_last_transaction()
1422 }
1423
1424 pub fn group_until_transaction(&mut self, transaction_id: TransactionId) {
1425 self.history.group_until(transaction_id);
1426 }
1427
1428 pub fn base_text(&self) -> &Rope {
1429 &self.history.base_text
1430 }
1431
1432 pub fn operations(&self) -> &TreeMap<clock::Lamport, Operation> {
1433 &self.history.operations
1434 }
1435
1436 pub fn undo(&mut self) -> Option<(TransactionId, Operation)> {
1437 if let Some(entry) = self.history.pop_undo() {
1438 let transaction = entry.transaction.clone();
1439 let transaction_id = transaction.id;
1440 let op = self.undo_or_redo(transaction);
1441 Some((transaction_id, op))
1442 } else {
1443 None
1444 }
1445 }
1446
1447 pub fn undo_transaction(&mut self, transaction_id: TransactionId) -> Option<Operation> {
1448 let transaction = self
1449 .history
1450 .remove_from_undo(transaction_id)?
1451 .transaction
1452 .clone();
1453 Some(self.undo_or_redo(transaction))
1454 }
1455
1456 pub fn undo_to_transaction(&mut self, transaction_id: TransactionId) -> Vec<Operation> {
1457 let transactions = self
1458 .history
1459 .remove_from_undo_until(transaction_id)
1460 .iter()
1461 .map(|entry| entry.transaction.clone())
1462 .collect::<Vec<_>>();
1463
1464 transactions
1465 .into_iter()
1466 .map(|transaction| self.undo_or_redo(transaction))
1467 .collect()
1468 }
1469
1470 pub fn forget_transaction(&mut self, transaction_id: TransactionId) -> Option<Transaction> {
1471 self.history.forget(transaction_id)
1472 }
1473
1474 pub fn get_transaction(&self, transaction_id: TransactionId) -> Option<&Transaction> {
1475 self.history.transaction(transaction_id)
1476 }
1477
1478 pub fn merge_transactions(&mut self, transaction: TransactionId, destination: TransactionId) {
1479 self.history.merge_transactions(transaction, destination);
1480 }
1481
1482 pub fn redo(&mut self) -> Option<(TransactionId, Operation)> {
1483 if let Some(entry) = self.history.pop_redo() {
1484 let transaction = entry.transaction.clone();
1485 let transaction_id = transaction.id;
1486 let op = self.undo_or_redo(transaction);
1487 Some((transaction_id, op))
1488 } else {
1489 None
1490 }
1491 }
1492
1493 pub fn redo_to_transaction(&mut self, transaction_id: TransactionId) -> Vec<Operation> {
1494 let transactions = self
1495 .history
1496 .remove_from_redo(transaction_id)
1497 .iter()
1498 .map(|entry| entry.transaction.clone())
1499 .collect::<Vec<_>>();
1500
1501 transactions
1502 .into_iter()
1503 .map(|transaction| self.undo_or_redo(transaction))
1504 .collect()
1505 }
1506
1507 fn undo_or_redo(&mut self, transaction: Transaction) -> Operation {
1508 let mut counts = HashMap::default();
1509 for edit_id in transaction.edit_ids {
1510 counts.insert(edit_id, self.undo_map.undo_count(edit_id).saturating_add(1));
1511 }
1512
1513 let operation = self.undo_operations(counts);
1514 self.history.push(operation.clone());
1515 operation
1516 }
1517
1518 pub fn undo_operations(&mut self, counts: HashMap<clock::Lamport, u32>) -> Operation {
1519 let timestamp = self.lamport_clock.tick();
1520 let version = self.version();
1521 self.snapshot.version.observe(timestamp);
1522 let undo = UndoOperation {
1523 timestamp,
1524 version,
1525 counts,
1526 };
1527 self.apply_undo(&undo);
1528 Operation::Undo(undo)
1529 }
1530
1531 pub fn push_transaction(&mut self, transaction: Transaction, now: Instant) {
1532 self.history.push_transaction(transaction, now);
1533 }
1534
1535 /// Differs from `push_transaction` in that it does not clear the redo stack.
1536 /// The caller responsible for
1537 /// Differs from `push_transaction` in that it does not clear the redo
1538 /// stack. Intended to be used to create a parent transaction to merge
1539 /// potential child transactions into.
1540 ///
1541 /// The caller is responsible for removing it from the undo history using
1542 /// `forget_transaction` if no edits are merged into it. Otherwise, if edits
1543 /// are merged into this transaction, the caller is responsible for ensuring
1544 /// the redo stack is cleared. The easiest way to ensure the redo stack is
1545 /// cleared is to create transactions with the usual `start_transaction` and
1546 /// `end_transaction` methods and merging the resulting transactions into
1547 /// the transaction created by this method
1548 pub fn push_empty_transaction(&mut self, now: Instant) -> TransactionId {
1549 self.history
1550 .push_empty_transaction(self.version.clone(), now, &mut self.lamport_clock)
1551 }
1552
1553 pub fn edited_ranges_for_transaction_id<D>(
1554 &self,
1555 transaction_id: TransactionId,
1556 ) -> impl '_ + Iterator<Item = Range<D>>
1557 where
1558 D: TextDimension,
1559 {
1560 self.history
1561 .transaction(transaction_id)
1562 .into_iter()
1563 .flat_map(|transaction| self.edited_ranges_for_transaction(transaction))
1564 }
1565
1566 pub fn edited_ranges_for_edit_ids<'a, D>(
1567 &'a self,
1568 edit_ids: impl IntoIterator<Item = &'a clock::Lamport>,
1569 ) -> impl 'a + Iterator<Item = Range<D>>
1570 where
1571 D: TextDimension,
1572 {
1573 // get fragment ranges
1574 let mut cursor = self
1575 .fragments
1576 .cursor::<Dimensions<Option<&Locator>, usize>>(&None);
1577 let offset_ranges = self
1578 .fragment_ids_for_edits(edit_ids.into_iter())
1579 .into_iter()
1580 .filter_map(move |fragment_id| {
1581 cursor.seek_forward(&Some(fragment_id), Bias::Left);
1582 let fragment = cursor.item()?;
1583 let start_offset = cursor.start().1;
1584 let end_offset = start_offset + if fragment.visible { fragment.len } else { 0 };
1585 Some(start_offset..end_offset)
1586 });
1587
1588 // combine adjacent ranges
1589 let mut prev_range: Option<Range<usize>> = None;
1590 let disjoint_ranges = offset_ranges
1591 .map(Some)
1592 .chain([None])
1593 .filter_map(move |range| {
1594 if let Some((range, prev_range)) = range.as_ref().zip(prev_range.as_mut())
1595 && prev_range.end == range.start
1596 {
1597 prev_range.end = range.end;
1598 return None;
1599 }
1600 let result = prev_range.clone();
1601 prev_range = range;
1602 result
1603 });
1604
1605 // convert to the desired text dimension.
1606 let mut position = D::zero(());
1607 let mut rope_cursor = self.visible_text.cursor(0);
1608 disjoint_ranges.map(move |range| {
1609 position.add_assign(&rope_cursor.summary(range.start));
1610 let start = position;
1611 position.add_assign(&rope_cursor.summary(range.end));
1612 let end = position;
1613 start..end
1614 })
1615 }
1616
1617 pub fn edited_ranges_for_transaction<'a, D>(
1618 &'a self,
1619 transaction: &'a Transaction,
1620 ) -> impl 'a + Iterator<Item = Range<D>>
1621 where
1622 D: TextDimension,
1623 {
1624 self.edited_ranges_for_edit_ids(&transaction.edit_ids)
1625 }
1626
1627 pub fn subscribe(&mut self) -> Subscription<usize> {
1628 self.subscriptions.subscribe()
1629 }
1630
1631 pub fn wait_for_edits<It: IntoIterator<Item = clock::Lamport>>(
1632 &mut self,
1633 edit_ids: It,
1634 ) -> impl 'static + Future<Output = Result<()>> + use<It> {
1635 let mut futures = Vec::new();
1636 for edit_id in edit_ids {
1637 if !self.version.observed(edit_id) {
1638 let (tx, rx) = oneshot::channel();
1639 self.edit_id_resolvers.entry(edit_id).or_default().push(tx);
1640 futures.push(rx);
1641 }
1642 }
1643
1644 async move {
1645 for mut future in futures {
1646 if future.recv().await.is_none() {
1647 anyhow::bail!("gave up waiting for edits");
1648 }
1649 }
1650 Ok(())
1651 }
1652 }
1653
1654 pub fn wait_for_anchors<It: IntoIterator<Item = Anchor>>(
1655 &mut self,
1656 anchors: It,
1657 ) -> impl 'static + Future<Output = Result<()>> + use<It> {
1658 let mut futures = Vec::new();
1659 for anchor in anchors {
1660 if !self.version.observed(anchor.timestamp) && !anchor.is_max() && !anchor.is_min() {
1661 let (tx, rx) = oneshot::channel();
1662 self.edit_id_resolvers
1663 .entry(anchor.timestamp)
1664 .or_default()
1665 .push(tx);
1666 futures.push(rx);
1667 }
1668 }
1669
1670 async move {
1671 for mut future in futures {
1672 if future.recv().await.is_none() {
1673 anyhow::bail!("gave up waiting for anchors");
1674 }
1675 }
1676 Ok(())
1677 }
1678 }
1679
1680 pub fn wait_for_version(
1681 &mut self,
1682 version: clock::Global,
1683 ) -> impl Future<Output = Result<()>> + use<> {
1684 let mut rx = None;
1685 if !self.snapshot.version.observed_all(&version) {
1686 let channel = oneshot::channel();
1687 self.wait_for_version_txs.push((version, channel.0));
1688 rx = Some(channel.1);
1689 }
1690 async move {
1691 if let Some(mut rx) = rx
1692 && rx.recv().await.is_none()
1693 {
1694 anyhow::bail!("gave up waiting for version");
1695 }
1696 Ok(())
1697 }
1698 }
1699
1700 pub fn give_up_waiting(&mut self) {
1701 self.edit_id_resolvers.clear();
1702 self.wait_for_version_txs.clear();
1703 }
1704
1705 fn resolve_edit(&mut self, edit_id: clock::Lamport) {
1706 for mut tx in self
1707 .edit_id_resolvers
1708 .remove(&edit_id)
1709 .into_iter()
1710 .flatten()
1711 {
1712 tx.try_send(()).ok();
1713 }
1714 }
1715}
1716
1717#[cfg(any(test, feature = "test-support"))]
1718impl Buffer {
1719 #[track_caller]
1720 pub fn edit_via_marked_text(&mut self, marked_string: &str) {
1721 let edits = self.edits_for_marked_text(marked_string);
1722 self.edit(edits);
1723 }
1724
1725 #[track_caller]
1726 pub fn edits_for_marked_text(&self, marked_string: &str) -> Vec<(Range<usize>, String)> {
1727 let old_text = self.text();
1728 let (new_text, mut ranges) = util::test::marked_text_ranges(marked_string, false);
1729 if ranges.is_empty() {
1730 ranges.push(0..new_text.len());
1731 }
1732
1733 assert_eq!(
1734 old_text[..ranges[0].start],
1735 new_text[..ranges[0].start],
1736 "invalid edit"
1737 );
1738
1739 let mut delta = 0;
1740 let mut edits = Vec::new();
1741 let mut ranges = ranges.into_iter().peekable();
1742
1743 while let Some(inserted_range) = ranges.next() {
1744 let new_start = inserted_range.start;
1745 let old_start = (new_start as isize - delta) as usize;
1746
1747 let following_text = if let Some(next_range) = ranges.peek() {
1748 &new_text[inserted_range.end..next_range.start]
1749 } else {
1750 &new_text[inserted_range.end..]
1751 };
1752
1753 let inserted_len = inserted_range.len();
1754 let deleted_len = old_text[old_start..]
1755 .find(following_text)
1756 .expect("invalid edit");
1757
1758 let old_range = old_start..old_start + deleted_len;
1759 edits.push((old_range, new_text[inserted_range].to_string()));
1760 delta += inserted_len as isize - deleted_len as isize;
1761 }
1762
1763 assert_eq!(
1764 old_text.len() as isize + delta,
1765 new_text.len() as isize,
1766 "invalid edit"
1767 );
1768
1769 edits
1770 }
1771
1772 pub fn check_invariants(&self) {
1773 // Ensure every fragment is ordered by locator in the fragment tree and corresponds
1774 // to an insertion fragment in the insertions tree.
1775 let mut prev_fragment_id = Locator::min();
1776 for fragment in self.snapshot.fragments.items(&None) {
1777 assert!(fragment.id > prev_fragment_id);
1778 prev_fragment_id = fragment.id.clone();
1779
1780 let insertion_fragment = self
1781 .snapshot
1782 .insertions
1783 .get(
1784 &InsertionFragmentKey {
1785 timestamp: fragment.timestamp,
1786 split_offset: fragment.insertion_offset,
1787 },
1788 (),
1789 )
1790 .unwrap();
1791 assert_eq!(
1792 insertion_fragment.fragment_id, fragment.id,
1793 "fragment: {:?}\ninsertion: {:?}",
1794 fragment, insertion_fragment
1795 );
1796 }
1797
1798 let mut cursor = self.snapshot.fragments.cursor::<Option<&Locator>>(&None);
1799 for insertion_fragment in self.snapshot.insertions.cursor::<()>(()) {
1800 cursor.seek(&Some(&insertion_fragment.fragment_id), Bias::Left);
1801 let fragment = cursor.item().unwrap();
1802 assert_eq!(insertion_fragment.fragment_id, fragment.id);
1803 assert_eq!(insertion_fragment.split_offset, fragment.insertion_offset);
1804 }
1805
1806 let fragment_summary = self.snapshot.fragments.summary();
1807 assert_eq!(
1808 fragment_summary.text.visible,
1809 self.snapshot.visible_text.len()
1810 );
1811 assert_eq!(
1812 fragment_summary.text.deleted,
1813 self.snapshot.deleted_text.len()
1814 );
1815
1816 assert!(!self.text().contains("\r\n"));
1817 }
1818
1819 pub fn set_group_interval(&mut self, group_interval: Duration) {
1820 self.history.group_interval = group_interval;
1821 }
1822
1823 pub fn random_byte_range(&self, start_offset: usize, rng: &mut impl rand::Rng) -> Range<usize> {
1824 let end = self.clip_offset(rng.random_range(start_offset..=self.len()), Bias::Right);
1825 let start = self.clip_offset(rng.random_range(start_offset..=end), Bias::Right);
1826 start..end
1827 }
1828
1829 pub fn get_random_edits<T>(
1830 &self,
1831 rng: &mut T,
1832 edit_count: usize,
1833 ) -> Vec<(Range<usize>, Arc<str>)>
1834 where
1835 T: rand::Rng,
1836 {
1837 let mut edits: Vec<(Range<usize>, Arc<str>)> = Vec::new();
1838 let mut last_end = None;
1839 for _ in 0..edit_count {
1840 if last_end.is_some_and(|last_end| last_end >= self.len()) {
1841 break;
1842 }
1843 let new_start = last_end.map_or(0, |last_end| last_end + 1);
1844 let range = self.random_byte_range(new_start, rng);
1845 last_end = Some(range.end);
1846
1847 let new_text_len = rng.random_range(0..10);
1848 let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
1849
1850 edits.push((range, new_text.into()));
1851 }
1852 edits
1853 }
1854
1855 pub fn randomly_edit<T>(
1856 &mut self,
1857 rng: &mut T,
1858 edit_count: usize,
1859 ) -> (Vec<(Range<usize>, Arc<str>)>, Operation)
1860 where
1861 T: rand::Rng,
1862 {
1863 let mut edits = self.get_random_edits(rng, edit_count);
1864 log::info!("mutating buffer {:?} with {:?}", self.replica_id, edits);
1865
1866 let op = self.edit(edits.iter().cloned());
1867 if let Operation::Edit(edit) = &op {
1868 assert_eq!(edits.len(), edit.new_text.len());
1869 for (edit, new_text) in edits.iter_mut().zip(&edit.new_text) {
1870 edit.1 = new_text.clone();
1871 }
1872 } else {
1873 unreachable!()
1874 }
1875
1876 (edits, op)
1877 }
1878
1879 pub fn randomly_undo_redo(&mut self, rng: &mut impl rand::Rng) -> Vec<Operation> {
1880 use rand::prelude::*;
1881
1882 let mut ops = Vec::new();
1883 for _ in 0..rng.random_range(1..=5) {
1884 if let Some(entry) = self.history.undo_stack.choose(rng) {
1885 let transaction = entry.transaction.clone();
1886 log::info!(
1887 "undoing buffer {:?} transaction {:?}",
1888 self.replica_id,
1889 transaction
1890 );
1891 ops.push(self.undo_or_redo(transaction));
1892 }
1893 }
1894 ops
1895 }
1896}
1897
1898impl Deref for Buffer {
1899 type Target = BufferSnapshot;
1900
1901 fn deref(&self) -> &Self::Target {
1902 &self.snapshot
1903 }
1904}
1905
1906impl BufferSnapshot {
1907 pub fn as_rope(&self) -> &Rope {
1908 &self.visible_text
1909 }
1910
1911 pub fn rope_for_version(&self, version: &clock::Global) -> Rope {
1912 let mut rope = Rope::new();
1913
1914 let mut cursor = self
1915 .fragments
1916 .filter::<_, FragmentTextSummary>(&None, move |summary| {
1917 !version.observed_all(&summary.max_version)
1918 });
1919 cursor.next();
1920
1921 let mut visible_cursor = self.visible_text.cursor(0);
1922 let mut deleted_cursor = self.deleted_text.cursor(0);
1923
1924 while let Some(fragment) = cursor.item() {
1925 if cursor.start().visible > visible_cursor.offset() {
1926 let text = visible_cursor.slice(cursor.start().visible);
1927 rope.append(text);
1928 }
1929
1930 if fragment.was_visible(version, &self.undo_map) {
1931 if fragment.visible {
1932 let text = visible_cursor.slice(cursor.end().visible);
1933 rope.append(text);
1934 } else {
1935 deleted_cursor.seek_forward(cursor.start().deleted);
1936 let text = deleted_cursor.slice(cursor.end().deleted);
1937 rope.append(text);
1938 }
1939 } else if fragment.visible {
1940 visible_cursor.seek_forward(cursor.end().visible);
1941 }
1942
1943 cursor.next();
1944 }
1945
1946 if cursor.start().visible > visible_cursor.offset() {
1947 let text = visible_cursor.slice(cursor.start().visible);
1948 rope.append(text);
1949 }
1950
1951 rope
1952 }
1953
1954 pub fn remote_id(&self) -> BufferId {
1955 self.remote_id
1956 }
1957
1958 pub fn replica_id(&self) -> ReplicaId {
1959 self.replica_id
1960 }
1961
1962 pub fn row_count(&self) -> u32 {
1963 self.max_point().row + 1
1964 }
1965
1966 pub fn len(&self) -> usize {
1967 self.visible_text.len()
1968 }
1969
1970 pub fn is_empty(&self) -> bool {
1971 self.len() == 0
1972 }
1973
1974 pub fn chars(&self) -> impl Iterator<Item = char> + '_ {
1975 self.chars_at(0)
1976 }
1977
1978 pub fn chars_for_range<T: ToOffset>(&self, range: Range<T>) -> impl Iterator<Item = char> + '_ {
1979 self.text_for_range(range).flat_map(str::chars)
1980 }
1981
1982 pub fn reversed_chars_for_range<T: ToOffset>(
1983 &self,
1984 range: Range<T>,
1985 ) -> impl Iterator<Item = char> + '_ {
1986 self.reversed_chunks_in_range(range)
1987 .flat_map(|chunk| chunk.chars().rev())
1988 }
1989
1990 pub fn contains_str_at<T>(&self, position: T, needle: &str) -> bool
1991 where
1992 T: ToOffset,
1993 {
1994 let position = position.to_offset(self);
1995 position == self.clip_offset(position, Bias::Left)
1996 && self
1997 .bytes_in_range(position..self.len())
1998 .flatten()
1999 .copied()
2000 .take(needle.len())
2001 .eq(needle.bytes())
2002 }
2003
2004 pub fn common_prefix_at<T>(&self, position: T, needle: &str) -> Range<T>
2005 where
2006 T: ToOffset + TextDimension,
2007 {
2008 let offset = position.to_offset(self);
2009 let common_prefix_len = needle
2010 .char_indices()
2011 .map(|(index, _)| index)
2012 .chain([needle.len()])
2013 .take_while(|&len| len <= offset)
2014 .filter(|&len| {
2015 let left = self
2016 .chars_for_range(offset - len..offset)
2017 .flat_map(char::to_lowercase);
2018 let right = needle[..len].chars().flat_map(char::to_lowercase);
2019 left.eq(right)
2020 })
2021 .last()
2022 .unwrap_or(0);
2023 let start_offset = offset - common_prefix_len;
2024 let start = self.text_summary_for_range(0..start_offset);
2025 start..position
2026 }
2027
2028 pub fn text(&self) -> String {
2029 self.visible_text.to_string()
2030 }
2031
2032 pub fn line_ending(&self) -> LineEnding {
2033 self.line_ending
2034 }
2035
2036 pub fn deleted_text(&self) -> String {
2037 self.deleted_text.to_string()
2038 }
2039
2040 pub fn fragments(&self) -> impl Iterator<Item = &Fragment> {
2041 self.fragments.iter()
2042 }
2043
2044 pub fn text_summary(&self) -> TextSummary {
2045 self.visible_text.summary()
2046 }
2047
2048 pub fn max_point(&self) -> Point {
2049 self.visible_text.max_point()
2050 }
2051
2052 pub fn max_point_utf16(&self) -> PointUtf16 {
2053 self.visible_text.max_point_utf16()
2054 }
2055
2056 pub fn point_to_offset(&self, point: Point) -> usize {
2057 self.visible_text.point_to_offset(point)
2058 }
2059
2060 pub fn point_to_offset_utf16(&self, point: Point) -> OffsetUtf16 {
2061 self.visible_text.point_to_offset_utf16(point)
2062 }
2063
2064 pub fn point_utf16_to_offset_utf16(&self, point: PointUtf16) -> OffsetUtf16 {
2065 self.visible_text.point_utf16_to_offset_utf16(point)
2066 }
2067
2068 pub fn point_utf16_to_offset(&self, point: PointUtf16) -> usize {
2069 self.visible_text.point_utf16_to_offset(point)
2070 }
2071
2072 pub fn unclipped_point_utf16_to_offset(&self, point: Unclipped<PointUtf16>) -> usize {
2073 self.visible_text.unclipped_point_utf16_to_offset(point)
2074 }
2075
2076 pub fn unclipped_point_utf16_to_point(&self, point: Unclipped<PointUtf16>) -> Point {
2077 self.visible_text.unclipped_point_utf16_to_point(point)
2078 }
2079
2080 pub fn offset_utf16_to_offset(&self, offset: OffsetUtf16) -> usize {
2081 self.visible_text.offset_utf16_to_offset(offset)
2082 }
2083
2084 pub fn offset_to_offset_utf16(&self, offset: usize) -> OffsetUtf16 {
2085 self.visible_text.offset_to_offset_utf16(offset)
2086 }
2087
2088 pub fn offset_to_point(&self, offset: usize) -> Point {
2089 self.visible_text.offset_to_point(offset)
2090 }
2091
2092 pub fn offset_to_point_utf16(&self, offset: usize) -> PointUtf16 {
2093 self.visible_text.offset_to_point_utf16(offset)
2094 }
2095
2096 pub fn point_to_point_utf16(&self, point: Point) -> PointUtf16 {
2097 self.visible_text.point_to_point_utf16(point)
2098 }
2099
2100 pub fn point_utf16_to_point(&self, point: PointUtf16) -> Point {
2101 self.visible_text.point_utf16_to_point(point)
2102 }
2103
2104 pub fn version(&self) -> &clock::Global {
2105 &self.version
2106 }
2107
2108 pub fn chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + '_ {
2109 let offset = position.to_offset(self);
2110 self.visible_text.chars_at(offset)
2111 }
2112
2113 pub fn reversed_chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + '_ {
2114 let offset = position.to_offset(self);
2115 self.visible_text.reversed_chars_at(offset)
2116 }
2117
2118 pub fn reversed_chunks_in_range<T: ToOffset>(&self, range: Range<T>) -> rope::Chunks<'_> {
2119 let range = range.start.to_offset(self)..range.end.to_offset(self);
2120 self.visible_text.reversed_chunks_in_range(range)
2121 }
2122
2123 pub fn bytes_in_range<T: ToOffset>(&self, range: Range<T>) -> rope::Bytes<'_> {
2124 let start = range.start.to_offset(self);
2125 let end = range.end.to_offset(self);
2126 self.visible_text.bytes_in_range(start..end)
2127 }
2128
2129 pub fn reversed_bytes_in_range<T: ToOffset>(&self, range: Range<T>) -> rope::Bytes<'_> {
2130 let start = range.start.to_offset(self);
2131 let end = range.end.to_offset(self);
2132 self.visible_text.reversed_bytes_in_range(start..end)
2133 }
2134
2135 pub fn text_for_range<T: ToOffset>(&self, range: Range<T>) -> Chunks<'_> {
2136 let start = range.start.to_offset(self);
2137 let end = range.end.to_offset(self);
2138 self.visible_text.chunks_in_range(start..end)
2139 }
2140
2141 pub fn line_len(&self, row: u32) -> u32 {
2142 let row_start_offset = Point::new(row, 0).to_offset(self);
2143 let row_end_offset = if row >= self.max_point().row {
2144 self.len()
2145 } else {
2146 Point::new(row + 1, 0).to_previous_offset(self)
2147 };
2148 (row_end_offset - row_start_offset) as u32
2149 }
2150
2151 pub fn line_indents_in_row_range(
2152 &self,
2153 row_range: Range<u32>,
2154 ) -> impl Iterator<Item = (u32, LineIndent)> + '_ {
2155 let start = Point::new(row_range.start, 0).to_offset(self);
2156 let end = Point::new(row_range.end, self.line_len(row_range.end)).to_offset(self);
2157
2158 let mut chunks = self.as_rope().chunks_in_range(start..end);
2159 let mut row = row_range.start;
2160 let mut done = false;
2161 std::iter::from_fn(move || {
2162 if done {
2163 None
2164 } else {
2165 let indent = (row, LineIndent::from_chunks(&mut chunks));
2166 done = !chunks.next_line();
2167 row += 1;
2168 Some(indent)
2169 }
2170 })
2171 }
2172
2173 /// Returns the line indents in the given row range, exclusive of end row, in reversed order.
2174 pub fn reversed_line_indents_in_row_range(
2175 &self,
2176 row_range: Range<u32>,
2177 ) -> impl Iterator<Item = (u32, LineIndent)> + '_ {
2178 let start = Point::new(row_range.start, 0).to_offset(self);
2179
2180 let end_point;
2181 let end;
2182 if row_range.end > row_range.start {
2183 end_point = Point::new(row_range.end - 1, self.line_len(row_range.end - 1));
2184 end = end_point.to_offset(self);
2185 } else {
2186 end_point = Point::new(row_range.start, 0);
2187 end = start;
2188 };
2189
2190 let mut chunks = self.as_rope().chunks_in_range(start..end);
2191 // Move the cursor to the start of the last line if it's not empty.
2192 chunks.seek(end);
2193 if end_point.column > 0 {
2194 chunks.prev_line();
2195 }
2196
2197 let mut row = end_point.row;
2198 let mut done = false;
2199 std::iter::from_fn(move || {
2200 if done {
2201 None
2202 } else {
2203 let initial_offset = chunks.offset();
2204 let indent = (row, LineIndent::from_chunks(&mut chunks));
2205 if chunks.offset() > initial_offset {
2206 chunks.prev_line();
2207 }
2208 done = !chunks.prev_line();
2209 if !done {
2210 row -= 1;
2211 }
2212
2213 Some(indent)
2214 }
2215 })
2216 }
2217
2218 pub fn line_indent_for_row(&self, row: u32) -> LineIndent {
2219 LineIndent::from_iter(self.chars_at(Point::new(row, 0)))
2220 }
2221
2222 pub fn is_line_blank(&self, row: u32) -> bool {
2223 self.text_for_range(Point::new(row, 0)..Point::new(row, self.line_len(row)))
2224 .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
2225 }
2226
2227 pub fn text_summary_for_range<D, O: ToOffset>(&self, range: Range<O>) -> D
2228 where
2229 D: TextDimension,
2230 {
2231 self.visible_text
2232 .cursor(range.start.to_offset(self))
2233 .summary(range.end.to_offset(self))
2234 }
2235
2236 pub fn summaries_for_anchors<'a, D, A>(&'a self, anchors: A) -> impl 'a + Iterator<Item = D>
2237 where
2238 D: 'a + TextDimension,
2239 A: 'a + IntoIterator<Item = &'a Anchor>,
2240 {
2241 let anchors = anchors.into_iter();
2242 self.summaries_for_anchors_with_payload::<D, _, ()>(anchors.map(|a| (a, ())))
2243 .map(|d| d.0)
2244 }
2245
2246 pub fn summaries_for_anchors_with_payload<'a, D, A, T>(
2247 &'a self,
2248 anchors: A,
2249 ) -> impl 'a + Iterator<Item = (D, T)>
2250 where
2251 D: 'a + TextDimension,
2252 A: 'a + IntoIterator<Item = (&'a Anchor, T)>,
2253 {
2254 let anchors = anchors.into_iter();
2255 let mut fragment_cursor = self
2256 .fragments
2257 .cursor::<Dimensions<Option<&Locator>, usize>>(&None);
2258 let mut text_cursor = self.visible_text.cursor(0);
2259 let mut position = D::zero(());
2260
2261 anchors.map(move |(anchor, payload)| {
2262 if anchor.is_min() {
2263 return (D::zero(()), payload);
2264 } else if anchor.is_max() {
2265 return (D::from_text_summary(&self.visible_text.summary()), payload);
2266 }
2267
2268 let Some(insertion) = self.try_find_fragment(anchor) else {
2269 panic!(
2270 "invalid insertion for buffer {}@{:?} with anchor {:?}",
2271 self.remote_id(),
2272 self.version,
2273 anchor
2274 );
2275 };
2276 assert_eq!(
2277 insertion.timestamp,
2278 anchor.timestamp,
2279 "invalid insertion for buffer {}@{:?} and anchor {:?}",
2280 self.remote_id(),
2281 self.version,
2282 anchor
2283 );
2284
2285 fragment_cursor.seek_forward(&Some(&insertion.fragment_id), Bias::Left);
2286 let fragment = fragment_cursor.item().unwrap();
2287 let mut fragment_offset = fragment_cursor.start().1;
2288 if fragment.visible {
2289 fragment_offset += anchor.offset - insertion.split_offset;
2290 }
2291
2292 position.add_assign(&text_cursor.summary(fragment_offset));
2293 (position, payload)
2294 })
2295 }
2296
2297 pub fn summary_for_anchor<D>(&self, anchor: &Anchor) -> D
2298 where
2299 D: TextDimension,
2300 {
2301 self.text_summary_for_range(0..self.offset_for_anchor(anchor))
2302 }
2303
2304 pub fn offset_for_anchor(&self, anchor: &Anchor) -> usize {
2305 if anchor.is_min() {
2306 0
2307 } else if anchor.is_max() {
2308 self.visible_text.len()
2309 } else {
2310 debug_assert_eq!(anchor.buffer_id, Some(self.remote_id));
2311 debug_assert!(
2312 self.version.observed(anchor.timestamp),
2313 "Anchor timestamp {:?} not observed by buffer {:?}",
2314 anchor.timestamp,
2315 self.version
2316 );
2317 let item = self.try_find_fragment(anchor);
2318 let Some(insertion) = item.filter(|insertion| insertion.timestamp == anchor.timestamp)
2319 else {
2320 self.panic_bad_anchor(anchor);
2321 };
2322
2323 let (start, _, item) = self
2324 .fragments
2325 .find::<Dimensions<Option<&Locator>, usize>, _>(
2326 &None,
2327 &Some(&insertion.fragment_id),
2328 Bias::Left,
2329 );
2330 let fragment = item.unwrap();
2331 let mut fragment_offset = start.1;
2332 if fragment.visible {
2333 fragment_offset += anchor.offset - insertion.split_offset;
2334 }
2335 fragment_offset
2336 }
2337 }
2338
2339 #[cold]
2340 fn panic_bad_anchor(&self, anchor: &Anchor) -> ! {
2341 if anchor.buffer_id.is_some_and(|id| id != self.remote_id) {
2342 panic!(
2343 "invalid anchor - buffer id does not match: anchor {anchor:?}; buffer id: {}, version: {:?}",
2344 self.remote_id, self.version
2345 );
2346 } else if !self.version.observed(anchor.timestamp) {
2347 panic!(
2348 "invalid anchor - snapshot has not observed lamport: {:?}; version: {:?}",
2349 anchor, self.version
2350 );
2351 } else {
2352 panic!(
2353 "invalid anchor {:?}. buffer id: {}, version: {:?}",
2354 anchor, self.remote_id, self.version
2355 );
2356 }
2357 }
2358
2359 fn fragment_id_for_anchor(&self, anchor: &Anchor) -> &Locator {
2360 self.try_fragment_id_for_anchor(anchor)
2361 .unwrap_or_else(|| self.panic_bad_anchor(anchor))
2362 }
2363
2364 fn try_fragment_id_for_anchor(&self, anchor: &Anchor) -> Option<&Locator> {
2365 if anchor.is_min() {
2366 Some(Locator::min_ref())
2367 } else if anchor.is_max() {
2368 Some(Locator::max_ref())
2369 } else {
2370 let item = self.try_find_fragment(anchor);
2371 item.filter(|insertion| {
2372 !cfg!(debug_assertions) || insertion.timestamp == anchor.timestamp
2373 })
2374 .map(|insertion| &insertion.fragment_id)
2375 }
2376 }
2377
2378 fn try_find_fragment(&self, anchor: &Anchor) -> Option<&InsertionFragment> {
2379 let anchor_key = InsertionFragmentKey {
2380 timestamp: anchor.timestamp,
2381 split_offset: anchor.offset,
2382 };
2383 match self.insertions.find_with_prev::<InsertionFragmentKey, _>(
2384 (),
2385 &anchor_key,
2386 anchor.bias,
2387 ) {
2388 (_, _, Some((prev, insertion))) => {
2389 let comparison = sum_tree::KeyedItem::key(insertion).cmp(&anchor_key);
2390 if comparison == Ordering::Greater
2391 || (anchor.bias == Bias::Left
2392 && comparison == Ordering::Equal
2393 && anchor.offset > 0)
2394 {
2395 prev
2396 } else {
2397 Some(insertion)
2398 }
2399 }
2400 _ => self.insertions.last(),
2401 }
2402 }
2403
2404 /// Returns an anchor range for the given input position range that is anchored to the text inbetween.
2405 pub fn anchor_range_between<T: ToOffset>(&self, position: Range<T>) -> Range<Anchor> {
2406 self.anchor_before(position.start)..self.anchor_after(position.end)
2407 }
2408
2409 /// Returns an anchor range for the given input position range that is anchored to the text before the start position and after the end position.
2410 pub fn anchor_range_around<T: ToOffset>(&self, position: Range<T>) -> Range<Anchor> {
2411 self.anchor_before(position.start)..self.anchor_after(position.end)
2412 }
2413
2414 /// Returns an anchor for the given input position that is anchored to the text before the position.
2415 pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
2416 self.anchor_at(position, Bias::Left)
2417 }
2418
2419 /// Returns an anchor for the given input position that is anchored to the text after the position.
2420 pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
2421 self.anchor_at(position, Bias::Right)
2422 }
2423
2424 pub fn anchor_at<T: ToOffset>(&self, position: T, bias: Bias) -> Anchor {
2425 self.anchor_at_offset(position.to_offset(self), bias)
2426 }
2427
2428 fn anchor_at_offset(&self, mut offset: usize, bias: Bias) -> Anchor {
2429 if bias == Bias::Left && offset == 0 {
2430 Anchor::min_for_buffer(self.remote_id)
2431 } else if bias == Bias::Right
2432 && ((!cfg!(debug_assertions) && offset >= self.len()) || offset == self.len())
2433 {
2434 Anchor::max_for_buffer(self.remote_id)
2435 } else {
2436 if !self
2437 .visible_text
2438 .assert_char_boundary::<{ cfg!(debug_assertions) }>(offset)
2439 {
2440 offset = match bias {
2441 Bias::Left => self.visible_text.floor_char_boundary(offset),
2442 Bias::Right => self.visible_text.ceil_char_boundary(offset),
2443 };
2444 }
2445 let (start, _, item) = self.fragments.find::<usize, _>(&None, &offset, bias);
2446 let Some(fragment) = item else {
2447 // We got a bad offset, likely out of bounds
2448 debug_panic!(
2449 "Failed to find fragment at offset {} (len: {})",
2450 offset,
2451 self.len()
2452 );
2453 return Anchor::max_for_buffer(self.remote_id);
2454 };
2455 let overshoot = offset - start;
2456 Anchor {
2457 timestamp: fragment.timestamp,
2458 offset: fragment.insertion_offset + overshoot,
2459 bias,
2460 buffer_id: Some(self.remote_id),
2461 }
2462 }
2463 }
2464
2465 pub fn can_resolve(&self, anchor: &Anchor) -> bool {
2466 anchor.is_min()
2467 || anchor.is_max()
2468 || (Some(self.remote_id) == anchor.buffer_id && self.version.observed(anchor.timestamp))
2469 }
2470
2471 pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
2472 self.visible_text.clip_offset(offset, bias)
2473 }
2474
2475 pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
2476 self.visible_text.clip_point(point, bias)
2477 }
2478
2479 pub fn clip_offset_utf16(&self, offset: OffsetUtf16, bias: Bias) -> OffsetUtf16 {
2480 self.visible_text.clip_offset_utf16(offset, bias)
2481 }
2482
2483 pub fn clip_point_utf16(&self, point: Unclipped<PointUtf16>, bias: Bias) -> PointUtf16 {
2484 self.visible_text.clip_point_utf16(point, bias)
2485 }
2486
2487 pub fn edits_since<'a, D>(
2488 &'a self,
2489 since: &'a clock::Global,
2490 ) -> impl 'a + Iterator<Item = Edit<D>>
2491 where
2492 D: TextDimension + Ord,
2493 {
2494 self.edits_since_in_range(since, Anchor::MIN..Anchor::MAX)
2495 }
2496
2497 pub fn anchored_edits_since<'a, D>(
2498 &'a self,
2499 since: &'a clock::Global,
2500 ) -> impl 'a + Iterator<Item = (Edit<D>, Range<Anchor>)>
2501 where
2502 D: TextDimension + Ord,
2503 {
2504 self.anchored_edits_since_in_range(since, Anchor::MIN..Anchor::MAX)
2505 }
2506
2507 pub fn edits_since_in_range<'a, D>(
2508 &'a self,
2509 since: &'a clock::Global,
2510 range: Range<Anchor>,
2511 ) -> impl 'a + Iterator<Item = Edit<D>>
2512 where
2513 D: TextDimension + Ord,
2514 {
2515 self.anchored_edits_since_in_range(since, range)
2516 .map(|item| item.0)
2517 }
2518
2519 pub fn anchored_edits_since_in_range<'a, D>(
2520 &'a self,
2521 since: &'a clock::Global,
2522 range: Range<Anchor>,
2523 ) -> impl 'a + Iterator<Item = (Edit<D>, Range<Anchor>)>
2524 where
2525 D: TextDimension + Ord,
2526 {
2527 if *since == self.version {
2528 return None.into_iter().flatten();
2529 }
2530 let mut cursor = self.fragments.filter(&None, move |summary| {
2531 !since.observed_all(&summary.max_version)
2532 });
2533 cursor.next();
2534 let fragments_cursor = Some(cursor);
2535 let start_fragment_id = self.fragment_id_for_anchor(&range.start);
2536 let (start, _, item) = self
2537 .fragments
2538 .find::<Dimensions<Option<&Locator>, FragmentTextSummary>, _>(
2539 &None,
2540 &Some(start_fragment_id),
2541 Bias::Left,
2542 );
2543 let mut visible_start = start.1.visible;
2544 let mut deleted_start = start.1.deleted;
2545 if let Some(fragment) = item {
2546 let overshoot = range.start.offset - fragment.insertion_offset;
2547 if fragment.visible {
2548 visible_start += overshoot;
2549 } else {
2550 deleted_start += overshoot;
2551 }
2552 }
2553 let end_fragment_id = self.fragment_id_for_anchor(&range.end);
2554
2555 Some(Edits {
2556 visible_cursor: self.visible_text.cursor(visible_start),
2557 deleted_cursor: self.deleted_text.cursor(deleted_start),
2558 fragments_cursor,
2559 undos: &self.undo_map,
2560 since,
2561 old_end: D::zero(()),
2562 new_end: D::zero(()),
2563 range: (start_fragment_id, range.start.offset)..(end_fragment_id, range.end.offset),
2564 buffer_id: self.remote_id,
2565 })
2566 .into_iter()
2567 .flatten()
2568 }
2569
2570 pub fn has_edits_since_in_range(&self, since: &clock::Global, range: Range<Anchor>) -> bool {
2571 if *since != self.version {
2572 let start_fragment_id = self.fragment_id_for_anchor(&range.start);
2573 let end_fragment_id = self.fragment_id_for_anchor(&range.end);
2574 let mut cursor = self.fragments.filter::<_, usize>(&None, move |summary| {
2575 !since.observed_all(&summary.max_version)
2576 });
2577 cursor.next();
2578 while let Some(fragment) = cursor.item() {
2579 if fragment.id > *end_fragment_id {
2580 break;
2581 }
2582 if fragment.id > *start_fragment_id {
2583 let was_visible = fragment.was_visible(since, &self.undo_map);
2584 let is_visible = fragment.visible;
2585 if was_visible != is_visible {
2586 return true;
2587 }
2588 }
2589 cursor.next();
2590 }
2591 }
2592 false
2593 }
2594
2595 pub fn has_edits_since(&self, since: &clock::Global) -> bool {
2596 if *since != self.version {
2597 let mut cursor = self.fragments.filter::<_, usize>(&None, move |summary| {
2598 !since.observed_all(&summary.max_version)
2599 });
2600 cursor.next();
2601 while let Some(fragment) = cursor.item() {
2602 let was_visible = fragment.was_visible(since, &self.undo_map);
2603 let is_visible = fragment.visible;
2604 if was_visible != is_visible {
2605 return true;
2606 }
2607 cursor.next();
2608 }
2609 }
2610 false
2611 }
2612
2613 pub fn range_to_version(&self, range: Range<usize>, version: &clock::Global) -> Range<usize> {
2614 let mut offsets = self.offsets_to_version([range.start, range.end], version);
2615 offsets.next().unwrap()..offsets.next().unwrap()
2616 }
2617
2618 /// Converts the given sequence of offsets into their corresponding offsets
2619 /// at a prior version of this buffer.
2620 pub fn offsets_to_version<'a>(
2621 &'a self,
2622 offsets: impl 'a + IntoIterator<Item = usize>,
2623 version: &'a clock::Global,
2624 ) -> impl 'a + Iterator<Item = usize> {
2625 let mut edits = self.edits_since(version).peekable();
2626 let mut last_old_end = 0;
2627 let mut last_new_end = 0;
2628 offsets.into_iter().map(move |new_offset| {
2629 while let Some(edit) = edits.peek() {
2630 if edit.new.start > new_offset {
2631 break;
2632 }
2633
2634 if edit.new.end <= new_offset {
2635 last_new_end = edit.new.end;
2636 last_old_end = edit.old.end;
2637 edits.next();
2638 continue;
2639 }
2640
2641 let overshoot = new_offset - edit.new.start;
2642 return (edit.old.start + overshoot).min(edit.old.end);
2643 }
2644
2645 last_old_end + new_offset.saturating_sub(last_new_end)
2646 })
2647 }
2648
2649 /// Visually annotates a position or range with the `Debug` representation of a value. The
2650 /// callsite of this function is used as a key - previous annotations will be removed.
2651 #[cfg(debug_assertions)]
2652 #[track_caller]
2653 pub fn debug<R, V>(&self, ranges: &R, value: V)
2654 where
2655 R: debug::ToDebugRanges,
2656 V: std::fmt::Debug,
2657 {
2658 self.debug_with_key(std::panic::Location::caller(), ranges, value);
2659 }
2660
2661 /// Visually annotates a position or range with the `Debug` representation of a value. Previous
2662 /// debug annotations with the same key will be removed. The key is also used to determine the
2663 /// annotation's color.
2664 #[cfg(debug_assertions)]
2665 pub fn debug_with_key<K, R, V>(&self, key: &K, ranges: &R, value: V)
2666 where
2667 K: std::hash::Hash + 'static,
2668 R: debug::ToDebugRanges,
2669 V: std::fmt::Debug,
2670 {
2671 let ranges = ranges
2672 .to_debug_ranges(self)
2673 .into_iter()
2674 .map(|range| self.anchor_after(range.start)..self.anchor_before(range.end))
2675 .collect();
2676 debug::GlobalDebugRanges::with_locked(|debug_ranges| {
2677 debug_ranges.insert(key, ranges, format!("{value:?}").into());
2678 });
2679 }
2680}
2681
2682struct RopeBuilder<'a> {
2683 old_visible_cursor: rope::Cursor<'a>,
2684 old_deleted_cursor: rope::Cursor<'a>,
2685 new_visible: Rope,
2686 new_deleted: Rope,
2687}
2688
2689impl<'a> RopeBuilder<'a> {
2690 fn new(old_visible_cursor: rope::Cursor<'a>, old_deleted_cursor: rope::Cursor<'a>) -> Self {
2691 Self {
2692 old_visible_cursor,
2693 old_deleted_cursor,
2694 new_visible: Rope::new(),
2695 new_deleted: Rope::new(),
2696 }
2697 }
2698
2699 fn append(&mut self, len: FragmentTextSummary) {
2700 self.push(len.visible, true, true);
2701 self.push(len.deleted, false, false);
2702 }
2703
2704 fn push_fragment(&mut self, fragment: &Fragment, was_visible: bool) {
2705 debug_assert!(fragment.len > 0);
2706 self.push(fragment.len, was_visible, fragment.visible)
2707 }
2708
2709 fn push(&mut self, len: usize, was_visible: bool, is_visible: bool) {
2710 let text = if was_visible {
2711 self.old_visible_cursor
2712 .slice(self.old_visible_cursor.offset() + len)
2713 } else {
2714 self.old_deleted_cursor
2715 .slice(self.old_deleted_cursor.offset() + len)
2716 };
2717 if is_visible {
2718 self.new_visible.append(text);
2719 } else {
2720 self.new_deleted.append(text);
2721 }
2722 }
2723
2724 fn push_str(&mut self, text: &str) {
2725 self.new_visible.push(text);
2726 }
2727
2728 fn finish(mut self) -> (Rope, Rope) {
2729 self.new_visible.append(self.old_visible_cursor.suffix());
2730 self.new_deleted.append(self.old_deleted_cursor.suffix());
2731 (self.new_visible, self.new_deleted)
2732 }
2733}
2734
2735impl<D: TextDimension + Ord, F: FnMut(&FragmentSummary) -> bool> Iterator for Edits<'_, D, F> {
2736 type Item = (Edit<D>, Range<Anchor>);
2737
2738 fn next(&mut self) -> Option<Self::Item> {
2739 let mut pending_edit: Option<Self::Item> = None;
2740 let cursor = self.fragments_cursor.as_mut()?;
2741
2742 while let Some(fragment) = cursor.item() {
2743 if fragment.id < *self.range.start.0 {
2744 cursor.next();
2745 continue;
2746 } else if fragment.id > *self.range.end.0 {
2747 break;
2748 }
2749
2750 if cursor.start().visible > self.visible_cursor.offset() {
2751 let summary = self.visible_cursor.summary(cursor.start().visible);
2752 self.old_end.add_assign(&summary);
2753 self.new_end.add_assign(&summary);
2754 }
2755
2756 if pending_edit
2757 .as_ref()
2758 .is_some_and(|(change, _)| change.new.end < self.new_end)
2759 {
2760 break;
2761 }
2762
2763 let start_anchor = Anchor {
2764 timestamp: fragment.timestamp,
2765 offset: fragment.insertion_offset,
2766 bias: Bias::Right,
2767 buffer_id: Some(self.buffer_id),
2768 };
2769 let end_anchor = Anchor {
2770 timestamp: fragment.timestamp,
2771 offset: fragment.insertion_offset + fragment.len,
2772 bias: Bias::Left,
2773 buffer_id: Some(self.buffer_id),
2774 };
2775
2776 if !fragment.was_visible(self.since, self.undos) && fragment.visible {
2777 let mut visible_end = cursor.end().visible;
2778 if fragment.id == *self.range.end.0 {
2779 visible_end = cmp::min(
2780 visible_end,
2781 cursor.start().visible + (self.range.end.1 - fragment.insertion_offset),
2782 );
2783 }
2784
2785 let fragment_summary = self.visible_cursor.summary(visible_end);
2786 let mut new_end = self.new_end;
2787 new_end.add_assign(&fragment_summary);
2788 if let Some((edit, range)) = pending_edit.as_mut() {
2789 edit.new.end = new_end;
2790 range.end = end_anchor;
2791 } else {
2792 pending_edit = Some((
2793 Edit {
2794 old: self.old_end..self.old_end,
2795 new: self.new_end..new_end,
2796 },
2797 start_anchor..end_anchor,
2798 ));
2799 }
2800
2801 self.new_end = new_end;
2802 } else if fragment.was_visible(self.since, self.undos) && !fragment.visible {
2803 let mut deleted_end = cursor.end().deleted;
2804 if fragment.id == *self.range.end.0 {
2805 deleted_end = cmp::min(
2806 deleted_end,
2807 cursor.start().deleted + (self.range.end.1 - fragment.insertion_offset),
2808 );
2809 }
2810
2811 if cursor.start().deleted > self.deleted_cursor.offset() {
2812 self.deleted_cursor.seek_forward(cursor.start().deleted);
2813 }
2814 let fragment_summary = self.deleted_cursor.summary(deleted_end);
2815 let mut old_end = self.old_end;
2816 old_end.add_assign(&fragment_summary);
2817 if let Some((edit, range)) = pending_edit.as_mut() {
2818 edit.old.end = old_end;
2819 range.end = end_anchor;
2820 } else {
2821 pending_edit = Some((
2822 Edit {
2823 old: self.old_end..old_end,
2824 new: self.new_end..self.new_end,
2825 },
2826 start_anchor..end_anchor,
2827 ));
2828 }
2829
2830 self.old_end = old_end;
2831 }
2832
2833 cursor.next();
2834 }
2835
2836 pending_edit
2837 }
2838}
2839
2840impl Fragment {
2841 fn is_visible(&self, undos: &UndoMap) -> bool {
2842 !undos.is_undone(self.timestamp) && self.deletions.iter().all(|d| undos.is_undone(*d))
2843 }
2844
2845 fn was_visible(&self, version: &clock::Global, undos: &UndoMap) -> bool {
2846 (version.observed(self.timestamp) && !undos.was_undone(self.timestamp, version))
2847 && self
2848 .deletions
2849 .iter()
2850 .all(|d| !version.observed(*d) || undos.was_undone(*d, version))
2851 }
2852}
2853
2854impl sum_tree::Item for Fragment {
2855 type Summary = FragmentSummary;
2856
2857 fn summary(&self, _cx: &Option<clock::Global>) -> Self::Summary {
2858 let mut max_version = clock::Global::new();
2859 max_version.observe(self.timestamp);
2860 for deletion in &self.deletions {
2861 max_version.observe(*deletion);
2862 }
2863 max_version.join(&self.max_undos);
2864
2865 let mut min_insertion_version = clock::Global::new();
2866 min_insertion_version.observe(self.timestamp);
2867 let max_insertion_version = min_insertion_version.clone();
2868 if self.visible {
2869 FragmentSummary {
2870 max_id: self.id.clone(),
2871 text: FragmentTextSummary {
2872 visible: self.len,
2873 deleted: 0,
2874 },
2875 max_version,
2876 min_insertion_version,
2877 max_insertion_version,
2878 }
2879 } else {
2880 FragmentSummary {
2881 max_id: self.id.clone(),
2882 text: FragmentTextSummary {
2883 visible: 0,
2884 deleted: self.len,
2885 },
2886 max_version,
2887 min_insertion_version,
2888 max_insertion_version,
2889 }
2890 }
2891 }
2892}
2893
2894impl sum_tree::Summary for FragmentSummary {
2895 type Context<'a> = &'a Option<clock::Global>;
2896
2897 fn zero(_cx: Self::Context<'_>) -> Self {
2898 Default::default()
2899 }
2900
2901 fn add_summary(&mut self, other: &Self, _: Self::Context<'_>) {
2902 self.max_id.assign(&other.max_id);
2903 self.text.visible += &other.text.visible;
2904 self.text.deleted += &other.text.deleted;
2905 self.max_version.join(&other.max_version);
2906 self.min_insertion_version
2907 .meet(&other.min_insertion_version);
2908 self.max_insertion_version
2909 .join(&other.max_insertion_version);
2910 }
2911}
2912
2913impl Default for FragmentSummary {
2914 fn default() -> Self {
2915 FragmentSummary {
2916 max_id: Locator::min(),
2917 text: FragmentTextSummary::default(),
2918 max_version: clock::Global::new(),
2919 min_insertion_version: clock::Global::new(),
2920 max_insertion_version: clock::Global::new(),
2921 }
2922 }
2923}
2924
2925impl sum_tree::Item for InsertionFragment {
2926 type Summary = InsertionFragmentKey;
2927
2928 fn summary(&self, _cx: ()) -> Self::Summary {
2929 InsertionFragmentKey {
2930 timestamp: self.timestamp,
2931 split_offset: self.split_offset,
2932 }
2933 }
2934}
2935
2936impl sum_tree::KeyedItem for InsertionFragment {
2937 type Key = InsertionFragmentKey;
2938
2939 fn key(&self) -> Self::Key {
2940 sum_tree::Item::summary(self, ())
2941 }
2942}
2943
2944impl InsertionFragment {
2945 fn new(fragment: &Fragment) -> Self {
2946 Self {
2947 timestamp: fragment.timestamp,
2948 split_offset: fragment.insertion_offset,
2949 fragment_id: fragment.id.clone(),
2950 }
2951 }
2952
2953 fn insert_new(fragment: &Fragment) -> sum_tree::Edit<Self> {
2954 sum_tree::Edit::Insert(Self::new(fragment))
2955 }
2956}
2957
2958impl sum_tree::ContextLessSummary for InsertionFragmentKey {
2959 fn zero() -> Self {
2960 InsertionFragmentKey {
2961 timestamp: Lamport::MIN,
2962 split_offset: 0,
2963 }
2964 }
2965
2966 fn add_summary(&mut self, summary: &Self) {
2967 *self = *summary;
2968 }
2969}
2970
2971#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
2972pub struct FullOffset(pub usize);
2973
2974impl ops::AddAssign<usize> for FullOffset {
2975 fn add_assign(&mut self, rhs: usize) {
2976 self.0 += rhs;
2977 }
2978}
2979
2980impl ops::Add<usize> for FullOffset {
2981 type Output = Self;
2982
2983 fn add(mut self, rhs: usize) -> Self::Output {
2984 self += rhs;
2985 self
2986 }
2987}
2988
2989impl ops::Sub for FullOffset {
2990 type Output = usize;
2991
2992 fn sub(self, rhs: Self) -> Self::Output {
2993 self.0 - rhs.0
2994 }
2995}
2996
2997impl sum_tree::Dimension<'_, FragmentSummary> for usize {
2998 fn zero(_: &Option<clock::Global>) -> Self {
2999 Default::default()
3000 }
3001
3002 fn add_summary(&mut self, summary: &FragmentSummary, _: &Option<clock::Global>) {
3003 *self += summary.text.visible;
3004 }
3005}
3006
3007impl sum_tree::Dimension<'_, FragmentSummary> for FullOffset {
3008 fn zero(_: &Option<clock::Global>) -> Self {
3009 Default::default()
3010 }
3011
3012 fn add_summary(&mut self, summary: &FragmentSummary, _: &Option<clock::Global>) {
3013 self.0 += summary.text.visible + summary.text.deleted;
3014 }
3015}
3016
3017impl<'a> sum_tree::Dimension<'a, FragmentSummary> for Option<&'a Locator> {
3018 fn zero(_: &Option<clock::Global>) -> Self {
3019 Default::default()
3020 }
3021
3022 fn add_summary(&mut self, summary: &'a FragmentSummary, _: &Option<clock::Global>) {
3023 *self = Some(&summary.max_id);
3024 }
3025}
3026
3027impl sum_tree::SeekTarget<'_, FragmentSummary, FragmentTextSummary> for usize {
3028 fn cmp(
3029 &self,
3030 cursor_location: &FragmentTextSummary,
3031 _: &Option<clock::Global>,
3032 ) -> cmp::Ordering {
3033 Ord::cmp(self, &cursor_location.visible)
3034 }
3035}
3036
3037#[derive(Copy, Clone, Debug, Eq, PartialEq)]
3038enum VersionedFullOffset {
3039 Offset(FullOffset),
3040 Invalid,
3041}
3042
3043impl VersionedFullOffset {
3044 fn full_offset(&self) -> FullOffset {
3045 if let Self::Offset(position) = self {
3046 *position
3047 } else {
3048 panic!("invalid version")
3049 }
3050 }
3051}
3052
3053impl Default for VersionedFullOffset {
3054 fn default() -> Self {
3055 Self::Offset(Default::default())
3056 }
3057}
3058
3059impl<'a> sum_tree::Dimension<'a, FragmentSummary> for VersionedFullOffset {
3060 fn zero(_cx: &Option<clock::Global>) -> Self {
3061 Default::default()
3062 }
3063
3064 fn add_summary(&mut self, summary: &'a FragmentSummary, cx: &Option<clock::Global>) {
3065 if let Self::Offset(offset) = self {
3066 let version = cx.as_ref().unwrap();
3067 if version.observed_all(&summary.max_insertion_version) {
3068 *offset += summary.text.visible + summary.text.deleted;
3069 } else if version.observed_any(&summary.min_insertion_version) {
3070 *self = Self::Invalid;
3071 }
3072 }
3073 }
3074}
3075
3076impl sum_tree::SeekTarget<'_, FragmentSummary, Self> for VersionedFullOffset {
3077 fn cmp(&self, cursor_position: &Self, _: &Option<clock::Global>) -> cmp::Ordering {
3078 match (self, cursor_position) {
3079 (Self::Offset(a), Self::Offset(b)) => Ord::cmp(a, b),
3080 (Self::Offset(_), Self::Invalid) => cmp::Ordering::Less,
3081 (Self::Invalid, _) => unreachable!(),
3082 }
3083 }
3084}
3085
3086impl Operation {
3087 fn replica_id(&self) -> ReplicaId {
3088 operation_queue::Operation::lamport_timestamp(self).replica_id
3089 }
3090
3091 pub fn timestamp(&self) -> clock::Lamport {
3092 match self {
3093 Operation::Edit(edit) => edit.timestamp,
3094 Operation::Undo(undo) => undo.timestamp,
3095 }
3096 }
3097
3098 pub fn as_edit(&self) -> Option<&EditOperation> {
3099 match self {
3100 Operation::Edit(edit) => Some(edit),
3101 _ => None,
3102 }
3103 }
3104
3105 pub fn is_edit(&self) -> bool {
3106 matches!(self, Operation::Edit { .. })
3107 }
3108}
3109
3110impl operation_queue::Operation for Operation {
3111 fn lamport_timestamp(&self) -> clock::Lamport {
3112 match self {
3113 Operation::Edit(edit) => edit.timestamp,
3114 Operation::Undo(undo) => undo.timestamp,
3115 }
3116 }
3117}
3118
3119pub trait ToOffset {
3120 fn to_offset(&self, snapshot: &BufferSnapshot) -> usize;
3121 /// Turns this point into the next offset in the buffer that comes after this, respecting utf8 boundaries.
3122 fn to_next_offset(&self, snapshot: &BufferSnapshot) -> usize {
3123 snapshot
3124 .visible_text
3125 .ceil_char_boundary(self.to_offset(snapshot) + 1)
3126 }
3127 /// Turns this point into the previous offset in the buffer that comes before this, respecting utf8 boundaries.
3128 fn to_previous_offset(&self, snapshot: &BufferSnapshot) -> usize {
3129 snapshot
3130 .visible_text
3131 .floor_char_boundary(self.to_offset(snapshot).saturating_sub(1))
3132 }
3133}
3134
3135impl ToOffset for Point {
3136 #[inline]
3137 fn to_offset(&self, snapshot: &BufferSnapshot) -> usize {
3138 snapshot.point_to_offset(*self)
3139 }
3140}
3141
3142impl ToOffset for usize {
3143 #[track_caller]
3144 fn to_offset(&self, snapshot: &BufferSnapshot) -> usize {
3145 if !snapshot
3146 .as_rope()
3147 .assert_char_boundary::<{ cfg!(debug_assertions) }>(*self)
3148 {
3149 snapshot.as_rope().floor_char_boundary(*self)
3150 } else {
3151 *self
3152 }
3153 }
3154}
3155
3156impl ToOffset for Anchor {
3157 #[inline]
3158 fn to_offset(&self, snapshot: &BufferSnapshot) -> usize {
3159 snapshot.summary_for_anchor(self)
3160 }
3161}
3162
3163impl<T: ToOffset> ToOffset for &T {
3164 #[inline]
3165 fn to_offset(&self, content: &BufferSnapshot) -> usize {
3166 (*self).to_offset(content)
3167 }
3168}
3169
3170impl ToOffset for PointUtf16 {
3171 #[inline]
3172 fn to_offset(&self, snapshot: &BufferSnapshot) -> usize {
3173 snapshot.point_utf16_to_offset(*self)
3174 }
3175}
3176
3177impl ToOffset for Unclipped<PointUtf16> {
3178 #[inline]
3179 fn to_offset(&self, snapshot: &BufferSnapshot) -> usize {
3180 snapshot.unclipped_point_utf16_to_offset(*self)
3181 }
3182}
3183
3184pub trait ToPoint {
3185 fn to_point(&self, snapshot: &BufferSnapshot) -> Point;
3186}
3187
3188impl ToPoint for Anchor {
3189 #[inline]
3190 fn to_point(&self, snapshot: &BufferSnapshot) -> Point {
3191 snapshot.summary_for_anchor(self)
3192 }
3193}
3194
3195impl ToPoint for usize {
3196 #[inline]
3197 fn to_point(&self, snapshot: &BufferSnapshot) -> Point {
3198 snapshot.offset_to_point(*self)
3199 }
3200}
3201
3202impl ToPoint for Point {
3203 #[inline]
3204 fn to_point(&self, _: &BufferSnapshot) -> Point {
3205 *self
3206 }
3207}
3208
3209impl ToPoint for Unclipped<PointUtf16> {
3210 #[inline]
3211 fn to_point(&self, snapshot: &BufferSnapshot) -> Point {
3212 snapshot.unclipped_point_utf16_to_point(*self)
3213 }
3214}
3215
3216pub trait ToPointUtf16 {
3217 fn to_point_utf16(&self, snapshot: &BufferSnapshot) -> PointUtf16;
3218}
3219
3220impl ToPointUtf16 for Anchor {
3221 #[inline]
3222 fn to_point_utf16(&self, snapshot: &BufferSnapshot) -> PointUtf16 {
3223 snapshot.summary_for_anchor(self)
3224 }
3225}
3226
3227impl ToPointUtf16 for usize {
3228 #[inline]
3229 fn to_point_utf16(&self, snapshot: &BufferSnapshot) -> PointUtf16 {
3230 snapshot.offset_to_point_utf16(*self)
3231 }
3232}
3233
3234impl ToPointUtf16 for PointUtf16 {
3235 #[inline]
3236 fn to_point_utf16(&self, _: &BufferSnapshot) -> PointUtf16 {
3237 *self
3238 }
3239}
3240
3241impl ToPointUtf16 for Point {
3242 #[inline]
3243 fn to_point_utf16(&self, snapshot: &BufferSnapshot) -> PointUtf16 {
3244 snapshot.point_to_point_utf16(*self)
3245 }
3246}
3247
3248pub trait ToOffsetUtf16 {
3249 fn to_offset_utf16(&self, snapshot: &BufferSnapshot) -> OffsetUtf16;
3250}
3251
3252impl ToOffsetUtf16 for Anchor {
3253 #[inline]
3254 fn to_offset_utf16(&self, snapshot: &BufferSnapshot) -> OffsetUtf16 {
3255 snapshot.summary_for_anchor(self)
3256 }
3257}
3258
3259impl ToOffsetUtf16 for usize {
3260 #[inline]
3261 fn to_offset_utf16(&self, snapshot: &BufferSnapshot) -> OffsetUtf16 {
3262 snapshot.offset_to_offset_utf16(*self)
3263 }
3264}
3265
3266impl ToOffsetUtf16 for OffsetUtf16 {
3267 #[inline]
3268 fn to_offset_utf16(&self, _snapshot: &BufferSnapshot) -> OffsetUtf16 {
3269 *self
3270 }
3271}
3272
3273pub trait FromAnchor {
3274 fn from_anchor(anchor: &Anchor, snapshot: &BufferSnapshot) -> Self;
3275}
3276
3277impl FromAnchor for Anchor {
3278 #[inline]
3279 fn from_anchor(anchor: &Anchor, _snapshot: &BufferSnapshot) -> Self {
3280 *anchor
3281 }
3282}
3283
3284impl FromAnchor for Point {
3285 #[inline]
3286 fn from_anchor(anchor: &Anchor, snapshot: &BufferSnapshot) -> Self {
3287 snapshot.summary_for_anchor(anchor)
3288 }
3289}
3290
3291impl FromAnchor for PointUtf16 {
3292 #[inline]
3293 fn from_anchor(anchor: &Anchor, snapshot: &BufferSnapshot) -> Self {
3294 snapshot.summary_for_anchor(anchor)
3295 }
3296}
3297
3298impl FromAnchor for usize {
3299 #[inline]
3300 fn from_anchor(anchor: &Anchor, snapshot: &BufferSnapshot) -> Self {
3301 snapshot.summary_for_anchor(anchor)
3302 }
3303}
3304
3305#[derive(Clone, Copy, Debug, PartialEq)]
3306pub enum LineEnding {
3307 Unix,
3308 Windows,
3309}
3310
3311impl Default for LineEnding {
3312 fn default() -> Self {
3313 #[cfg(unix)]
3314 return Self::Unix;
3315
3316 #[cfg(not(unix))]
3317 return Self::Windows;
3318 }
3319}
3320
3321impl LineEnding {
3322 pub fn as_str(&self) -> &'static str {
3323 match self {
3324 LineEnding::Unix => "\n",
3325 LineEnding::Windows => "\r\n",
3326 }
3327 }
3328
3329 pub fn label(&self) -> &'static str {
3330 match self {
3331 LineEnding::Unix => "LF",
3332 LineEnding::Windows => "CRLF",
3333 }
3334 }
3335
3336 pub fn detect(text: &str) -> Self {
3337 let mut max_ix = cmp::min(text.len(), 1000);
3338 while !text.is_char_boundary(max_ix) {
3339 max_ix -= 1;
3340 }
3341
3342 if let Some(ix) = text[..max_ix].find(['\n']) {
3343 if ix > 0 && text.as_bytes()[ix - 1] == b'\r' {
3344 Self::Windows
3345 } else {
3346 Self::Unix
3347 }
3348 } else {
3349 Self::default()
3350 }
3351 }
3352
3353 pub fn normalize(text: &mut String) {
3354 if let Cow::Owned(replaced) = LINE_SEPARATORS_REGEX.replace_all(text, "\n") {
3355 *text = replaced;
3356 }
3357 }
3358
3359 pub fn normalize_arc(text: Arc<str>) -> Arc<str> {
3360 if let Cow::Owned(replaced) = LINE_SEPARATORS_REGEX.replace_all(&text, "\n") {
3361 replaced.into()
3362 } else {
3363 text
3364 }
3365 }
3366
3367 pub fn normalize_cow(text: Cow<str>) -> Cow<str> {
3368 if let Cow::Owned(replaced) = LINE_SEPARATORS_REGEX.replace_all(&text, "\n") {
3369 replaced.into()
3370 } else {
3371 text
3372 }
3373 }
3374}
3375
3376pub fn chunks_with_line_ending(rope: &Rope, line_ending: LineEnding) -> impl Iterator<Item = &str> {
3377 rope.chunks().flat_map(move |chunk| {
3378 let mut newline = false;
3379 let end_with_newline = chunk.ends_with('\n').then_some(line_ending.as_str());
3380 chunk
3381 .lines()
3382 .flat_map(move |line| {
3383 let ending = if newline {
3384 Some(line_ending.as_str())
3385 } else {
3386 None
3387 };
3388 newline = true;
3389 ending.into_iter().chain([line])
3390 })
3391 .chain(end_with_newline)
3392 })
3393}
3394
3395#[cfg(debug_assertions)]
3396pub mod debug {
3397 use super::*;
3398 use parking_lot::Mutex;
3399 use std::any::TypeId;
3400 use std::hash::{Hash, Hasher};
3401
3402 static GLOBAL_DEBUG_RANGES: Mutex<Option<GlobalDebugRanges>> = Mutex::new(None);
3403
3404 pub struct GlobalDebugRanges {
3405 pub ranges: Vec<DebugRange>,
3406 key_to_occurrence_index: HashMap<Key, usize>,
3407 next_occurrence_index: usize,
3408 }
3409
3410 pub struct DebugRange {
3411 key: Key,
3412 pub ranges: Vec<Range<Anchor>>,
3413 pub value: Arc<str>,
3414 pub occurrence_index: usize,
3415 }
3416
3417 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
3418 struct Key {
3419 type_id: TypeId,
3420 hash: u64,
3421 }
3422
3423 impl GlobalDebugRanges {
3424 pub fn with_locked<R>(f: impl FnOnce(&mut Self) -> R) -> R {
3425 let mut state = GLOBAL_DEBUG_RANGES.lock();
3426 if state.is_none() {
3427 *state = Some(GlobalDebugRanges {
3428 ranges: Vec::new(),
3429 key_to_occurrence_index: HashMap::default(),
3430 next_occurrence_index: 0,
3431 });
3432 }
3433 if let Some(global_debug_ranges) = state.as_mut() {
3434 f(global_debug_ranges)
3435 } else {
3436 unreachable!()
3437 }
3438 }
3439
3440 pub fn insert<K: Hash + 'static>(
3441 &mut self,
3442 key: &K,
3443 ranges: Vec<Range<Anchor>>,
3444 value: Arc<str>,
3445 ) {
3446 let occurrence_index = *self
3447 .key_to_occurrence_index
3448 .entry(Key::new(key))
3449 .or_insert_with(|| {
3450 let occurrence_index = self.next_occurrence_index;
3451 self.next_occurrence_index += 1;
3452 occurrence_index
3453 });
3454 let key = Key::new(key);
3455 let existing = self
3456 .ranges
3457 .iter()
3458 .enumerate()
3459 .rfind(|(_, existing)| existing.key == key);
3460 if let Some((existing_ix, _)) = existing {
3461 self.ranges.remove(existing_ix);
3462 }
3463 self.ranges.push(DebugRange {
3464 ranges,
3465 key,
3466 value,
3467 occurrence_index,
3468 });
3469 }
3470
3471 pub fn remove<K: Hash + 'static>(&mut self, key: &K) {
3472 self.remove_impl(&Key::new(key));
3473 }
3474
3475 fn remove_impl(&mut self, key: &Key) {
3476 let existing = self
3477 .ranges
3478 .iter()
3479 .enumerate()
3480 .rfind(|(_, existing)| &existing.key == key);
3481 if let Some((existing_ix, _)) = existing {
3482 self.ranges.remove(existing_ix);
3483 }
3484 }
3485
3486 pub fn remove_all_with_key_type<K: 'static>(&mut self) {
3487 self.ranges
3488 .retain(|item| item.key.type_id != TypeId::of::<K>());
3489 }
3490 }
3491
3492 impl Key {
3493 fn new<K: Hash + 'static>(key: &K) -> Self {
3494 let type_id = TypeId::of::<K>();
3495 let mut hasher = collections::FxHasher::default();
3496 key.hash(&mut hasher);
3497 Key {
3498 type_id,
3499 hash: hasher.finish(),
3500 }
3501 }
3502 }
3503
3504 pub trait ToDebugRanges {
3505 fn to_debug_ranges(&self, snapshot: &BufferSnapshot) -> Vec<Range<usize>>;
3506 }
3507
3508 impl<T: ToOffset> ToDebugRanges for T {
3509 fn to_debug_ranges(&self, snapshot: &BufferSnapshot) -> Vec<Range<usize>> {
3510 [self.to_offset(snapshot)].to_debug_ranges(snapshot)
3511 }
3512 }
3513
3514 impl<T: ToOffset + Clone> ToDebugRanges for Range<T> {
3515 fn to_debug_ranges(&self, snapshot: &BufferSnapshot) -> Vec<Range<usize>> {
3516 [self.clone()].to_debug_ranges(snapshot)
3517 }
3518 }
3519
3520 impl<T: ToOffset> ToDebugRanges for Vec<T> {
3521 fn to_debug_ranges(&self, snapshot: &BufferSnapshot) -> Vec<Range<usize>> {
3522 self.as_slice().to_debug_ranges(snapshot)
3523 }
3524 }
3525
3526 impl<T: ToOffset> ToDebugRanges for Vec<Range<T>> {
3527 fn to_debug_ranges(&self, snapshot: &BufferSnapshot) -> Vec<Range<usize>> {
3528 self.as_slice().to_debug_ranges(snapshot)
3529 }
3530 }
3531
3532 impl<T: ToOffset> ToDebugRanges for [T] {
3533 fn to_debug_ranges(&self, snapshot: &BufferSnapshot) -> Vec<Range<usize>> {
3534 self.iter()
3535 .map(|item| {
3536 let offset = item.to_offset(snapshot);
3537 offset..offset
3538 })
3539 .collect()
3540 }
3541 }
3542
3543 impl<T: ToOffset> ToDebugRanges for [Range<T>] {
3544 fn to_debug_ranges(&self, snapshot: &BufferSnapshot) -> Vec<Range<usize>> {
3545 self.iter()
3546 .map(|range| range.start.to_offset(snapshot)..range.end.to_offset(snapshot))
3547 .collect()
3548 }
3549 }
3550}