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 peek(&self) -> ParserResult<Option<u8>> {
43 self.peek_n(1)
44 }
45
46 pub(crate) fn current(&self) -> ParserResult<Option<u8>> {
48 self.peek_n(0)
49 }
50
51 pub(crate) fn peek_n(&self, n: usize) -> ParserResult<Option<u8>> {
53 T::get_ascii(self.source, self.pos + n)
54 }
55
56 pub(crate) fn check<F>(&self, f: F) -> ParserResult<Option<bool>>
58 where
59 F: FnOnce(u8) -> bool,
60 {
61 Ok(self.current()?.map(f))
62 }
63
64 pub(crate) fn check_or<F>(&self, default: bool, f: F) -> ParserResult<bool>
66 where
67 F: FnOnce(u8) -> bool,
68 {
69 Ok(self.current()?.map_or(default, f))
70 }
71
72 pub(crate) fn next(&mut self) -> ParserResult<Option<u8>> {
74 let result = self.current();
75 self.advance_n(1);
76 result
77 }
78
79 pub(crate) fn next_digit(&mut self) -> ParserResult<Option<u8>> {
84 let ascii_char = self.next_or(ParseError::AbruptEnd { location: "digit" })?;
85 if ascii_char.is_ascii_digit() {
86 Ok(Some(ascii_char - 48))
87 } else {
88 Ok(None)
89 }
90 }
91
92 pub(crate) fn next_or(&mut self, err: ParseError) -> ParserResult<u8> {
94 self.next()?.ok_or(err)
95 }
96
97 pub(crate) fn advance_n(&mut self, n: usize) {
99 self.pos += n;
100 }
101
102 pub(crate) fn advance(&mut self) {
104 self.advance_n(1)
105 }
106
107 pub(crate) fn advance_if(&mut self, condition: bool) {
109 if condition {
110 self.advance();
111 }
112 }
113
114 pub(crate) fn close(&mut self) -> ParserResult<()> {
116 if self.pos < self.source.len() {
117 return Err(ParseError::InvalidEnd);
118 }
119 Ok(())
120 }
121}