Markdown parser fork with extended syntax for personal use.
at hack 125 lines 3.6 kB view raw
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}