1use crate::encoding::EncodingType;
8use crate::{ParseError, ParserResult};
9
10#[derive(Debug)]
14pub(crate) struct Cursor<'a, T: EncodingType> {
15 pos: usize,
16 source: &'a [T::CodeUnit],
17}
18
19impl<'a, T: EncodingType> Cursor<'a, T> {
20 #[must_use]
22 pub fn new(source: &'a [T::CodeUnit]) -> Self {
23 Self { pos: 0, source }
24 }
25
26 pub(crate) fn slice(&self, start: usize, end: usize) -> Option<&'a [T::CodeUnit]> {
28 T::slice(self.source, start, end)
29 }
30
31 pub(crate) const fn pos(&self) -> usize {
33 self.pos
34 }
35
36 pub(crate) fn set_position(&mut self, pos: usize) {
38 self.pos = pos;
39 }
40
41 pub(crate) fn current(&self) -> ParserResult<Option<u8>> {
43 self.peek_n(0)
44 }
45
46 pub(crate) fn peek_n(&self, n: usize) -> ParserResult<Option<u8>> {
48 T::get_ascii(self.source, self.pos + n)
49 }
50
51 pub(crate) fn check<F>(&self, f: F) -> ParserResult<Option<bool>>
53 where
54 F: FnOnce(u8) -> bool,
55 {
56 Ok(self.current()?.map(f))
57 }
58
59 pub(crate) fn check_or<F>(&self, default: bool, f: F) -> ParserResult<bool>
61 where
62 F: FnOnce(u8) -> bool,
63 {
64 Ok(self.current()?.map_or(default, f))
65 }
66
67 pub(crate) fn next(&mut self) -> ParserResult<Option<u8>> {
69 let result = self.current();
70 self.advance_n(1);
71 result
72 }
73
74 pub(crate) fn next_if(&mut self, f: impl FnOnce(u8) -> bool) -> ParserResult<Option<u8>> {
76 if let Some(ch) = self.current()? {
77 if f(ch) {
78 self.advance();
79 return Ok(Some(ch));
80 }
81 }
82 Ok(None)
83 }
84
85 pub(crate) fn next_digit(&mut self) -> ParserResult<Option<u8>> {
90 let ascii_char = self.next_or(ParseError::AbruptEnd { location: "digit" })?;
91 if ascii_char.is_ascii_digit() {
92 Ok(Some(ascii_char - 48))
93 } else {
94 Ok(None)
95 }
96 }
97
98 pub(crate) fn next_or(&mut self, err: ParseError) -> ParserResult<u8> {
100 self.next()?.ok_or(err)
101 }
102
103 pub(crate) fn advance_n(&mut self, n: usize) {
105 self.pos += n;
106 }
107
108 pub(crate) fn advance(&mut self) {
110 self.advance_n(1)
111 }
112
113 pub(crate) fn advance_if(&mut self, condition: bool) {
115 if condition {
116 self.advance();
117 }
118 }
119
120 pub(crate) fn close(&mut self) -> ParserResult<()> {
122 if self.pos < self.source.len() {
123 return Err(ParseError::InvalidEnd);
124 }
125 Ok(())
126 }
127}