mirror of
https://github.com/hexedtech/codemp.git
synced 2024-11-22 23:34:49 +01:00
fix: we clip the change span in from 0 to the buffer length, this avoids that
badly formatted changes will crash the worker. Previously I was able to crash the worker by sending oob changes. chore: improved text change docs a lil bit
This commit is contained in:
parent
d0d57f6fd5
commit
0b1a542ed5
2 changed files with 12 additions and 6 deletions
|
@ -40,22 +40,24 @@ impl TextChange {
|
||||||
|
|
||||||
#[cfg_attr(feature = "python", pyo3::pymethods)]
|
#[cfg_attr(feature = "python", pyo3::pymethods)]
|
||||||
impl TextChange {
|
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 {
|
pub fn is_delete(&self) -> bool {
|
||||||
self.start < self.end
|
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 {
|
pub fn is_insert(&self) -> bool {
|
||||||
!self.content.is_empty()
|
!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 {
|
pub fn is_empty(&self) -> bool {
|
||||||
!self.is_delete() && !self.is_insert()
|
!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 {
|
pub fn apply(&self, txt: &str) -> String {
|
||||||
let pre_index = std::cmp::min(self.start as usize, txt.len());
|
let pre_index = std::cmp::min(self.start as usize, txt.len());
|
||||||
let pre = txt.get(..pre_index).unwrap_or("").to_string();
|
let pre = txt.get(..pre_index).unwrap_or("").to_string();
|
||||||
|
|
|
@ -106,13 +106,17 @@ impl ControllerWorker<TextChange> for BufferWorker {
|
||||||
Some((change, ack)) => {
|
Some((change, ack)) => {
|
||||||
let agent_id = oplog.get_or_create_agent_id(&self.user_id.to_string());
|
let agent_id = oplog.get_or_create_agent_id(&self.user_id.to_string());
|
||||||
let last_ver = oplog.local_version();
|
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() {
|
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() {
|
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() {
|
if change.is_delete() || change.is_insert() {
|
||||||
|
|
Loading…
Reference in a new issue