1extern crate alloc;
4
5use alloc::format;
6
7use crate::document::node::NodeTuple;
8use crate::prelude_internal::*;
9
10use super::{DocumentParser, FromEure, ParseContext, ParseError, ParseErrorKind, UnionTagMode};
11
12#[derive(Debug)]
26#[must_use]
27pub struct TupleParser<'doc> {
28 doc: &'doc EureDocument,
29 node_id: NodeId,
30 tuple: &'doc NodeTuple,
31 position: usize,
32 union_tag_mode: UnionTagMode,
33}
34
35impl<'doc> TupleParser<'doc> {
36 pub(crate) fn new(ctx: &ParseContext<'doc>) -> Result<Self, ParseError> {
38 Self::from_doc_and_node_with_mode(ctx.doc(), ctx.node_id(), ctx.union_tag_mode())
39 }
40
41 pub(crate) fn from_doc_and_node(
43 doc: &'doc EureDocument,
44 node_id: NodeId,
45 ) -> Result<Self, ParseError> {
46 Self::from_doc_and_node_with_mode(doc, node_id, UnionTagMode::default())
47 }
48
49 fn from_doc_and_node_with_mode(
50 doc: &'doc EureDocument,
51 node_id: NodeId,
52 union_tag_mode: UnionTagMode,
53 ) -> Result<Self, ParseError> {
54 let node = doc.node(node_id);
55 match &node.content {
56 NodeValue::Tuple(tuple) => Ok(Self {
57 doc,
58 node_id,
59 tuple,
60 position: 0,
61 union_tag_mode,
62 }),
63 NodeValue::Hole(_) => Err(ParseError {
64 node_id,
65 kind: ParseErrorKind::UnexpectedHole,
66 }),
67 _ => Err(ParseError {
68 node_id,
69 kind: ParseErrorKind::TypeMismatch {
70 expected: crate::value::ValueKind::Tuple,
71 actual: node.content.value_kind(),
72 },
73 }),
74 }
75 }
76
77 pub fn node_id(&self) -> NodeId {
79 self.node_id
80 }
81
82 #[allow(clippy::should_implement_trait)]
86 pub fn next<T>(&mut self) -> Result<T, T::Error>
87 where
88 T: FromEure<'doc>,
89 T::Error: From<ParseError>,
90 {
91 self.next_with(T::parse)
92 }
93
94 pub fn next_with<T>(&mut self, mut parser: T) -> Result<T::Output, T::Error>
96 where
97 T: DocumentParser<'doc>,
98 T::Error: From<ParseError>,
99 {
100 let index = self.position;
101 let element_node_id = self.tuple.get(index).ok_or_else(|| ParseError {
102 node_id: self.node_id,
103 kind: ParseErrorKind::MissingField(format!("#{}", index)),
104 })?;
105 self.position += 1;
106 let ctx = ParseContext::with_union_tag_mode(self.doc, element_node_id, self.union_tag_mode);
107 parser.parse(&ctx)
108 }
109
110 pub fn next_via<M, T>(&mut self) -> Result<T, M::Error>
112 where
113 M: FromEure<'doc, T>,
114 M::Error: From<ParseError>,
115 {
116 self.next_with(M::parse)
117 }
118
119 pub fn get<T>(&self, index: usize) -> Result<T, T::Error>
123 where
124 T: FromEure<'doc>,
125 T::Error: From<ParseError>,
126 {
127 self.get_with(index, T::parse)
128 }
129
130 pub fn get_with<T>(&self, index: usize, mut parser: T) -> Result<T::Output, T::Error>
132 where
133 T: DocumentParser<'doc>,
134 T::Error: From<ParseError>,
135 {
136 let element_node_id = self.tuple.get(index).ok_or_else(|| ParseError {
137 node_id: self.node_id,
138 kind: ParseErrorKind::MissingField(format!("#{}", index)),
139 })?;
140 let ctx = ParseContext::with_union_tag_mode(self.doc, element_node_id, self.union_tag_mode);
141 parser.parse(&ctx)
142 }
143
144 pub fn get_via<M, T>(&self, index: usize) -> Result<T, M::Error>
146 where
147 M: FromEure<'doc, T>,
148 M::Error: From<ParseError>,
149 {
150 self.get_with(index, M::parse)
151 }
152
153 pub fn remaining(&self) -> usize {
155 self.tuple.len().saturating_sub(self.position)
156 }
157
158 pub fn finish(self) -> Result<(), ParseError> {
162 if self.position != self.tuple.len() {
163 return Err(ParseError {
164 node_id: self.node_id,
165 kind: ParseErrorKind::UnexpectedTupleLength {
166 expected: self.position,
167 actual: self.tuple.len(),
168 },
169 });
170 }
171 Ok(())
172 }
173
174 pub fn expect_len(&self, expected: usize) -> Result<(), ParseError> {
178 if self.tuple.len() != expected {
179 return Err(ParseError {
180 node_id: self.node_id,
181 kind: ParseErrorKind::UnexpectedTupleLength {
182 expected,
183 actual: self.tuple.len(),
184 },
185 });
186 }
187 Ok(())
188 }
189
190 pub fn len(&self) -> usize {
192 self.tuple.len()
193 }
194
195 pub fn is_empty(&self) -> bool {
197 self.tuple.is_empty()
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204 use crate::document::constructor::DocumentConstructor;
205 use crate::path::PathSegment;
206 use crate::value::PrimitiveValue;
207
208 fn create_tuple_doc(elements: Vec<PrimitiveValue>) -> EureDocument {
209 let mut c = DocumentConstructor::new();
210 c.bind_empty_tuple().unwrap();
211 for (i, elem) in elements.into_iter().enumerate() {
212 let scope = c.begin_scope();
213 c.navigate(PathSegment::TupleIndex(i as u8)).unwrap();
214 c.bind_primitive(elem).unwrap();
215 c.end_scope(scope).unwrap();
216 }
217 c.finish()
218 }
219
220 #[test]
221 fn test_next_sequential() {
222 let doc = create_tuple_doc(vec![
223 PrimitiveValue::Integer(1.into()),
224 PrimitiveValue::Integer(2.into()),
225 PrimitiveValue::Integer(3.into()),
226 ]);
227
228 let mut tuple = doc.parse_tuple(doc.get_root_id()).unwrap();
229 assert_eq!(tuple.next::<i32>().unwrap(), 1);
230 assert_eq!(tuple.next::<i32>().unwrap(), 2);
231 assert_eq!(tuple.next::<i32>().unwrap(), 3);
232 tuple.finish().unwrap();
233 }
234
235 #[test]
236 fn test_next_past_end() {
237 let doc = create_tuple_doc(vec![PrimitiveValue::Integer(1.into())]);
238
239 let mut tuple = doc.parse_tuple(doc.get_root_id()).unwrap();
240 tuple.next::<i32>().unwrap();
241 let result = tuple.next::<i32>();
242 assert!(matches!(
243 result.unwrap_err().kind,
244 ParseErrorKind::MissingField(_)
245 ));
246 }
247
248 #[test]
249 fn test_get_random_access() {
250 let doc = create_tuple_doc(vec![
251 PrimitiveValue::Integer(10.into()),
252 PrimitiveValue::Integer(20.into()),
253 PrimitiveValue::Integer(30.into()),
254 ]);
255
256 let tuple = doc.parse_tuple(doc.get_root_id()).unwrap();
257 assert_eq!(tuple.get::<i32>(2).unwrap(), 30);
258 assert_eq!(tuple.get::<i32>(0).unwrap(), 10);
259 assert_eq!(tuple.get::<i32>(1).unwrap(), 20);
260 }
261
262 #[test]
263 fn test_get_out_of_bounds() {
264 let doc = create_tuple_doc(vec![PrimitiveValue::Integer(1.into())]);
265
266 let tuple = doc.parse_tuple(doc.get_root_id()).unwrap();
267 let result = tuple.get::<i32>(5);
268 assert!(matches!(
269 result.unwrap_err().kind,
270 ParseErrorKind::MissingField(_)
271 ));
272 }
273
274 #[test]
275 fn test_remaining() {
276 let doc = create_tuple_doc(vec![
277 PrimitiveValue::Integer(1.into()),
278 PrimitiveValue::Integer(2.into()),
279 PrimitiveValue::Integer(3.into()),
280 ]);
281
282 let mut tuple = doc.parse_tuple(doc.get_root_id()).unwrap();
283 assert_eq!(tuple.remaining(), 3);
284 tuple.next::<i32>().unwrap();
285 assert_eq!(tuple.remaining(), 2);
286 tuple.next::<i32>().unwrap();
287 assert_eq!(tuple.remaining(), 1);
288 tuple.next::<i32>().unwrap();
289 assert_eq!(tuple.remaining(), 0);
290 }
291
292 #[test]
293 fn test_finish_with_remaining_elements() {
294 let doc = create_tuple_doc(vec![
295 PrimitiveValue::Integer(1.into()),
296 PrimitiveValue::Integer(2.into()),
297 ]);
298
299 let mut tuple = doc.parse_tuple(doc.get_root_id()).unwrap();
300 tuple.next::<i32>().unwrap();
301 let result = tuple.finish();
303 assert!(matches!(
304 result.unwrap_err().kind,
305 ParseErrorKind::UnexpectedTupleLength {
306 expected: 1,
307 actual: 2
308 }
309 ));
310 }
311
312 #[test]
313 fn test_expect_len_correct() {
314 let doc = create_tuple_doc(vec![
315 PrimitiveValue::Integer(1.into()),
316 PrimitiveValue::Integer(2.into()),
317 ]);
318
319 let tuple = doc.parse_tuple(doc.get_root_id()).unwrap();
320 tuple.expect_len(2).unwrap();
321 }
322
323 #[test]
324 fn test_expect_len_incorrect() {
325 let doc = create_tuple_doc(vec![PrimitiveValue::Integer(1.into())]);
326
327 let tuple = doc.parse_tuple(doc.get_root_id()).unwrap();
328 let result = tuple.expect_len(3);
329 assert!(matches!(
330 result.unwrap_err().kind,
331 ParseErrorKind::UnexpectedTupleLength {
332 expected: 3,
333 actual: 1
334 }
335 ));
336 }
337
338 #[test]
339 fn test_empty_tuple() {
340 let doc = create_tuple_doc(vec![]);
341
342 let tuple = doc.parse_tuple(doc.get_root_id()).unwrap();
343 assert!(tuple.is_empty());
344 assert_eq!(tuple.len(), 0);
345 assert_eq!(tuple.remaining(), 0);
346 tuple.finish().unwrap();
347 }
348
349 #[test]
350 fn test_len_and_is_empty() {
351 let doc = create_tuple_doc(vec![
352 PrimitiveValue::Integer(1.into()),
353 PrimitiveValue::Integer(2.into()),
354 ]);
355
356 let tuple = doc.parse_tuple(doc.get_root_id()).unwrap();
357 assert!(!tuple.is_empty());
358 assert_eq!(tuple.len(), 2);
359 }
360
361 #[test]
362 fn test_parse_non_tuple_fails() {
363 let mut c = DocumentConstructor::new();
364 c.bind_empty_array().unwrap();
365 let doc = c.finish();
366
367 let result = doc.parse_tuple(doc.get_root_id());
368 assert!(matches!(
369 result.unwrap_err().kind,
370 ParseErrorKind::TypeMismatch { .. }
371 ));
372 }
373}