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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
mod helpers; pub mod test; use std::borrow::Cow; pub struct Cursor<'a> { doc: Cow<'a, str>, index: usize, end_index: usize, } impl<'a> From<String> for Cursor<'a> { fn from(doc: String) -> Self { let end_index = doc.chars().count(); Cursor { doc: doc.into(), index: 0, end_index, } } } impl<'a> From<&'a String> for Cursor<'a> { fn from(doc: &'a String) -> Self { let end_index = doc.chars().count(); Cursor { doc: doc.into(), index: 0, end_index, } } } impl<'a> From<Cow<'a, str>> for Cursor<'a> { fn from(doc: Cow<'a, str>) -> Self { let end_index = doc.chars().count(); Cursor { doc, index: 0, end_index, } } } impl<'a> Cursor<'a> { pub fn from_string_at( doc: Cow<'a, str>, index: usize, ) -> Cursor<'a> { let end_index = doc.chars().count(); Cursor { doc, index, end_index, } } pub fn get_doc(&self) -> &Cow<'a, str> { &self.doc } pub fn get_index(&self) -> usize { self.index } pub fn get_end_index(&self) -> usize { self.end_index } pub fn is_at(&self, cursor: &Cursor) -> bool { self.index == cursor.index } pub fn is_eof(&self) -> bool { self.index == self.end_index } pub fn set_index_mut(&mut self, index: usize) { if index > self.end_index { self.index = self.end_index; } else { self.index = index; }; } pub fn next_mut(&mut self, count: usize) { self.set_index_mut(self.index + count); } pub fn starts_with(&self, test_str: &str) -> bool { let start = self.index; let count = test_str.chars().count(); self.doc .chars() .skip(start) .take(count) .collect::<String>() == test_str } pub fn one_of<'b>( &self, test_strs: &'b Vec<String>, ) -> Option<&'b String> { for test_str in test_strs { if self.starts_with(test_str) { return Some(test_str); }; } return None; } pub fn lookahead(&self, count: usize) -> String { let start = self.index; self.doc.chars().skip(start).take(count).collect() } pub fn take_until(&self, cursor: &Cursor) -> String { let start = self.index; let count = cursor.get_index() - start; self.doc.chars().skip(start).take(count).collect() } pub fn move_to_mut(&mut self, cursor: &Cursor) { self.index = if cursor.index < self.end_index { cursor.index } else { self.end_index }; } } impl<'a> Clone for Cursor<'a> { fn clone(&self) -> Self { Cursor { doc: self.doc.to_owned(), index: self.index, end_index: self.end_index, } } }