unidok_parser/
input.rs

1use std::ops::{Deref, DerefMut, Index};
2
3use detached_str::{Str, StrSlice};
4
5use crate::{Parse, ParseInfallible};
6
7#[derive(Debug, Clone)]
8pub struct Input {
9    pub text: Str,
10    idx: usize,
11}
12
13impl Input {
14    pub fn new(text: impl ToString) -> Self {
15        Input { text: text.to_string().into(), idx: 0 }
16    }
17
18    #[must_use]
19    pub fn start(&mut self) -> ModifyInput<'_> {
20        let prev_idx = self.idx;
21        ModifyInput { input: self, prev_idx }
22    }
23
24    pub fn len(&self) -> usize {
25        self.text.len() - self.idx
26    }
27
28    pub fn is_empty(&self) -> bool {
29        self.len() == 0
30    }
31
32    pub fn rest(&self) -> &str {
33        &self.text[self.idx as usize..]
34    }
35
36    #[cfg(test)]
37    pub fn prev(&self) -> &str {
38        &self.text[..self.idx as usize]
39    }
40
41    pub fn prev_slice_bytes(&self, bytes: usize) -> StrSlice {
42        self.text.get(self.idx - bytes..self.idx)
43    }
44
45    pub fn bump(&mut self, bytes: usize) -> StrSlice {
46        self.idx += bytes;
47        self.text.get(self.idx - bytes..self.idx)
48    }
49
50    pub fn peek_char(&self) -> Option<char> {
51        self.rest().chars().next()
52    }
53
54    pub fn prev_char(&self) -> Option<char> {
55        let parsed = &self.text[..self.idx as usize];
56        parsed.chars().last()
57    }
58
59    /// This parses the specified parser and returns the result. If it fails,
60    /// [`None`] is returned. For correctness, the parser should NOT be bumped
61    /// if `None` is returned.
62    #[must_use]
63    pub fn parse<P: Parse>(&mut self, mut parser: P) -> Option<P::Output> {
64        parser.parse(self)
65    }
66
67    /// This parses the specified parser and returns the result. The parser
68    /// can't fail.
69    pub fn parse_i<P: ParseInfallible>(&mut self, parser: P) -> P::Output {
70        parser.parse_infallible(self)
71    }
72
73    /// This tries to parse the specified parser. If it doesn't succeed, nothing
74    /// happens.
75    pub fn try_parse<P: Parse>(&mut self, mut parser: P) {
76        parser.parse(self);
77    }
78
79    /// This returns whether the parser can be successfully parsed. For
80    /// correctness, the parser should NOT be bumped.
81    pub fn can_parse<P: Parse>(&mut self, mut parser: P) -> bool {
82        parser.can_parse(self)
83    }
84}
85
86pub struct ModifyInput<'a> {
87    input: &'a mut Input,
88    prev_idx: usize,
89}
90
91impl ModifyInput<'_> {
92    pub fn apply(mut self) -> StrSlice {
93        let prev = self.prev_idx;
94        self.prev_idx = self.input.idx;
95        self.prev_slice_bytes(self.input.idx - prev)
96    }
97}
98
99impl Deref for ModifyInput<'_> {
100    type Target = Input;
101
102    fn deref(&self) -> &Self::Target {
103        self.input
104    }
105}
106
107impl DerefMut for ModifyInput<'_> {
108    fn deref_mut(&mut self) -> &mut Self::Target {
109        self.input
110    }
111}
112
113impl<'a> AsRef<Input> for ModifyInput<'a> {
114    fn as_ref(&self) -> &Input {
115        self.input
116    }
117}
118
119impl<'a> AsMut<Input> for ModifyInput<'a> {
120    fn as_mut(&mut self) -> &mut Input {
121        self.input
122    }
123}
124
125impl Drop for ModifyInput<'_> {
126    fn drop(&mut self) {
127        self.input.idx = self.prev_idx;
128    }
129}
130
131impl Index<StrSlice> for Input {
132    type Output = str;
133
134    fn index(&self, index: StrSlice) -> &Self::Output {
135        &self.text[index.range()]
136    }
137}
138
139#[test]
140fn test_bump() {
141    let mut input = Input::new("abcd");
142    assert_eq!(input.rest(), "abcd");
143    input.bump(2);
144    assert_eq!(input.rest(), "cd");
145    input.bump(2);
146    assert_eq!(input.rest(), "");
147}
148
149#[test]
150fn test_modify() {
151    let mut input = Input::new("abcdef");
152    {
153        let mut input2 = input.start();
154        input2.bump(1);
155        assert_eq!(input2.rest(), "bcdef");
156    }
157    assert_eq!(input.rest(), "abcdef");
158
159    {
160        let mut input3 = input.start();
161        input3.bump(1);
162        input3.apply();
163    }
164    assert_eq!(input.rest(), "bcdef");
165
166    {
167        let mut input4 = input.start();
168        input4.bump(1);
169        {
170            let mut input5 = input4.start();
171            input5.bump(2);
172            input5.apply();
173        }
174    }
175    assert_eq!(input.rest(), "bcdef");
176
177    {
178        let mut input6 = input.start();
179        input6.bump(1);
180        {
181            let mut input7 = input6.start();
182            input7.bump(2);
183        }
184        input6.apply();
185    }
186    assert_eq!(input.rest(), "cdef");
187
188    {
189        let mut input8 = input.start();
190        input8.bump(1);
191        {
192            let mut input9 = input8.start();
193            input9.bump(2);
194            input9.apply();
195        }
196        input8.apply();
197    }
198    assert_eq!(input.rest(), "f");
199
200    {
201        let mut input8 = input.start();
202        input8.bump(1);
203    }
204
205    assert_eq!(input.prev(), "abcde");
206}