fuchsia_triage/metrics/
context.rs
1use nom::error::{ErrorKind, ParseError};
6use nom::{AsBytes, Compare, CompareResult, Err, IResult, Input, Needed, Offset, ParseTo};
7use std::num::NonZero;
8use std::str::{CharIndices, Chars};
9
10#[derive(Debug, Clone, Copy, PartialEq)]
12pub struct ParsingContext<'a> {
13 input: &'a str,
15 namespace: &'a str,
17}
18
19impl<'a> ParsingContext<'a> {
20 pub fn new(input: &'a str, namespace: &'a str) -> Self {
21 Self { input, namespace }
22 }
23 pub fn into_inner(self) -> &'a str {
24 self.input
25 }
26}
27
28impl AsBytes for ParsingContext<'_> {
29 fn as_bytes(&self) -> &[u8] {
30 self.input.as_bytes()
31 }
32}
33
34impl<'a, T> Compare<T> for ParsingContext<'a>
35where
36 &'a str: Compare<T>,
37{
38 fn compare(&self, t: T) -> CompareResult {
39 self.input.compare(t)
40 }
41 fn compare_no_case(&self, t: T) -> CompareResult {
42 self.input.compare_no_case(t)
43 }
44}
45
46impl<'a> Input for ParsingContext<'a> {
47 type Item = char;
48 type IterIndices = CharIndices<'a>;
49 type Iter = Chars<'a>;
50
51 fn iter_indices(&self) -> Self::IterIndices {
52 self.input.char_indices()
53 }
54
55 fn iter_elements(&self) -> Self::Iter {
56 self.input.chars()
57 }
58
59 fn position<P>(&self, predicate: P) -> Option<usize>
60 where
61 P: Fn(Self::Item) -> bool,
62 {
63 self.input.position(predicate)
64 }
65
66 fn slice_index(&self, count: usize) -> Result<usize, Needed> {
67 self.input.slice_index(count)
68 }
69
70 fn input_len(&self) -> usize {
71 self.input.len()
72 }
73
74 fn take(&self, count: usize) -> Self {
75 Self::new(&self.input[..count], self.namespace)
76 }
77
78 fn take_from(&self, index: usize) -> Self {
79 Self::new(&self.input[index..], self.namespace)
80 }
81
82 fn take_split(&self, count: usize) -> (Self, Self) {
83 let (s0, s1) = self.input.split_at(count);
84 (ParsingContext::new(s1, self.namespace), ParsingContext::new(s0, self.namespace))
85 }
86
87 fn split_at_position<P, E: ParseError<Self>>(&self, predicate: P) -> IResult<Self, Self, E>
88 where
89 P: Fn(Self::Item) -> bool,
90 {
91 self.input
92 .position(predicate)
93 .map(|idx| Self::take_split(self, idx))
94 .ok_or(Err::Incomplete(Needed::Size(NonZero::new(1).unwrap())))
95 }
96
97 fn split_at_position1<P, E: ParseError<Self>>(
98 &self,
99 predicate: P,
100 e: ErrorKind,
101 ) -> IResult<Self, Self, E>
102 where
103 P: Fn(Self::Item) -> bool,
104 {
105 match self.input.position(predicate) {
106 Some(0) => Err(Err::Error(E::from_error_kind(*self, e))),
107 Some(idx) => Ok(Self::take_split(self, idx)),
108 None => Err(Err::Incomplete(Needed::Size(NonZero::new(1).unwrap()))),
109 }
110 }
111
112 fn split_at_position_complete<P, E: ParseError<Self>>(
113 &self,
114 predicate: P,
115 ) -> IResult<Self, Self, E>
116 where
117 P: Fn(Self::Item) -> bool,
118 {
119 match self.split_at_position(predicate) {
120 Err(Err::Incomplete(_)) => Ok(Self::take_split(self, self.input.input_len())),
121 elt => elt,
122 }
123 }
124 fn split_at_position1_complete<P, E: ParseError<Self>>(
125 &self,
126 predicate: P,
127 e: ErrorKind,
128 ) -> IResult<Self, Self, E>
129 where
130 P: Fn(Self::Item) -> bool,
131 {
132 match self.input.position(predicate) {
133 Some(0) => Err(Err::Error(E::from_error_kind(*self, e))),
134 Some(idx) => Ok(Self::take_split(self, idx)),
135 None => Ok(Self::take_split(self, self.input.input_len())),
136 }
137 }
138}
139
140impl Offset for ParsingContext<'_> {
141 fn offset(&self, second: &Self) -> usize {
142 self.input.offset(second.input)
143 }
144}
145
146impl<'a, R> ParseTo<R> for ParsingContext<'a>
147where
148 &'a str: ParseTo<R>,
149{
150 fn parse_to(&self) -> Option<R> {
151 self.input.parse_to()
152 }
153}