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}