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
position(&self) -> Self::Position21     fn position(&self) -> Self::Position;
22     /// Updates the position given that `token` has been taken from the stream
update(&mut self, token: &Item)23     fn update(&mut self, token: &Item);
24 
checkpoint(&self) -> Self::Checkpoint25     fn checkpoint(&self) -> Self::Checkpoint;
reset(&mut self, checkpoint: 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
update_range(&mut self, range: &Range)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.
with_positioner(input: Input, positioner: X) -> Stream<Input, X>98     pub fn with_positioner(input: Input, positioner: X) -> Stream<Input, X> {
99         Stream { input, positioner }
100     }
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.
new(input: Input) -> Stream<Input, Input::Positioner>109     pub fn new(input: Input) -> Stream<Input, Input::Positioner> {
110         Stream::with_positioner(input, Input::Positioner::default())
111     }
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]
position(&self) -> Self::Position123     fn position(&self) -> Self::Position {
124         self.positioner.position()
125     }
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]
uncons(&mut self) -> Result<Input::Token, StreamErrorFor<Self>>142     fn uncons(&mut self) -> Result<Input::Token, StreamErrorFor<Self>> {
143         self.input.uncons().map(|c| {
144             self.positioner.update(&c);
145             c
146         })
147     }
148 
is_partial(&self) -> bool149     fn is_partial(&self) -> bool {
150         self.input.is_partial()
151     }
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]
position(&self) -> T::Position163     fn position(&self) -> T::Position {
164         (**self).position()
165     }
166 
167     #[inline]
update(&mut self, item: &Item)168     fn update(&mut self, item: &Item) {
169         (**self).update(item)
170     }
171 
172     #[inline]
checkpoint(&self) -> Self::Checkpoint173     fn checkpoint(&self) -> Self::Checkpoint {
174         (**self).checkpoint()
175     }
176 
177     #[inline]
reset(&mut self, checkpoint: Self::Checkpoint)178     fn reset(&mut self, checkpoint: Self::Checkpoint) {
179         (**self).reset(checkpoint)
180     }
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 {
update_range(&mut self, range: &Range)189     fn update_range(&mut self, range: &Range) {
190         (**self).update_range(range);
191     }
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]
position(&self) -> usize208     fn position(&self) -> usize {
209         self.0
210     }
211 
212     #[inline]
update(&mut self, _item: &Item)213     fn update(&mut self, _item: &Item) {
214         self.0 += 1
215     }
216 
217     #[inline]
checkpoint(&self) -> Self::Checkpoint218     fn checkpoint(&self) -> Self::Checkpoint {
219         self.clone()
220     }
221 
222     #[inline]
reset(&mut self, checkpoint: Self::Checkpoint)223     fn reset(&mut self, checkpoint: Self::Checkpoint) {
224         *self = checkpoint;
225     }
226 }
227 
228 impl IndexPositioner {
new() -> IndexPositioner229     pub fn new() -> IndexPositioner {
230         IndexPositioner::new_with_position(0)
231     }
232 
new_with_position(position: usize) -> IndexPositioner233     pub fn new_with_position(position: usize) -> IndexPositioner {
234         IndexPositioner(position)
235     }
236 }
237 
238 impl<Item, Range> RangePositioner<Item, Range> for IndexPositioner
239 where
240     Item: Clone,
241     Range: Clone + crate::stream::Range,
242 {
update_range(&mut self, range: &Range)243     fn update_range(&mut self, range: &Range) {
244         self.0 += range.len()
245     }
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 {
default() -> Self258     fn default() -> Self {
259         SourcePosition { line: 1, column: 1 }
260     }
261 }
262 
263 impl fmt::Display for SourcePosition {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result264     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265         write!(f, "line: {}, column: {}", self.line, self.column)
266     }
267 }
268 
269 impl SourcePosition {
new() -> Self270     pub fn new() -> Self {
271         SourcePosition::default()
272     }
273 }
274 
275 impl Positioner<char> for SourcePosition {
276     type Position = SourcePosition;
277     type Checkpoint = Self;
278 
279     #[inline]
position(&self) -> SourcePosition280     fn position(&self) -> SourcePosition {
281         *self
282     }
283 
284     #[inline]
update(&mut self, token: &char)285     fn update(&mut self, token: &char) {
286         self.column += 1;
287         if *token == '\n' {
288             self.column = 1;
289             self.line += 1;
290         }
291     }
292 
293     #[inline]
checkpoint(&self) -> Self::Checkpoint294     fn checkpoint(&self) -> Self::Checkpoint {
295         *self
296     }
297 
298     #[inline]
reset(&mut self, checkpoint: Self::Checkpoint)299     fn reset(&mut self, checkpoint: Self::Checkpoint) {
300         *self = checkpoint;
301     }
302 }
303 
304 impl Positioner<u8> for SourcePosition {
305     type Position = SourcePosition;
306     type Checkpoint = Self;
307 
308     #[inline]
position(&self) -> SourcePosition309     fn position(&self) -> SourcePosition {
310         *self
311     }
312 
313     #[inline]
update(&mut self, token: &u8)314     fn update(&mut self, token: &u8) {
315         self.column += 1;
316         if *token == b'\n' {
317             self.column = 1;
318             self.line += 1;
319         }
320     }
321 
322     #[inline]
checkpoint(&self) -> Self::Checkpoint323     fn checkpoint(&self) -> Self::Checkpoint {
324         *self
325     }
326 
327     #[inline]
reset(&mut self, checkpoint: Self::Checkpoint)328     fn reset(&mut self, checkpoint: Self::Checkpoint) {
329         *self = checkpoint;
330     }
331 }
332 
333 impl<'a> RangePositioner<char, &'a str> for SourcePosition {
update_range(&mut self, range: &&'a str)334     fn update_range(&mut self, range: &&'a str) {
335         for c in range.chars() {
336             self.update(&c);
337         }
338     }
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]
uncons_range(&mut self, size: usize) -> Result<Input::Range, StreamErrorFor<Self>>351     fn uncons_range(&mut self, size: usize) -> Result<Input::Range, StreamErrorFor<Self>> {
352         self.input.uncons_range(size).map(|range| {
353             self.positioner.update_range(&range);
354             range
355         })
356     }
357 
358     #[inline]
uncons_while<F>(&mut self, mut predicate: F) -> Result<Input::Range, StreamErrorFor<Self>> where F: FnMut(Input::Token) -> bool,359     fn uncons_while<F>(&mut self, mut predicate: F) -> Result<Input::Range, StreamErrorFor<Self>>
360     where
361         F: FnMut(Input::Token) -> bool,
362     {
363         let positioner = &mut self.positioner;
364         self.input.uncons_while(|t| {
365             if predicate(t.clone()) {
366                 positioner.update(&t);
367                 true
368             } else {
369                 false
370             }
371         })
372     }
373 
374     #[inline]
uncons_while1<F>( &mut self, mut predicate: F, ) -> ParseResult<Self::Range, StreamErrorFor<Self>> where F: FnMut(Self::Token) -> bool,375     fn uncons_while1<F>(
376         &mut self,
377         mut predicate: F,
378     ) -> ParseResult<Self::Range, StreamErrorFor<Self>>
379     where
380         F: FnMut(Self::Token) -> bool,
381     {
382         let positioner = &mut self.positioner;
383         self.input.uncons_while1(|t| {
384             if predicate(t.clone()) {
385                 positioner.update(&t);
386                 true
387             } else {
388                 false
389             }
390         })
391     }
392 
393     #[inline]
distance(&self, end: &Self::Checkpoint) -> usize394     fn distance(&self, end: &Self::Checkpoint) -> usize {
395         self.input.distance(&end.input)
396     }
397 
range(&self) -> Self::Range398     fn range(&self) -> Self::Range {
399         self.input.range()
400     }
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>;
checkpoint(&self) -> Self::Checkpoint412     fn checkpoint(&self) -> Self::Checkpoint {
413         Stream {
414             input: self.input.checkpoint(),
415             positioner: self.positioner.checkpoint(),
416         }
417     }
reset(&mut self, checkpoint: Self::Checkpoint) -> Result<(), Self::Error>418     fn reset(&mut self, checkpoint: Self::Checkpoint) -> Result<(), Self::Error> {
419         self.input.reset(checkpoint.input)?;
420         self.positioner.reset(checkpoint.positioner);
421         Ok(())
422     }
423 }
424 
425 #[cfg(all(feature = "std", test))]
426 mod tests {
427 
428     use crate::Parser;
429 
430     use super::*;
431 
432     #[test]
test_positioner()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]
test_range_positioner()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 }
466