rsv_lib/io/
search.rs

1use crate::args::Search;
2use crate::utils::column::Columns;
3use crate::utils::filename::new_file;
4use crate::utils::regex::Re;
5use crate::utils::{cli_result::CliResult, writer::Writer};
6use std::io::{self, BufRead};
7
8impl Search {
9    pub fn io_run(&self) -> CliResult {
10        // wtr and rdr
11        let out = new_file("searched.csv");
12        let mut wtr = Writer::file_or_stdout(self.export, &out)?;
13        let mut cols = Columns::new(&self.cols);
14        let mut filter = Columns::new(&self.filter);
15
16        // read
17        let mut rdr = io::stdin().lock().lines();
18
19        // header
20        if !self.no_header {
21            let Some(r) = rdr.next() else { return Ok(()) };
22            let r = r?;
23
24            let mut fields = self.split_row_to_vec(&r);
25            cols = cols.total_col(fields.len()).parse();
26            filter = filter.total_col(fields.len()).parse();
27
28            if cols.select_all {
29                wtr.write_str_unchecked(&r)
30            } else {
31                fields = cols.iter().map(|&i| fields[i]).collect();
32                wtr.write_fields_unchecked(&fields);
33            }
34        }
35
36        // regex
37        let re = Re::new(&self.pattern)?;
38        let mut matched = 0;
39        for r in rdr {
40            let r = r?;
41
42            if !cols.parsed {
43                let n = self.row_field_count(&r);
44                cols = cols.total_col(n).parse();
45            }
46            if !filter.parsed {
47                let n = self.row_field_count(&r);
48                filter = filter.total_col(n).parse();
49            }
50
51            match (cols.select_all, filter.select_all) {
52                (true, true) => {
53                    if re.is_match(&r) {
54                        matched += 1;
55                        wtr.write_str(&r)?;
56                    }
57                }
58                (true, false) => {
59                    let f = self.split_row_to_vec(&r);
60                    if filter.iter().any(|&i| re.is_match(f[i])) {
61                        wtr.write_str(&r)?;
62                    }
63                }
64                (false, true) => {
65                    if re.is_match(&r) {
66                        let r = self.split_row_to_vec(&r);
67                        let r = cols.iter().map(|&i| r[i]).collect::<Vec<_>>();
68                        wtr.write_fields_unchecked(&r)
69                    }
70                }
71                (false, false) => {
72                    let r = self.split_row_to_vec(&r);
73                    if filter.iter().any(|&i| re.is_match(r[i])) {
74                        let r = cols.iter().map(|&i| r[i]).collect::<Vec<_>>();
75                        wtr.write_fields_unchecked(&r)
76                    }
77                }
78            }
79        }
80
81        if self.export {
82            println!("Matched rows: {matched}");
83            println!("Saved to file: {}", out.display())
84        }
85
86        Ok(())
87    }
88}