120 lines
3.2 KiB
Rust
120 lines
3.2 KiB
Rust
use clap::{App, ArgMatches};
|
|
use std::fs::File;
|
|
use std::io::{BufRead, BufReader, Write};
|
|
#[macro_use]
|
|
extern crate clap;
|
|
|
|
struct Params {
|
|
delimiter: String,
|
|
source: String,
|
|
compared: String,
|
|
column: usize,
|
|
output: String,
|
|
}
|
|
|
|
impl Params {
|
|
pub fn new_from_matches(matches: ArgMatches) -> Self {
|
|
Self {
|
|
delimiter: matches.value_of("delimiter").unwrap_or(";").to_string(),
|
|
source: matches.value_of("source").unwrap().to_string(),
|
|
compared: matches.value_of("compared").unwrap().to_string(),
|
|
column: matches.value_of("column").unwrap().parse().unwrap(),
|
|
output: matches.value_of("output").unwrap().to_string(),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(crate) struct CsvLine {
|
|
line: String,
|
|
}
|
|
|
|
impl CsvLine {
|
|
pub fn new(line: String) -> Self {
|
|
Self { line }
|
|
}
|
|
}
|
|
|
|
pub(crate) fn load_vector(vector: &mut Vec<CsvLine>, reader: BufReader<File>) {
|
|
// Read the file line by line using the lines() iterator from std::io::BufRead.
|
|
for (_index, line) in reader.lines().enumerate() {
|
|
let line = line.unwrap();
|
|
vector.push(CsvLine::new(line.to_string()));
|
|
}
|
|
}
|
|
|
|
fn print_lines(vector: Vec<CsvLine>) {
|
|
for line in vector.iter() {
|
|
println!("{}", line.line);
|
|
}
|
|
}
|
|
fn main() {
|
|
let yaml = load_yaml!("cli.yml");
|
|
let matches = App::from_yaml(yaml).get_matches();
|
|
let params = Params::new_from_matches(matches);
|
|
|
|
let file = File::open(¶ms.source).unwrap();
|
|
let file2 = File::open(¶ms.compared).unwrap();
|
|
|
|
let reader = BufReader::new(file);
|
|
let reader2 = BufReader::new(file2);
|
|
|
|
let mut vec1: Vec<CsvLine> = Vec::new();
|
|
let mut vec2: Vec<CsvLine> = Vec::new();
|
|
let mut diff: Vec<CsvLine> = Vec::new();
|
|
|
|
load_vector(&mut vec1, reader);
|
|
load_vector(&mut vec2, reader2);
|
|
|
|
for i in vec1.iter() {
|
|
let splitter: Vec<&str> = i.line.split(¶ms.delimiter).collect();
|
|
let value = splitter[params.column];
|
|
|
|
let found = !matches!(
|
|
vec2.iter().position(|r| {
|
|
let splitter_b: Vec<&str> = r.line.split(¶ms.delimiter).collect();
|
|
let search = splitter_b[params.column];
|
|
search == value
|
|
}),
|
|
None
|
|
);
|
|
|
|
if !found {
|
|
diff.push(CsvLine::new(i.line.parse().unwrap()));
|
|
}
|
|
}
|
|
|
|
if params.output.is_empty() == false {
|
|
let mut file = File::create(params.output).unwrap();
|
|
for line in diff.iter() {
|
|
writeln!(&mut file, "{}", line.line).unwrap();
|
|
}
|
|
} else {
|
|
print_lines(diff);
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use std::{fs::File, io::BufReader, path::Path};
|
|
|
|
use crate::{load_vector, CsvLine};
|
|
|
|
fn get_reader() -> BufReader<File> {
|
|
let path = Path::new("./assets/csv1.csv");
|
|
assert_eq!(path.is_file(), true);
|
|
let file = File::open(path);
|
|
match file {
|
|
Ok(_) => BufReader::new(file.unwrap()),
|
|
Err(_) => panic!("error, could not read file"),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_load_vector() {
|
|
let reader = get_reader();
|
|
let mut vec1: Vec<CsvLine> = Vec::new();
|
|
load_vector(&mut vec1, reader);
|
|
assert_eq!(3, vec1.iter().count());
|
|
}
|
|
}
|