asciidoc_parser/span/
slice.rs1use std::ops::{Range, RangeFrom, RangeTo};
2
3use bytecount::num_chars;
4use memchr::Memchr;
5
6use super::Span;
7
8impl<'src> Span<'src> {
9 pub(crate) fn slice(&self, range: Range<usize>) -> Self {
11 self.slice_internal(&self.data[range])
12 }
13
14 pub(crate) fn slice_from(&self, range: RangeFrom<usize>) -> Self {
16 self.slice_internal(&self.data[range])
17 }
18
19 pub(crate) fn slice_to(&self, range: RangeTo<usize>) -> Self {
21 self.slice_internal(&self.data[range])
22 }
23
24 pub(crate) fn position<P>(&self, predicate: P) -> Option<usize>
26 where
27 P: Fn(char) -> bool,
28 {
29 for (o, c) in self.data.char_indices() {
30 if predicate(c) {
31 return Some(o);
32 }
33 }
34 None
35 }
36
37 fn slice_internal(&self, slice_data: &'src str) -> Self {
38 let offset = offset(self.data, slice_data);
39
40 if offset == 0 {
41 return Self {
42 data: slice_data,
43 line: self.line,
44 col: self.col,
45 offset: self.offset,
46 };
47 }
48
49 let old_data = &self.data[..offset];
50 let new_line_iter = Memchr::new(b'\n', old_data.as_bytes());
51
52 let mut lines_to_add = 0;
53 let mut last_index = None;
54 for i in new_line_iter {
55 lines_to_add += 1;
56 last_index = Some(i);
57 }
58 let last_index = last_index.map_or(0, |v| v + 1);
59
60 let col = num_chars(&old_data.as_bytes()[last_index..]);
61
62 Self {
63 data: slice_data,
64 line: self.line + lines_to_add,
65 col: if lines_to_add == 0 {
66 self.col + col
67 } else {
68 col + 1
70 },
71 offset: self.offset + offset,
72 }
73 }
74}
75
76fn offset(first: &str, second: &str) -> usize {
77 let p1 = first.as_ptr();
78 let p2 = second.as_ptr();
79 p2 as usize - p1 as usize
80}