tc/
input.rs

1/// Byte position into an input stream.
2pub type Pos = u32;
3
4/// Byte span into an input stream
5/// (first pos, one past last pos)
6pub type Span = (Pos, Pos);
7
8pub trait HasSpan {
9    fn span(&self) -> Span;
10}
11
12/// A cursor over an input stream of characters.
13/// It keeps track of the current position in the stream.
14/// It has the ability to put characters back into the stream.
15#[derive(Debug, Clone)]
16pub struct Cursor<I> {
17    // input iterator
18    input: I,
19    // current position in the stream
20    cur_pos: u32,
21}
22
23impl<I> Cursor<I> {
24    pub fn new(input: I) -> Cursor<I> {
25        Cursor { input, cur_pos: 0 }
26    }
27
28    pub fn pos(&self) -> Pos {
29        self.cur_pos
30    }
31}
32
33impl<I: Iterator<Item = char> + Clone> Cursor<I> {
34    pub fn first(&self) -> Option<char> {
35        self.input.clone().next()
36    }
37}
38
39impl<I: Iterator<Item = char>> Iterator for Cursor<I> {
40    type Item = char;
41    fn next(&mut self) -> Option<char> {
42        let c = self.input.next();
43        if c.is_some() {
44            self.cur_pos += 1;
45        }
46        c
47    }
48}
49
50#[test]
51fn test_cursor() {
52    let mut c = Cursor::new("some string".chars());
53    assert_eq!(c.pos(), 0);
54    assert_eq!(c.next(), Some('s'));
55    assert_eq!(c.next(), Some('o'));
56    assert_eq!(c.next(), Some('m'));
57    assert_eq!(c.next(), Some('e'));
58    assert_eq!(c.pos(), 4);
59    assert_eq!(c.first(), Some(' '));
60    assert_eq!(c.pos(), 4);
61    assert_eq!(c.next(), Some(' '));
62    assert_eq!(c.pos(), 5);
63
64    let mut cl = c.clone();
65    assert_eq!(cl.pos(), 5);
66    assert_eq!(cl.next(), Some('s'));
67    assert_eq!(cl.next(), Some('t'));
68    assert_eq!(cl.pos(), 7);
69
70    assert_eq!(c.pos(), 5);
71    assert_eq!(c.next(), Some('s'));
72    assert_eq!(c.next(), Some('t'));
73    assert_eq!(c.next(), Some('r'));
74    assert_eq!(c.next(), Some('i'));
75    assert_eq!(c.next(), Some('n'));
76    assert_eq!(c.pos(), 10);
77    assert_eq!(c.next(), Some('g'));
78    assert_eq!(c.pos(), 11);
79    assert_eq!(c.next(), None);
80}