1pub fn is_single_line(bytes: &[u8]) -> bool {
5 for &byte in bytes {
6 if byte == b'\n' {
7 return false;
8 }
9 }
10 true
11}
12
13pub fn line_column(text: &str, byte_offset: usize) -> (usize, usize) {
15 let mut line = 1usize;
16 let mut column = 1usize;
17 let mut index = 0usize;
18 while index < byte_offset && index < text.len() {
19 let ch = text[index..].chars().next().expect("valid utf-8");
20 let ch_len = ch.len_utf8();
21 if ch == '\n' {
22 line += 1;
23 column = 1;
24 } else {
25 column += 1;
26 }
27 index += ch_len;
28 }
29 (line, column)
30}
31
32pub fn char_count(text: &str, start_byte: usize, end_byte: usize) -> usize {
34 let end_byte = end_byte.min(text.len());
35 if start_byte >= end_byte {
36 return 0;
37 }
38 let mut count = 0usize;
39 let mut index = start_byte;
40 while index < end_byte {
41 let ch = text[index..].chars().next().expect("valid utf-8");
42 count += 1;
43 index += ch.len_utf8();
44 }
45 count
46}
47
48pub fn line_column_from_line(text: &str, line_number: usize, byte_offset: usize) -> usize {
50 let mut line = 1usize;
51 let mut column = 1usize;
52 let mut index = 0usize;
53 while index < text.len() {
54 if line == line_number && index >= byte_offset {
55 return column;
56 }
57 let ch = text[index..].chars().next().expect("valid utf-8");
58 let ch_len = ch.len_utf8();
59 if ch == '\n' {
60 line += 1;
61 column = 1;
62 } else {
63 column += 1;
64 }
65 index += ch_len;
66 }
67 if line == line_number { column } else { 1 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[test]
75 fn line_column_counts_utf8_chars() {
76 let text = "α: 1\nb: 2";
77 let (line, column) = line_column(text, 0);
78 assert_eq!(line, 1);
79 assert_eq!(column, 1);
80 let (line, column) = line_column(text, text.find('\n').unwrap() + 1);
81 assert_eq!(line, 2);
82 assert_eq!(column, 1);
83 }
84}