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