1use super::{Parse, ParseElem, ParseLiteral, ParseSlice, RuleResult};
4use std::fmt::Display;
5
6#[derive(PartialEq, Eq, Debug, Clone, Copy)]
8pub struct LineCol {
9 pub line: usize,
11
12 pub column: usize,
14
15 pub offset: usize,
17}
18
19impl Display for LineCol {
20 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
21 write!(fmt, "{}:{}", self.line, self.column)
22 }
23}
24
25impl Parse for str {
26 type PositionRepr = LineCol;
27 #[inline]
28 fn start(&self) -> usize {
29 0
30 }
31
32 #[inline]
33 fn is_eof(&self, pos: usize) -> bool {
34 pos >= self.len()
35 }
36
37 fn position_repr(&self, pos: usize) -> LineCol {
38 let before = &self[..pos];
39 let line = before.as_bytes().iter().filter(|&&c| c == b'\n').count() + 1;
40 let column = before.chars().rev().take_while(|&c| c != '\n').count() + 1;
41 LineCol {
42 line,
43 column,
44 offset: pos,
45 }
46 }
47}
48
49impl<'input> ParseElem<'input> for str {
50 type Element = char;
51
52 #[inline]
53 fn parse_elem(&'input self, pos: usize) -> RuleResult<char> {
54 match self[pos..].chars().next() {
55 Some(c) => RuleResult::Matched(pos + c.len_utf8(), c),
56 None => RuleResult::Failed,
57 }
58 }
59}
60
61impl ParseLiteral for str {
62 #[inline]
63 fn parse_string_literal(&self, pos: usize, literal: &str) -> RuleResult<()> {
64 let l = literal.len();
65 if self.len() >= pos + l && &self.as_bytes()[pos..pos + l] == literal.as_bytes() {
66 RuleResult::Matched(pos + l, ())
67 } else {
68 RuleResult::Failed
69 }
70 }
71}
72
73impl<'input> ParseSlice<'input> for str {
74 type Slice = &'input str;
75 #[inline]
76 fn parse_slice(&'input self, p1: usize, p2: usize) -> &'input str {
77 &self[p1..p2]
78 }
79}