Skip to main content

quoth/parsable/
exact.rs

1use super::*;
2
3use crate as quoth;
4
5#[derive(Clone, Debug, Hash, PartialEq, Eq, ParsableExt, Spanned)]
6pub struct Exact(pub Span);
7
8impl Exact {
9    pub fn new(span: impl Into<Span>) -> Self {
10        Exact(span.into())
11    }
12
13    pub fn from(source: impl Into<Source>) -> Self {
14        let source = Rc::new(source.into());
15        let len = source.len();
16        Exact(Span::new(source, 0..len))
17    }
18}
19
20impl Parsable for Exact {
21    fn parse(stream: &mut ParseStream) -> Result<Self> {
22        Ok(Exact(Span::new(
23            stream.source().clone(),
24            stream.position..stream.position,
25        )))
26    }
27
28    fn parse_value(value: Self, stream: &mut ParseStream) -> Result<Self> {
29        let s = value.0;
30        let text = s.source_text();
31        if stream.remaining().starts_with(&text) {
32            let start_position = stream.position;
33            stream.position += text.len();
34            return Ok(Exact(Span::new(
35                stream.source().clone(),
36                start_position..stream.position,
37            )));
38        }
39        let prefix = common_prefix(&text, stream.remaining());
40        stream.consume(prefix.len())?;
41        let missing_span = stream.current_span();
42        let missing = text.slice(prefix.len()..);
43        Err(Error::expected(missing_span, missing))
44    }
45}
46
47#[test]
48fn test_parse_exact() {
49    let mut stream = ParseStream::from("hey this is a cool string");
50    assert_eq!(stream.parse::<Exact>().unwrap().0.source_text(), "");
51    assert_eq!(
52        stream
53            .parse_value(Exact::from("hey this"))
54            .unwrap()
55            .span()
56            .source_text(),
57        "hey this"
58    );
59    assert_eq!(stream.position, 8);
60    assert!(
61        stream
62            .parse_value(Exact::from(" is not cool"))
63            .unwrap_err()
64            .to_string()
65            .contains("expected `not cool`")
66    );
67    let mut stream = ParseStream::from("");
68    let parsed = stream.parse_value(Exact::from("hey")).unwrap_err();
69    assert!(parsed.to_string().contains("expected `hey`"));
70    let mut stream = ParseStream::from("3.14");
71    stream.consume(1).unwrap();
72    let ex = stream.parse_value(Exact::from(".")).unwrap();
73    assert_eq!(ex.to_string(), ".");
74}