noa_parser/
separated_list.rs1use crate::errors::{ParseError, ParseResult};
2use crate::scanner::Scanner;
3use crate::visitor::Visitor;
4use std::marker::PhantomData;
5
6#[derive(Debug)]
7pub struct SeparatedList<T, V, S> {
8 pub data: Vec<V>,
9 separator: PhantomData<(S, T)>,
10}
11
12enum YieldResult<V> {
13 Last(V),
14 MaybeNext(V),
15}
16
17impl<T, V, S> SeparatedList<T, V, S> {
18 pub fn into_iter(self) -> impl Iterator<Item = V> {
24 self.data.into_iter()
25 }
26}
27
28fn yield_element<'a, T, V, S>(scanner: &mut Scanner<'a, T>) -> ParseResult<YieldResult<V>>
48where
49 V: Visitor<'a, T>,
50 S: Visitor<'a, T>,
51{
52 let cursor = scanner.current_position();
53 let element = match scanner.visit::<V>() {
54 Ok(element) => element,
55 Err(err) => {
56 scanner.jump_to(cursor);
57 return Err(err);
58 }
59 };
60
61 if scanner.remaining().is_empty() {
62 return Ok(YieldResult::Last(element));
63 }
64
65 scanner.visit::<S>()?;
67
68 Ok(YieldResult::MaybeNext(element))
69}
70
71impl<'a, T, V, S> Visitor<'a, T> for SeparatedList<T, V, S>
72where
73 V: Visitor<'a, T>,
74 S: Visitor<'a, T>,
75{
76 fn accept(scanner: &mut Scanner<'a, T>) -> ParseResult<Self> {
93 let mut elements = vec![];
94 let cursor = scanner.current_position();
95
96 if scanner.remaining().is_empty() {
98 return Ok(SeparatedList {
99 data: elements,
100 separator: PhantomData,
101 });
102 }
103
104 loop {
105 if let Ok(result) = yield_element::<T, V, S>(scanner) {
106 let element: YieldResult<V> = result;
107
108 match element {
109 YieldResult::Last(element) => {
110 elements.push(element);
111 break;
112 }
113 YieldResult::MaybeNext(element) => {
114 elements.push(element);
115 }
116 }
117 } else {
118 scanner.jump_to(cursor);
119 return Err(ParseError::UnexpectedToken);
120 }
121 }
122
123 Ok(SeparatedList {
124 data: elements,
125 separator: PhantomData,
126 })
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use crate::bytes::primitives::number::Number;
133 use crate::bytes::token::Token;
134 use crate::errors::ParseResult;
135 use crate::recognizer::recognize;
136 use crate::scanner::Scanner;
137 use crate::separated_list::SeparatedList;
138 use crate::visitor::Visitor;
139
140 struct SeparatorComma;
141
142 impl<'a> Visitor<'a, u8> for SeparatorComma {
143 fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
144 recognize(Token::Comma, scanner)?;
145 Ok(SeparatorComma)
146 }
147 }
148
149 #[test]
155 fn test_parse_number_list() {
156 let data = b"12,4,78,22";
157 let mut scanner = Scanner::new(data);
158 let result = scanner
159 .visit::<SeparatedList<u8, Number<usize>, SeparatorComma>>()
160 .expect("failed to parse");
161 assert_eq!(
162 result.data,
163 vec![Number(12), Number(4), Number(78), Number(22)]
164 );
165 assert_eq!(scanner.current_position(), 10);
166
167 let data = b"";
168 let mut scanner = Scanner::new(data);
169 let result = scanner
170 .visit::<SeparatedList<u8, Number<usize>, SeparatorComma>>()
171 .expect("failed to parse");
172 assert_eq!(result.data, vec![]);
173 }
174}