pub(crate) fn char_to_byte_index(s: &str, char_index: usize) -> usize {
s.char_indices().nth(char_index).map_or(s.len(), |(idx, _)| idx)
}
pub(crate) fn char_range_to_byte_range(
text: &str,
start_char: usize,
end_char: usize,
) -> (usize, usize) {
let mut start_byte = text.len();
let mut end_byte = text.len();
for (char_idx, (byte_idx, _)) in text.char_indices().enumerate() {
if char_idx == start_char {
start_byte = byte_idx;
}
if char_idx == end_char {
end_byte = byte_idx;
break;
}
}
(start_byte, end_byte)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_char_to_byte_index_ascii() {
assert_eq!(char_to_byte_index("Hello", 0), 0);
assert_eq!(char_to_byte_index("Hello", 3), 3);
assert_eq!(char_to_byte_index("Hello", 5), 5);
}
#[test]
fn test_char_to_byte_index_multibyte() {
assert_eq!(char_to_byte_index("héllo", 0), 0);
assert_eq!(char_to_byte_index("héllo", 1), 1);
assert_eq!(char_to_byte_index("héllo", 2), 3);
assert_eq!(char_to_byte_index("汉字", 1), 3);
}
#[test]
fn test_char_to_byte_index_out_of_bounds() {
assert_eq!(char_to_byte_index("abc", 10), 3);
assert_eq!(char_to_byte_index("", 0), 0);
}
#[test]
fn test_char_range_to_byte_range_ascii() {
assert_eq!(char_range_to_byte_range("Hello", 0, 5), (0, 5));
assert_eq!(char_range_to_byte_range("Hello", 1, 3), (1, 3));
}
#[test]
fn test_char_range_to_byte_range_multibyte() {
let text = "héllo";
let (start, end) = char_range_to_byte_range(text, 1, 3);
assert_eq!(&text[start..end], "él");
}
#[test]
fn test_char_range_to_byte_range_out_of_bounds() {
let text = "héllo";
let (start, end) = char_range_to_byte_range(text, 1, 10);
assert_eq!(&text[start..end], "éllo");
}
#[test]
fn test_char_range_to_byte_range_empty() {
assert_eq!(char_range_to_byte_range("", 0, 0), (0, 0));
}
}