Skip to content

Commit f35398d

Browse files
authored
input: Fix some Rope method call will crash. (#1213)
1 parent cfc2449 commit f35398d

File tree

2 files changed

+32
-7
lines changed

2 files changed

+32
-7
lines changed

crates/ui/src/input/rope_ext.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,40 @@
11
pub(crate) trait RopeExt {
22
/// Get the index of (line, column) (0-based) from the byte offset (0-based).
33
/// If the offset is out of bounds, return the last line and column.
4+
///
5+
/// If the `offset` is out of bounds, it returns (0, 0).
46
fn line_column(&self, byte_offset: usize) -> (usize, usize);
57
/// Get the byte offset (0-based) from the line, column (0-based).
8+
///
9+
/// Return the last line, if line is out of bounds.
10+
/// Return the end column of line, if the column is out of bounds.
611
fn line_column_to_byte(&self, line_ix: usize, column_ix: usize) -> usize;
712
}
813

914
impl RopeExt for ropey::Rope {
1015
fn line_column(&self, offset: usize) -> (usize, usize) {
11-
let line_ix = self.byte_to_line(offset);
12-
let line_offset = offset.saturating_sub(self.line_to_byte(line_ix));
16+
let Ok(line_ix) = self.try_byte_to_line(offset) else {
17+
return (0, 0);
18+
};
19+
1320
let line = self.line(line_ix);
14-
let column_ix = line.byte_to_char(line_offset);
21+
let line_start_byte = self.line_to_byte(line_ix);
22+
let line_offset = offset.saturating_sub(line_start_byte);
23+
24+
let column_ix = line
25+
.try_byte_to_char(line_offset)
26+
.unwrap_or(line.len_chars());
1527

1628
(line_ix, column_ix)
1729
}
1830

1931
fn line_column_to_byte(&self, line_ix: usize, column_ix: usize) -> usize {
32+
let line_ix = self.len_lines().saturating_sub(1).min(line_ix);
2033
let line = self.line(line_ix);
21-
self.line_to_byte(line_ix) + line.char_to_byte(column_ix)
34+
35+
self.line_to_byte(line_ix)
36+
+ line
37+
.try_char_to_byte(column_ix)
38+
.unwrap_or(line.len_bytes().saturating_sub(1))
2239
}
2340
}

crates/ui/src/input/state.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -565,10 +565,18 @@ impl InputState {
565565
let offset = self.cursor().offset;
566566
let was_preferred_column = self.preferred_column;
567567

568-
let line_ix = self.text.byte_to_line(offset);
568+
let Ok(line_ix) = self.text.try_byte_to_line(offset) else {
569+
return;
570+
};
571+
569572
let new_line_ix = line_ix.saturating_add_signed(move_lines);
570-
let line = self.text.line(new_line_ix);
571-
let line_start_offset = self.text.line_to_byte(new_line_ix);
573+
let Some(line) = self.text.get_line(new_line_ix) else {
574+
return;
575+
};
576+
let Ok(line_start_offset) = self.text.try_line_to_byte(new_line_ix) else {
577+
return;
578+
};
579+
572580
let new_column = self
573581
.preferred_column
574582
.unwrap_or_default()

0 commit comments

Comments
 (0)