1use std::fs::File;
6use std::io::prelude::*;
7use std::io::{BufReader, BufWriter};
8use std::str;
9
10pub trait LineProcessorT<C> {
11 fn process(&self, line: &str, context: &C) -> Vec<u8>;
12}
13
14pub trait RtoolT<C, P: LineProcessorT<C>> {
15 fn process_lines<R: Read, W: Write>(
17 &self,
18 line_processor: &P,
19 input: BufReader<R>,
20 output: &mut BufWriter<W>,
21 context: &C,
22 ) {
23 for line in input.lines() {
24 let out_bytes = line_processor.process(&line.unwrap(), context);
25
26 output.write(&out_bytes).unwrap();
27 }
28 }
29
30 fn process_readable<R: std::io::Read, W: std::io::Write>(
32 &self,
33 line_processor: &P,
34 input: BufReader<R>,
35 output: &mut BufWriter<W>,
36 context: &C,
37 ) {
38 self.process_lines(line_processor, input, output, &context);
39 }
40
41 fn process_files<W: std::io::Write>(
43 &self,
44 line_processor: &P,
45 files: &Vec<&str>,
46 writable: W,
47 context: &C,
48 ) {
49 let mut output = BufWriter::new(writable);
51
52 for file in files {
53 match File::open(file) {
54 Ok(file) => {
55 let input = BufReader::new(file);
56 self.process_readable(line_processor, input, &mut output, context);
57 }
58 Err(err) => {
59 eprintln!("Could not read the file `{}`. The error: {:?}", file, err);
60 }
61 }
62 }
63 }
64
65 fn process<W: std::io::Write>(&self, line_processor: &P, files: &Vec<&str>, writable: &mut W, context: &C) {
67 if files.is_empty() {
70 self.process_readable(
71 line_processor,
72 BufReader::new(std::io::stdin()),
73 &mut BufWriter::new(writable),
74 context,
75 );
76 } else {
77 self.process_files(line_processor, &files, writable, context);
78 }
79 }
80
81 fn process_to_stdout(&self, line_processor: &P, files: &Vec<&str>, context: &C) {
83 self.process(line_processor, files, &mut BufWriter::new(std::io::stdout()), context);
84 }
85}