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