x12_stream_parser/
parser.rs

1use crate::errors::ParserError;
2use crate::segment::SegmentSlice;
3use x12_delimiters::Delimiters;
4
5#[derive(Clone)]
6pub struct Parser<'a> {
7    remaining_input: &'a [u8],
8    delimiters: Delimiters,
9    finished: bool, // Track if iteration is truly finished vs. just hit end of buffer temporarily
10}
11
12impl<'a> Parser<'a> {
13    pub fn new(input: &'a [u8], delimiters: Delimiters) -> Self {
14        Parser {
15            remaining_input: input,
16            delimiters,
17            finished: false,
18        }
19    }
20}
21
22impl<'a> Iterator for Parser<'a> {
23    type Item = Result<SegmentSlice<'a>, ParserError>;
24
25    fn next(&mut self) -> Option<Self::Item> {
26         if self.finished {
27             return None;
28         }
29
30        let terminator = self.delimiters.segment_terminator();
31
32        match self
33            .remaining_input
34            .iter()
35            .position(|&b| b == terminator)
36        {
37            Some(term_pos) => {
38                let segment_data = &self.remaining_input[..term_pos];
39                // Advance past segment including terminator for next iteration
40                self.remaining_input = &self.remaining_input[term_pos + 1..];
41
42                if segment_data.is_empty() {
43                     // Skip empty segments often caused by trailing terminators? Or return error?
44                     // Let's skip them. User might have input like "ISA*...~GS*...~~ST*..."
45                     // Recurse to find the next valid segment.
46                     // Avoid recursion depth issues: loop instead.
47                     // Actually, let's just return None if the segment_data is empty after a split.
48                     // This means consecutive terminators end the iteration.
49                     if self.remaining_input.is_empty() {
50                         self.finished = true;
51                     }
52                     return self.next(); // Try again with advanced input
53                }
54
55                match SegmentSlice::new(
56                    segment_data,
57                    self.delimiters.element_separator(),
58                    self.delimiters.sub_element_separator(),
59                ) {
60                    Some(segment_slice) => {
61                         if self.remaining_input.is_empty() {
62                            self.finished = true; // Mark finished if we consumed the rest
63                        }
64                        Some(Ok(segment_slice))
65                    },
66                    None => {
67                        // SegmentSlice::new returns None if segment_data is empty or ID is empty.
68                        // We already checked for empty segment_data. So this means empty ID.
69                        self.finished = true; // Stop iteration on error
70                        Some(Err(ParserError::SegmentIdNotFound))
71                    }
72                }
73            }
74            None => {
75                self.finished = true; // Mark as finished
76                // If there's remaining data, it's an error (unterminated)
77                if self.remaining_input.is_empty() {
78                    None // Normal end of iteration
79                } else {
80                    Some(Err(ParserError::UnterminatedSegment))
81                }
82            }
83        }
84    }
85}