1use crate::compare::Compare;
2use crate::operation::Operation;
3use noa_parser::bytes::matchers::match_pattern;
4use noa_parser::bytes::primitives::whitespace::OptionalWhitespaces;
5use noa_parser::bytes::token::Token;
6use noa_parser::errors::{ParseError, ParseResult};
7use noa_parser::matcher::{Match, MatchSize};
8use noa_parser::peek::{peek, Until, UntilEnd};
9use noa_parser::recognizer::recognize;
10use noa_parser::scanner::Scanner;
11use noa_parser::separated_list::SeparatedList;
12use noa_parser::visitor::Visitor;
13
14pub mod compare;
15pub mod operation;
16
17#[derive(Debug, PartialEq)]
19pub struct TxnData<'a> {
20 pub compares: Vec<Compare<'a>>,
22 pub success: Vec<Operation<'a>>,
24 pub failure: Vec<Operation<'a>>,
26}
27
28struct LineFeed;
29
30impl<'a> Visitor<'a, u8> for LineFeed {
31 fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
32 recognize(Token::Ln, scanner)?;
33 Ok(LineFeed)
34 }
35}
36
37#[derive(Clone)]
38struct SectionEnd;
39
40impl Match<u8> for SectionEnd {
41 fn matcher(&self, data: &[u8]) -> (bool, usize) {
42 match_pattern(b"\n\n", data)
43 }
44}
45
46impl MatchSize for SectionEnd {
47 fn size(&self) -> usize {
48 2
49 }
50}
51
52impl<'a> Visitor<'a, u8> for TxnData<'a> {
53 fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
54 OptionalWhitespaces::accept(scanner)?;
55
56 let section_compare =
58 peek(Until::new(SectionEnd), scanner)?.ok_or(ParseError::UnexpectedToken)?;
59 let mut compares = vec![];
60 if !section_compare.data.is_empty() {
61 let mut section_compare_scanner = Scanner::new(section_compare.data);
62 compares =
63 SeparatedList::<u8, Compare, LineFeed>::accept(&mut section_compare_scanner)?
64 .into_iter()
65 .collect();
66 scanner.bump_by(section_compare.end_slice);
67 }
68 LineFeed::accept(scanner)?;
69 LineFeed::accept(scanner)?;
70
71 let section_success =
73 peek(Until::new(SectionEnd), scanner)?.ok_or(ParseError::UnexpectedToken)?;
74 let mut success = vec![];
75 if !section_success.data.is_empty() {
76 let mut section_success_scanner = Scanner::new(section_success.data);
77 success =
78 SeparatedList::<u8, Operation, LineFeed>::accept(&mut section_success_scanner)?
79 .into_iter()
80 .collect();
81 scanner.bump_by(section_success.end_slice);
82 }
83 LineFeed::accept(scanner)?;
84 LineFeed::accept(scanner)?;
85
86 let section_failure =
88 peek(UntilEnd::default(), scanner)?.ok_or(ParseError::UnexpectedToken)?;
89 let mut failure = vec![];
90 if !section_failure.data.is_empty() {
91 let mut section_failure_scanner = Scanner::new(section_failure.data);
92 failure =
93 SeparatedList::<u8, Operation, LineFeed>::accept(&mut section_failure_scanner)?
94 .into_iter()
95 .collect();
96 }
97
98 Ok(TxnData {
99 compares,
100 success,
101 failure,
102 })
103 }
104}