Markdown parser fork with extended syntax for personal use.
1//! Deal with bytes.
2
3use crate::event::{Event, Kind, Point};
4use crate::util::constant::TAB_SIZE;
5use alloc::{format, string::String, vec};
6use core::str;
7
8/// A range between two points.
9#[derive(Debug)]
10pub struct Position<'a> {
11 /// Start point.
12 pub start: &'a Point,
13 /// End point.
14 pub end: &'a Point,
15}
16
17impl<'a> Position<'a> {
18 /// Get a position from an exit event.
19 ///
20 /// Looks backwards for the corresponding `enter` event.
21 /// This does not support nested events (such as lists in lists).
22 ///
23 /// ## Panics
24 ///
25 /// This function panics if an enter event is given.
26 /// When `markdown-rs` is used, this function never panics.
27 pub fn from_exit_event(events: &'a [Event], index: usize) -> Position<'a> {
28 debug_assert_eq!(events[index].kind, Kind::Exit, "expected `exit` event");
29 let end = &events[index].point;
30 let name = &events[index].name;
31 let mut index = index - 1;
32
33 while !(events[index].kind == Kind::Enter && events[index].name == *name) {
34 index -= 1;
35 }
36
37 let start = &events[index].point;
38
39 Position { start, end }
40 }
41
42 /// Turn a position into indices.
43 ///
44 /// Indices are places in `bytes` where this position starts and ends.
45 ///
46 /// > 👉 **Note**: indices cannot represent virtual spaces.
47 pub fn to_indices(&self) -> (usize, usize) {
48 (self.start.index, self.end.index)
49 }
50}
51
52/// Bytes belonging to a range.
53///
54/// Includes info on virtual spaces before and after the bytes.
55#[derive(Debug)]
56pub struct Slice<'a> {
57 /// Bytes.
58 pub bytes: &'a [u8],
59 /// Number of virtual spaces before the bytes.
60 pub before: usize,
61 /// Number of virtual spaces after the bytes.
62 pub after: usize,
63}
64
65impl<'a> Slice<'a> {
66 /// Get a slice for a position.
67 pub fn from_position(bytes: &'a [u8], position: &Position) -> Slice<'a> {
68 let mut before = position.start.vs;
69 let mut after = position.end.vs;
70 let mut start = position.start.index;
71 let mut end = position.end.index;
72
73 // If we have virtual spaces before, it means we are past the actual
74 // character at that index, and those virtual spaces.
75 if before > 0 {
76 before = TAB_SIZE - before;
77 start += 1;
78 }
79
80 // If we have virtual spaces after, it means that character is included,
81 // and one less virtual space.
82 if after > 0 {
83 after -= 1;
84 end += 1;
85 }
86
87 Slice {
88 bytes: &bytes[start..end],
89 before,
90 after,
91 }
92 }
93
94 /// Get a slice for two indices.
95 ///
96 /// > 👉 **Note**: indices cannot represent virtual spaces.
97 pub fn from_indices(bytes: &'a [u8], start: usize, end: usize) -> Slice<'a> {
98 Slice {
99 bytes: &bytes[start..end],
100 before: 0,
101 after: 0,
102 }
103 }
104
105 /// Get the size of this slice, including virtual spaces.
106 pub fn len(&self) -> usize {
107 self.bytes.len() + self.before + self.after
108 }
109
110 /// Turn the slice into a `&str`.
111 ///
112 /// > 👉 **Note**: cannot represent virtual spaces.
113 pub fn as_str(&self) -> &str {
114 str::from_utf8(self.bytes).unwrap()
115 }
116
117 /// Turn the slice into a `String`.
118 ///
119 /// Supports virtual spaces.
120 pub fn serialize(&self) -> String {
121 let prefix = String::from_utf8(vec![b' '; self.before]).unwrap();
122 let suffix = String::from_utf8(vec![b' '; self.after]).unwrap();
123 format!("{}{}{}", prefix, self.as_str(), suffix)
124 }
125}