line_column/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
#![no_std]
#![doc = include_str!("../README.md")]
#[cfg(test)]
mod tests;
const UNINIT_LINE_COL: (u32, u32) = (0, 0);
/// Get multiple sets of lines and columns may be faster
pub fn line_columns<const N: usize>(
s: &str,
indexs: [usize; N],
) -> [(u32, u32); N] {
let len = s.len();
for index in indexs {
assert!(index <= len,
"index {index} out of str length {len} of `{s:?}`");
assert!(s.is_char_boundary(index),
"byte index {index} is not a char boundary of `{s:?}`");
}
let result = line_columns_unchecked(s, indexs);
debug_assert!(! result.contains(&UNINIT_LINE_COL),
"impl error, report bug issue");
result
}
/// Get multiple of lines and columns may be faster
///
/// If the index does not fall on the character boundary,
/// the unspecified results
pub fn line_columns_unchecked<const N: usize>(
s: &str,
indexs: [usize; N],
) -> [(u32, u32); N] {
let len = s.len();
let mut result = [UNINIT_LINE_COL; N];
let last_loc = s.char_indices()
.fold((1, 1), |(line, column), (cur, ch)|
{
for (i, &index) in indexs.iter().enumerate() {
if index == cur {
result[i] = (line, column);
}
}
if ch == '\n' {
(line+1, 1)
} else {
(line, column+1)
}
});
for (i, &index) in indexs.iter().enumerate() {
if index == len {
result[i] = last_loc;
}
}
result
}
/// Get tuple of line and column
///
/// Use LF (0x0A) to split newline, also compatible with CRLF (0x0D 0x0A)
///
/// # Examples
/// ```
/// # use line_column::line_column;
/// assert_eq!(line_column("", 0), (1, 1));
/// assert_eq!(line_column("a", 0), (1, 1));
/// assert_eq!(line_column("a", 1), (1, 2));
/// assert_eq!(line_column("ab", 1), (1, 2));
/// assert_eq!(line_column("a\n", 1), (1, 2));
/// assert_eq!(line_column("a\n", 2), (2, 1));
/// assert_eq!(line_column("a\nb", 2), (2, 1));
/// ```
#[inline]
pub fn line_column(s: &str, index: usize) -> (u32, u32) {
line_columns(s, [index])[0]
}