/rust/registry/src/index.crates.io-1949cf8c6b5b557f/combine-4.6.7/src/stream/position.rs
Line | Count | Source |
1 | | use crate::{ |
2 | | error::{ParseError, ParseResult, StreamError}, |
3 | | lib::fmt, |
4 | | stream::{ |
5 | | IteratorStream, Positioned, RangeStreamOnce, ResetStream, SliceStream, StreamErrorFor, |
6 | | StreamOnce, |
7 | | }, |
8 | | }; |
9 | | |
10 | | #[cfg(feature = "std")] |
11 | | use crate::stream::read; |
12 | | |
13 | | /// Trait for tracking the current position of a `Stream`. |
14 | | pub trait Positioner<Item> { |
15 | | /// The type which keeps track of the position |
16 | | type Position: Clone + Ord; |
17 | | |
18 | | type Checkpoint: Clone; |
19 | | |
20 | | /// Returns the current position |
21 | | fn position(&self) -> Self::Position; |
22 | | /// Updates the position given that `token` has been taken from the stream |
23 | | fn update(&mut self, token: &Item); |
24 | | |
25 | | fn checkpoint(&self) -> Self::Checkpoint; |
26 | | fn reset(&mut self, checkpoint: Self::Checkpoint); |
27 | | } |
28 | | |
29 | | /// Trait for tracking the current position of a `RangeStream`. |
30 | | pub trait RangePositioner<Item, Range>: Positioner<Item> { |
31 | | /// Updates the position given that `range` has been taken from the stream |
32 | | fn update_range(&mut self, range: &Range); |
33 | | } |
34 | | |
35 | | /// Defines a default `Positioner` type for a particular `Stream` type. |
36 | | pub trait DefaultPositioned { |
37 | | type Positioner: Default; |
38 | | } |
39 | | |
40 | | impl<'a> DefaultPositioned for &'a str { |
41 | | type Positioner = SourcePosition; |
42 | | } |
43 | | |
44 | | impl<'a, T> DefaultPositioned for &'a [T] { |
45 | | type Positioner = IndexPositioner; |
46 | | } |
47 | | |
48 | | impl<'a, T> DefaultPositioned for SliceStream<'a, T> { |
49 | | type Positioner = IndexPositioner; |
50 | | } |
51 | | |
52 | | impl<T> DefaultPositioned for IteratorStream<T> { |
53 | | type Positioner = IndexPositioner; |
54 | | } |
55 | | |
56 | | #[cfg(feature = "std")] |
57 | | impl<R> DefaultPositioned for read::Stream<R> { |
58 | | type Positioner = IndexPositioner; |
59 | | } |
60 | | |
61 | | /// The `Stream<Input>` struct maintains the current position in the stream `Input` using |
62 | | /// the `Positioner` trait to track the position. |
63 | | /// |
64 | | /// ``` |
65 | | /// # #![cfg(feature = "std")] |
66 | | /// # extern crate combine; |
67 | | /// # use combine::*; |
68 | | /// # use combine::stream::easy; |
69 | | /// # use combine::stream::position; |
70 | | /// # fn main() { |
71 | | /// let result = token(b'9') |
72 | | /// .message("Not a nine") |
73 | | /// .easy_parse(position::Stream::new(&b"8"[..])); |
74 | | /// assert_eq!(result, Err(easy::Errors { |
75 | | /// position: 0, |
76 | | /// errors: vec![ |
77 | | /// easy::Error::Unexpected(b'8'.into()), |
78 | | /// easy::Error::Expected(b'9'.into()), |
79 | | /// easy::Error::Message("Not a nine".into()) |
80 | | /// ] |
81 | | /// })); |
82 | | /// # } |
83 | | /// ``` |
84 | | #[derive(Clone, Debug, PartialEq)] |
85 | | pub struct Stream<Input, X> { |
86 | | /// The input stream used when items are requested |
87 | | pub input: Input, |
88 | | /// The positioner used to update the current position |
89 | | pub positioner: X, |
90 | | } |
91 | | |
92 | | impl<Input, X> Stream<Input, X> |
93 | | where |
94 | | Input: StreamOnce, |
95 | | X: Positioner<Input::Token>, |
96 | | { |
97 | | /// Creates a new `Stream<Input, X>` from an input stream and a positioner. |
98 | 0 | pub fn with_positioner(input: Input, positioner: X) -> Stream<Input, X> { |
99 | 0 | Stream { input, positioner } |
100 | 0 | } |
101 | | } |
102 | | |
103 | | impl<Input> Stream<Input, Input::Positioner> |
104 | | where |
105 | | Input: StreamOnce + DefaultPositioned, |
106 | | Input::Positioner: Positioner<Input::Token>, |
107 | | { |
108 | | /// Creates a new `Stream<Input, X>` from an input stream and its default positioner. |
109 | 0 | pub fn new(input: Input) -> Stream<Input, Input::Positioner> { |
110 | 0 | Stream::with_positioner(input, Input::Positioner::default()) |
111 | 0 | } |
112 | | } |
113 | | |
114 | | impl<Input, X, S> Positioned for Stream<Input, X> |
115 | | where |
116 | | Input: StreamOnce, |
117 | | X: Positioner<Input::Token>, |
118 | | S: StreamError<Input::Token, Input::Range>, |
119 | | Input::Error: ParseError<Input::Token, Input::Range, X::Position, StreamError = S>, |
120 | | Input::Error: ParseError<Input::Token, Input::Range, Input::Position, StreamError = S>, |
121 | | { |
122 | | #[inline] |
123 | 0 | fn position(&self) -> Self::Position { |
124 | 0 | self.positioner.position() |
125 | 0 | } |
126 | | } |
127 | | |
128 | | impl<Input, X, S> StreamOnce for Stream<Input, X> |
129 | | where |
130 | | Input: StreamOnce, |
131 | | X: Positioner<Input::Token>, |
132 | | S: StreamError<Input::Token, Input::Range>, |
133 | | Input::Error: ParseError<Input::Token, Input::Range, X::Position, StreamError = S>, |
134 | | Input::Error: ParseError<Input::Token, Input::Range, Input::Position, StreamError = S>, |
135 | | { |
136 | | type Token = Input::Token; |
137 | | type Range = Input::Range; |
138 | | type Position = X::Position; |
139 | | type Error = Input::Error; |
140 | | |
141 | | #[inline] |
142 | 0 | fn uncons(&mut self) -> Result<Input::Token, StreamErrorFor<Self>> { |
143 | 0 | self.input.uncons().map(|c| { |
144 | 0 | self.positioner.update(&c); |
145 | 0 | c |
146 | 0 | }) |
147 | 0 | } |
148 | | |
149 | 0 | fn is_partial(&self) -> bool { |
150 | 0 | self.input.is_partial() |
151 | 0 | } |
152 | | } |
153 | | |
154 | | impl<Item, T> Positioner<Item> for &'_ mut T |
155 | | where |
156 | | Item: Clone, |
157 | | T: ?Sized + Positioner<Item>, |
158 | | { |
159 | | type Position = T::Position; |
160 | | type Checkpoint = T::Checkpoint; |
161 | | |
162 | | #[inline] |
163 | 0 | fn position(&self) -> T::Position { |
164 | 0 | (**self).position() |
165 | 0 | } |
166 | | |
167 | | #[inline] |
168 | 0 | fn update(&mut self, item: &Item) { |
169 | 0 | (**self).update(item) |
170 | 0 | } |
171 | | |
172 | | #[inline] |
173 | 0 | fn checkpoint(&self) -> Self::Checkpoint { |
174 | 0 | (**self).checkpoint() |
175 | 0 | } |
176 | | |
177 | | #[inline] |
178 | 0 | fn reset(&mut self, checkpoint: Self::Checkpoint) { |
179 | 0 | (**self).reset(checkpoint) |
180 | 0 | } |
181 | | } |
182 | | |
183 | | impl<Item, Range, T> RangePositioner<Item, Range> for &'_ mut T |
184 | | where |
185 | | Item: Clone, |
186 | | Range: Clone + crate::stream::Range, |
187 | | T: ?Sized + RangePositioner<Item, Range>, |
188 | | { |
189 | 0 | fn update_range(&mut self, range: &Range) { |
190 | 0 | (**self).update_range(range); |
191 | 0 | } |
192 | | } |
193 | | |
194 | | /// The `IndexPositioner<Item, Range>` struct maintains the current index into the stream `Input`. The |
195 | | /// initial index is index 0. Each `Item` committed increments the index by 1; each `range` committed |
196 | | /// increments the position by `range.len()`. |
197 | | #[derive(Clone, Debug, Default, PartialEq)] |
198 | | pub struct IndexPositioner(usize); |
199 | | |
200 | | impl<Item> Positioner<Item> for IndexPositioner |
201 | | where |
202 | | Item: Clone, |
203 | | { |
204 | | type Position = usize; |
205 | | type Checkpoint = Self; |
206 | | |
207 | | #[inline] |
208 | 0 | fn position(&self) -> usize { |
209 | 0 | self.0 |
210 | 0 | } |
211 | | |
212 | | #[inline] |
213 | 0 | fn update(&mut self, _item: &Item) { |
214 | 0 | self.0 += 1 |
215 | 0 | } |
216 | | |
217 | | #[inline] |
218 | 0 | fn checkpoint(&self) -> Self::Checkpoint { |
219 | 0 | self.clone() |
220 | 0 | } |
221 | | |
222 | | #[inline] |
223 | 0 | fn reset(&mut self, checkpoint: Self::Checkpoint) { |
224 | 0 | *self = checkpoint; |
225 | 0 | } |
226 | | } |
227 | | |
228 | | impl IndexPositioner { |
229 | 0 | pub fn new() -> IndexPositioner { |
230 | 0 | IndexPositioner::new_with_position(0) |
231 | 0 | } |
232 | | |
233 | 0 | pub fn new_with_position(position: usize) -> IndexPositioner { |
234 | 0 | IndexPositioner(position) |
235 | 0 | } |
236 | | } |
237 | | |
238 | | impl<Item, Range> RangePositioner<Item, Range> for IndexPositioner |
239 | | where |
240 | | Item: Clone, |
241 | | Range: Clone + crate::stream::Range, |
242 | | { |
243 | 0 | fn update_range(&mut self, range: &Range) { |
244 | 0 | self.0 += range.len() |
245 | 0 | } |
246 | | } |
247 | | |
248 | | /// Struct which represents a position in a source file. |
249 | | #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] |
250 | | pub struct SourcePosition { |
251 | | /// Current line of the input |
252 | | pub line: i32, |
253 | | /// Current column of the input |
254 | | pub column: i32, |
255 | | } |
256 | | |
257 | | impl Default for SourcePosition { |
258 | 0 | fn default() -> Self { |
259 | 0 | SourcePosition { line: 1, column: 1 } |
260 | 0 | } |
261 | | } |
262 | | |
263 | | impl fmt::Display for SourcePosition { |
264 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
265 | 0 | write!(f, "line: {}, column: {}", self.line, self.column) |
266 | 0 | } |
267 | | } |
268 | | |
269 | | impl SourcePosition { |
270 | 0 | pub fn new() -> Self { |
271 | 0 | SourcePosition::default() |
272 | 0 | } |
273 | | } |
274 | | |
275 | | impl Positioner<char> for SourcePosition { |
276 | | type Position = SourcePosition; |
277 | | type Checkpoint = Self; |
278 | | |
279 | | #[inline] |
280 | 0 | fn position(&self) -> SourcePosition { |
281 | 0 | *self |
282 | 0 | } |
283 | | |
284 | | #[inline] |
285 | 0 | fn update(&mut self, token: &char) { |
286 | 0 | self.column += 1; |
287 | 0 | if *token == '\n' { |
288 | 0 | self.column = 1; |
289 | 0 | self.line += 1; |
290 | 0 | } |
291 | 0 | } |
292 | | |
293 | | #[inline] |
294 | 0 | fn checkpoint(&self) -> Self::Checkpoint { |
295 | 0 | *self |
296 | 0 | } |
297 | | |
298 | | #[inline] |
299 | 0 | fn reset(&mut self, checkpoint: Self::Checkpoint) { |
300 | 0 | *self = checkpoint; |
301 | 0 | } |
302 | | } |
303 | | |
304 | | impl Positioner<u8> for SourcePosition { |
305 | | type Position = SourcePosition; |
306 | | type Checkpoint = Self; |
307 | | |
308 | | #[inline] |
309 | 0 | fn position(&self) -> SourcePosition { |
310 | 0 | *self |
311 | 0 | } |
312 | | |
313 | | #[inline] |
314 | 0 | fn update(&mut self, token: &u8) { |
315 | 0 | self.column += 1; |
316 | 0 | if *token == b'\n' { |
317 | 0 | self.column = 1; |
318 | 0 | self.line += 1; |
319 | 0 | } |
320 | 0 | } |
321 | | |
322 | | #[inline] |
323 | 0 | fn checkpoint(&self) -> Self::Checkpoint { |
324 | 0 | *self |
325 | 0 | } |
326 | | |
327 | | #[inline] |
328 | 0 | fn reset(&mut self, checkpoint: Self::Checkpoint) { |
329 | 0 | *self = checkpoint; |
330 | 0 | } |
331 | | } |
332 | | |
333 | | impl<'a> RangePositioner<char, &'a str> for SourcePosition { |
334 | 0 | fn update_range(&mut self, range: &&'a str) { |
335 | 0 | for c in range.chars() { |
336 | 0 | self.update(&c); |
337 | 0 | } |
338 | 0 | } |
339 | | } |
340 | | |
341 | | impl<Input, X, S> RangeStreamOnce for Stream<Input, X> |
342 | | where |
343 | | Input: RangeStreamOnce, |
344 | | X: RangePositioner<Input::Token, Input::Range>, |
345 | | S: StreamError<Input::Token, Input::Range>, |
346 | | Input::Error: ParseError<Input::Token, Input::Range, X::Position, StreamError = S>, |
347 | | Input::Error: ParseError<Input::Token, Input::Range, Input::Position, StreamError = S>, |
348 | | Input::Position: Clone + Ord, |
349 | | { |
350 | | #[inline] |
351 | 0 | fn uncons_range(&mut self, size: usize) -> Result<Input::Range, StreamErrorFor<Self>> { |
352 | 0 | self.input.uncons_range(size).map(|range| { |
353 | 0 | self.positioner.update_range(&range); |
354 | 0 | range |
355 | 0 | }) |
356 | 0 | } |
357 | | |
358 | | #[inline] |
359 | 0 | fn uncons_while<F>(&mut self, mut predicate: F) -> Result<Input::Range, StreamErrorFor<Self>> |
360 | 0 | where |
361 | 0 | F: FnMut(Input::Token) -> bool, |
362 | | { |
363 | 0 | let positioner = &mut self.positioner; |
364 | 0 | self.input.uncons_while(|t| { |
365 | 0 | if predicate(t.clone()) { |
366 | 0 | positioner.update(&t); |
367 | 0 | true |
368 | | } else { |
369 | 0 | false |
370 | | } |
371 | 0 | }) |
372 | 0 | } |
373 | | |
374 | | #[inline] |
375 | 0 | fn uncons_while1<F>( |
376 | 0 | &mut self, |
377 | 0 | mut predicate: F, |
378 | 0 | ) -> ParseResult<Self::Range, StreamErrorFor<Self>> |
379 | 0 | where |
380 | 0 | F: FnMut(Self::Token) -> bool, |
381 | | { |
382 | 0 | let positioner = &mut self.positioner; |
383 | 0 | self.input.uncons_while1(|t| { |
384 | 0 | if predicate(t.clone()) { |
385 | 0 | positioner.update(&t); |
386 | 0 | true |
387 | | } else { |
388 | 0 | false |
389 | | } |
390 | 0 | }) |
391 | 0 | } |
392 | | |
393 | | #[inline] |
394 | 0 | fn distance(&self, end: &Self::Checkpoint) -> usize { |
395 | 0 | self.input.distance(&end.input) |
396 | 0 | } |
397 | | |
398 | 0 | fn range(&self) -> Self::Range { |
399 | 0 | self.input.range() |
400 | 0 | } |
401 | | } |
402 | | |
403 | | impl<Input, X, S> ResetStream for Stream<Input, X> |
404 | | where |
405 | | Input: ResetStream, |
406 | | X: Positioner<Input::Token>, |
407 | | S: StreamError<Input::Token, Input::Range>, |
408 | | Input::Error: ParseError<Input::Token, Input::Range, X::Position, StreamError = S>, |
409 | | Input::Error: ParseError<Input::Token, Input::Range, Input::Position, StreamError = S>, |
410 | | { |
411 | | type Checkpoint = Stream<Input::Checkpoint, X::Checkpoint>; |
412 | 0 | fn checkpoint(&self) -> Self::Checkpoint { |
413 | 0 | Stream { |
414 | 0 | input: self.input.checkpoint(), |
415 | 0 | positioner: self.positioner.checkpoint(), |
416 | 0 | } |
417 | 0 | } |
418 | 0 | fn reset(&mut self, checkpoint: Self::Checkpoint) -> Result<(), Self::Error> { |
419 | 0 | self.input.reset(checkpoint.input)?; |
420 | 0 | self.positioner.reset(checkpoint.positioner); |
421 | 0 | Ok(()) |
422 | 0 | } |
423 | | } |
424 | | |
425 | | #[cfg(all(feature = "std", test))] |
426 | | mod tests { |
427 | | |
428 | | use crate::Parser; |
429 | | |
430 | | use super::*; |
431 | | |
432 | | #[test] |
433 | | fn test_positioner() { |
434 | | let input = ["a".to_string(), "b".to_string()]; |
435 | | let mut parser = crate::any(); |
436 | | let result = parser.parse(Stream::new(&input[..])); |
437 | | assert_eq!( |
438 | | result, |
439 | | Ok(( |
440 | | "a".to_string(), |
441 | | Stream::with_positioner( |
442 | | &["b".to_string()][..], |
443 | | IndexPositioner::new_with_position(1) |
444 | | ) |
445 | | )) |
446 | | ); |
447 | | } |
448 | | |
449 | | #[test] |
450 | | fn test_range_positioner() { |
451 | | let input = ["a".to_string(), "b".to_string(), "c".to_string()]; |
452 | | let mut parser = crate::parser::range::take(2); |
453 | | let result = parser.parse(Stream::new(&input[..])); |
454 | | assert_eq!( |
455 | | result, |
456 | | Ok(( |
457 | | &["a".to_string(), "b".to_string()][..], |
458 | | Stream::with_positioner( |
459 | | &["c".to_string()][..], |
460 | | IndexPositioner::new_with_position(2) |
461 | | ) |
462 | | )) |
463 | | ); |
464 | | } |
465 | | } |