rtools_traits/
lib.rs

1//! `rtools-traits` library provides common traits for tools
2//! that reimplement GNU tools.
3//!
4
5use 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    /// Generic line processor that delegates to concrete line processors
16    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    /// Process readable object: Send input to the line processor
31    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    /// Process files: Send them to the line processor
42    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        // TODO: What can we do about encodings? ASCII vs UTF-8 vs X
50        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    /// Read lines from the input files or STDIN and send them to the processor. Results go to defined output
66    fn process<W: std::io::Write>(&self, line_processor: &P, files: &Vec<&str>, writable: &mut W, context: &C) {
67        // TODO: What can we do about encodings? ASCII vs UTF-8 vs X
68        // TODO: Add a method to take BufWriter<W> instead of assuming STDOUT
69        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    /// Read lines from the input files or STDIN and write results to STDOUT
82    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}