diff --git a/src/api/change.rs b/src/api/change.rs index a040bcc..1c0841c 100644 --- a/src/api/change.rs +++ b/src/api/change.rs @@ -40,22 +40,24 @@ impl TextChange { #[cfg_attr(feature = "python", pyo3::pymethods)] impl TextChange { - /// returns true if this TextChange deletes existing text + /// A change is a "deletion" if the change range span is bigger than zero. + /// This is not exclusive, a change can be both an insertion and a deletion. pub fn is_delete(&self) -> bool { self.start < self.end } - /// returns true if this TextChange adds new text + /// A change is an "Insertion" if the content is not empty. + /// This is not exclusive, a change can be both an insertion and a deletion. pub fn is_insert(&self) -> bool { !self.content.is_empty() } - /// returns true if this TextChange is effectively as no-op + /// Returns true if this TextChange is effectively as no-op pub fn is_empty(&self) -> bool { !self.is_delete() && !self.is_insert() } - /// applies this text change to given text, returning a new string + /// Applies this text change to given text, returning a new string pub fn apply(&self, txt: &str) -> String { let pre_index = std::cmp::min(self.start as usize, txt.len()); let pre = txt.get(..pre_index).unwrap_or("").to_string(); diff --git a/src/buffer/worker.rs b/src/buffer/worker.rs index 83c56c9..995a131 100644 --- a/src/buffer/worker.rs +++ b/src/buffer/worker.rs @@ -106,13 +106,17 @@ impl ControllerWorker for BufferWorker { Some((change, ack)) => { let agent_id = oplog.get_or_create_agent_id(&self.user_id.to_string()); let last_ver = oplog.local_version(); + // clip to buffer extents + let clip_end = std::cmp::min(branch.len(), change.end as usize); + let clip_start = std::cmp::max(0, change.start as usize); + // in case we have a "replace" span if change.is_delete() { - branch.delete_without_content(&mut oplog, agent_id, change.start as usize..change.end as usize); + branch.delete_without_content(&mut oplog, agent_id, clip_start..clip_end); } if change.is_insert() { - branch.insert(&mut oplog, agent_id, change.start as usize, &change.content); + branch.insert(&mut oplog, agent_id, clip_start, &change.content); } if change.is_delete() || change.is_insert() {