1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
use crate::line_parser::{LineParser, LineParserError};
use crate::line_visitor::LineVisitor;
use crate::models::Line;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;
#[derive(Debug)]
pub enum LineProcessorError<E> {
ParseError {
line_no: usize,
error: LineParserError,
},
VisitorError {
line_no: usize,
error: E,
},
IoError(std::io::Error),
}
pub struct LineProcessor;
impl LineProcessor {
pub fn run_file<P, V>(
&self,
path: &Path,
line_visitor: &mut V,
) -> Result<usize, LineProcessorError<V::Error>>
where
P: LineParser,
V: LineVisitor,
{
match File::open(path) {
Ok(file) => {
let mut buf_reader = BufReader::new(file);
self.run::<P, _, _>(&mut buf_reader, line_visitor)
}
Err(err) => Err(LineProcessorError::IoError(err)),
}
}
pub fn run<P, R, V>(
&self,
mut rd: R,
line_visitor: &mut V,
) -> Result<usize, LineProcessorError<V::Error>>
where
P: LineParser,
R: BufRead,
V: LineVisitor,
{
let mut line_no = 0;
let mut line_buffer = String::new();
loop {
line_buffer.clear();
match rd.read_line(&mut line_buffer) {
Ok(0) => {
let _ = line_visitor
.visit_end_of_file()
.map_err(|error| LineProcessorError::VisitorError { line_no, error })?;
return Ok(line_no);
}
Ok(_) => match P::parse_line(&line_buffer) {
Ok(line) => match line {
Line::Posting(posting) => {
let _ = line_visitor.visit_posting(posting).map_err(|error| {
LineProcessorError::VisitorError { line_no, error }
})?;
}
Line::Empty => {}
Line::TransactionHeader(txn_header) => {
let _ = line_visitor.visit_transaction_header(txn_header).map_err(
|error| LineProcessorError::VisitorError { line_no, error },
)?;
}
Line::TransactionComment(txn_comment) => {
let _ = line_visitor
.visit_transaction_comment(txn_comment)
.map_err(|error| LineProcessorError::VisitorError {
line_no,
error,
})?;
}
},
Err(error) => {
return Err(LineProcessorError::ParseError { line_no, error });
}
},
Err(io_err) => {
return Err(LineProcessorError::IoError(io_err));
}
}
line_no += 1;
}
}
}