Fix crash on empty substrings

html_output
Wilfred Hughes 2022-02-13 16:27:00 +07:00
parent 653ebc8ad3
commit 714edd8f0c
1 changed files with 20 additions and 3 deletions

@ -18,15 +18,22 @@ pub enum BackgroundColor {
Light, Light,
} }
/// Slice `s` from `start` to `end` by codepoint. This is safer than /// Slice `s` from `start` inclusive to `end` exclusive by codepoint. This is safer than
/// slicing by bytes, which panics if the byte isn't on a codepoint /// slicing by bytes, which panics if the byte isn't on a codepoint
/// boundary. /// boundary.
fn substring_by_codepoint(s: &str, start: usize, end: usize) -> &str { fn substring_by_codepoint(s: &str, start: usize, end: usize) -> &str {
if start == end {
return &s[0..0];
}
assert!(end > start); assert!(end > start);
let mut char_idx_iter = s.char_indices(); let mut char_idx_iter = s.char_indices();
let byte_start = char_idx_iter.nth(start).expect("Expected a codepoint index inside `s`.").0; let byte_start = char_idx_iter
match char_idx_iter.nth(end - 1 - start) { .nth(start)
.expect("Expected a codepoint index inside `s`.")
.0;
match char_idx_iter.nth(end - start - 1) {
Some(byte_end) => &s[byte_start..byte_end.0], Some(byte_end) => &s[byte_start..byte_end.0],
None => &s[byte_start..], None => &s[byte_start..],
} }
@ -308,6 +315,16 @@ mod tests {
use super::*; use super::*;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
#[test]
fn test_substring_by_codepoint() {
assert_eq!(substring_by_codepoint("abcd", 0, 2), "ab");
}
#[test]
fn test_substring_by_codepoint_empty() {
assert_eq!(substring_by_codepoint("abcd", 0, 0), "");
}
#[test] #[test]
fn split_string_simple() { fn split_string_simple() {
assert_eq!(split_string("fooba", 3), vec!["foo", "ba "]); assert_eq!(split_string("fooba", 3), vec!["foo", "ba "]);