noa_parser/scanner.rs
1//! A scanner for a sequence of elements.
2
3use crate::errors::ParseResult;
4use crate::visitor::Visitor;
5use std::io::Cursor;
6use std::ops::Deref;
7
8/// Wrapper around a `Cursor`.
9#[derive(Debug, PartialEq)]
10pub struct Scanner<'a, T> {
11 /// The internal cursor.
12 cursor: Cursor<&'a [T]>,
13}
14
15impl<'a, T> Scanner<'a, T> {
16 pub fn new(data: &'a [T]) -> Scanner<'a, T> {
17 Scanner {
18 cursor: Cursor::new(data),
19 }
20 }
21}
22
23impl<'a, T> Scanner<'a, T> {
24 /// Move the internal cursor forward by `n` positions.
25 ///
26 /// # Arguments
27 ///
28 /// * `n` - The number of positions to move the cursor forward.
29 ///
30 /// # Panics
31 ///
32 /// Panics if the internal cursor is moved past the end of the data.
33 pub fn bump_by(&mut self, n: usize) {
34 self.cursor.set_position(self.cursor.position() + n as u64);
35 }
36
37 /// Move the internal cursor to the specified position.
38 ///
39 /// # Arguments
40 ///
41 /// * `n` - The position to move the cursor to.
42 ///
43 /// # Panics
44 ///
45 /// Panics if the internal cursor is moved past the end of the data.
46 pub fn jump_to(&mut self, n: usize) {
47 self.cursor.set_position(n as u64);
48 }
49
50 /// Move the internal cursor backward by `n` positions.
51 ///
52 /// # Arguments
53 ///
54 /// * `n` - The number of positions to move the cursor backward.
55 ///
56 /// # Panics
57 ///
58 /// Panics if the internal cursor is moved to a position before the start of the data.
59 pub fn rewind(&mut self, n: usize) {
60 self.cursor.set_position(self.cursor.position() - n as u64);
61 }
62
63 /// Return the current position of the internal cursor.
64 ///
65 /// # Returns
66 ///
67 /// The current position of the internal cursor.
68 pub fn current_position(&self) -> usize {
69 self.cursor.position() as usize
70 }
71
72 /// Return a slice of the data that remains to be scanned.
73 ///
74 /// # Returns
75 ///
76 /// A slice of the data that remains to be scanned.
77 pub fn remaining(&self) -> &[T] {
78 &self.cursor.get_ref()[self.current_position()..]
79 }
80
81 /// Return the original data given to the scanner.
82 ///
83 /// # Returns
84 ///
85 /// The original data given to the scanner.
86 pub fn data(&self) -> &'a [T] {
87 self.cursor.get_ref()
88 }
89
90 /// Consume the scanner and return a slice of the remaining data.
91 ///
92 /// # Returns
93 ///
94 /// A slice of the remaining data.
95 pub fn into_data(self) -> &'a [T] {
96 &self.cursor.get_ref()[self.current_position()..]
97 }
98
99 /// Return true if there are no more elements to scan, false otherwise.
100 ///
101 /// # Returns
102 ///
103 /// true if there are no more elements to scan, false otherwise.
104 pub fn is_empty(&self) -> bool {
105 self.remaining().is_empty()
106 }
107}
108
109impl<'a, T> Deref for Scanner<'a, T> {
110 type Target = [T];
111 fn deref(&self) -> &Self::Target {
112 self.remaining()
113 }
114}
115
116impl<'a, T> Scanner<'a, T> {
117 /// Run a visitor on the scanner.
118 ///
119 /// # Type Parameters
120 ///
121 /// * `V` - The type of the visitor to run.
122 ///
123 /// # Arguments
124 ///
125 /// * `&mut self` - The scanner to run the visitor on.
126 ///
127 /// # Returns
128 ///
129 /// The result of running the visitor on the scanner.
130 pub fn visit<V: Visitor<'a, T>>(&mut self) -> ParseResult<V> {
131 V::accept(self)
132 }
133}