1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use std::ops::{Index, RangeFrom};


/// Container for input into parsers
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct ParserContext<T> {
    // The full input to parse
    input: T,
    // The input length 
    length: usize,
    // Our current position with the input 
    position: usize,
}

impl<'i> From<&'i str> for ParserContext<&'i str> {
    fn from(value: &'i str) -> Self {
        ParserContext {
            input: value,
            length: value.len(),
            position: 0,
        }
    }
}

impl<'i, T> From<&'i [T]> for ParserContext<&'i [T]> {
    fn from(value: &'i [T]) -> Self {
        ParserContext {
            input: value,
            length: value.len(),
            position: 0,
        }
    }
}

// Note: You might be tempted to think the `Deref` trait would be cleaner to use here. However, the
// reference obtained through the `Deref` trait has the lifetime of the container. Parsers always
// accept an owned `ParserContext`, so returning a reference to it is not a allowed. We instead want
// to tell the compiler that we are returning a reference to the inner value
impl<'a, T: ?Sized> ParserContext<&'a T>
where
    T: Index<RangeFrom<usize>>,
{
    /// Returns the input being parsed. The first parser will see the entire input. Subsequent
    /// parsers will only see whatever is left to parse 
    pub fn input(&self) -> &'a <T as Index<RangeFrom<usize>>>::Output {
        // This is where the magic of the `ParseContext` struct comes from. It holds the entire parse
        // input, but to individual parsers, will only appear to hold the part of the input they
        // care about.
        &self.input[self.position..] 
    }
}



impl<T> ParserContext<T>
where
    T: Clone,
{
    /// Increments the input position by `count`. If there is less than `count` elements left in
    /// the input, the position will be set to the length of the input.
    ///
    /// Advancing the position affects what subsequent calls to `.input()` return
    pub fn advance_by(&mut self, count: usize) {
        let offset = if self.position + count <= self.length {
            count
        } else {
            self.length - self.position
        };

        self.position += offset;
    }
}

impl<T> ParserContext<T> {
    /// Returns `true` if this instance's position is at the end of the input
    pub fn end_of_input(&self) -> bool {
        self.position == self.length 
    }

    /// Returns the current input position
    pub fn get_position(&self) -> usize {
        self.position
    }
}


#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn test_equality() {
        let str = "A";
        let ctx = ParserContext::from(str);
        assert_eq!(ctx.input(), str);
        assert_eq!(ctx.input(), "A");

        let slice = &[0, 2, 4][..];
        let ctx = ParserContext::from(slice);
        assert_eq!(ctx.input(), slice);
        assert_eq!(ctx.input(), &[0, 2, 4]);
    }

    #[test]
    fn test_deref_magic() {
        let str = "ABC";

        let mut ctx = ParserContext::from(str);

        assert_eq!(ctx.input(), "ABC");

        ctx.advance_by(1);
        assert_eq!(ctx.input(), "BC");
        assert_eq!(&ctx.input()[0..], "BC");

        ctx.advance_by(1);
        assert_eq!(ctx.input(), "C");
        assert_eq!(&ctx.input()[0..], "C");

        ctx.advance_by(1);
        assert_eq!(ctx.input(), "");
        assert_eq!(&ctx.input()[0..], "");

        ctx.advance_by(1);
        ctx.advance_by(10);
        ctx.advance_by(3);

        assert_eq!(ctx.input(), "");
        assert_eq!(&ctx.input()[0..], "");
    }
}