diff --git a/project/src/action.rs b/project/src/action.rs new file mode 100644 index 0000000..d42b643 --- /dev/null +++ b/project/src/action.rs @@ -0,0 +1,10 @@ +// Libraries + +// Structures +pub struct Transaction { + description: String, + date: String, + amount: f64, +} + +// Implementations diff --git a/project/src/args.rs b/project/src/args.rs new file mode 100644 index 0000000..49e4f0c --- /dev/null +++ b/project/src/args.rs @@ -0,0 +1,50 @@ +// Libraries +use clap::{Arg, ArgAction, Command}; + +// Structures +pub struct Arguments { + pub file_input: String, + pub file_output: String, +} + +// Implementations +impl Arguments { + // Constructors + pub fn new() -> Self { + // Creating an Application + let matches = Command::new("statement-converter") + .about("A service that converts Bank Statement PDF files into CSV files") + .version("1.0.0") + .arg_required_else_help(true) + /* + PDF Path + */ + .arg( + Arg::new("file_in") + .short('i') + .long("file_in") + .help("The PDF you want to convert") + .action(ArgAction::Set) + .required(true), + ) + .arg( + Arg::new("file_out") + .short('o') + .long("file_out") + .help("The CSV Path you want to save to") + .action(ArgAction::Set) + .required(true), + ) + .get_matches(); + + // Getting the required arguments + let file_input = matches.get_one::("file_in").unwrap().to_string(); + let file_output = matches.get_one::("file_out").unwrap().to_string(); + + // Returning a Result + Self { + file_input, + file_output, + } + } +} diff --git a/project/src/parser.rs b/project/src/parser.rs new file mode 100644 index 0000000..057612a --- /dev/null +++ b/project/src/parser.rs @@ -0,0 +1,95 @@ +// Libraries +use super::action::Transaction; + +// Enums +enum ParserModes { + None, + Debit, + Credit, +} + +// Structures +pub struct Parser { + pub transactions: Vec, + mode: ParserModes, + paused: bool, + + content: String, +} + +// Implementations +impl Parser { + // Constructors + pub fn new(content: String) -> Self { + // Return Result + Self { + transactions: Vec::new(), + mode: ParserModes::None, + paused: false, + + content, + } + } + + // Functions + fn none(&mut self, line: &str) { + // Checking if the line is the beginning of a table + if line == "Other withdrawals, debits and service charges" { + self.mode = ParserModes::Debit; + } else if line == "Deposits, credits and interest" { + self.mode = ParserModes::Credit; + } + } + fn debit(&mut self, line: &str) { + // Should be pause? + if line.contains("continued") { + self.paused = true; + return; + } + + // Checking if it starts with a number + if !line.chars().next().map_or(false, |c| c.is_ascii_digit()) { + return; + } + + // Print the line + println!("Debit: {}", line); + } + fn credit(&mut self, line: &str) {} + + fn pause_check(&mut self, line: &str) { + // Check to see if the line contains "continued" + if !line.contains("continued") { + return; + } + + // We're good to continue now + self.paused = false; + } + + pub fn start(&mut self) { + // Referencing Content + let content = self.content.clone(); + + // Scanning Line-by-Line through Content + for line in content.split('\n') { + // Empty line? + if line.is_empty() { + continue; + } + + // Are we paused? + if self.paused { + self.pause_check(line); + continue; + } + + // Switching based on Mode + match self.mode { + ParserModes::None => self.none(line), + ParserModes::Debit => self.debit(line), + ParserModes::Credit => self.credit(line), + } + } + } +} diff --git a/project/src/reader.rs b/project/src/reader.rs new file mode 100644 index 0000000..0f5655d --- /dev/null +++ b/project/src/reader.rs @@ -0,0 +1,31 @@ +// Libraries +use std::fs::read; +use std::io::Result; + +use pdf_extract; + +// Structures +pub struct Reader { + bytes: Vec, +} + +// Implementations +impl Reader { + // Constructors + pub fn new(path: &String) -> Result { + // Reading the file from the path + let bytes = read(path)?; + + // Returning the Result + Ok(Self { bytes }) + } + + // Functions + pub fn extract(&self) -> String { + // Getting the text from our PDF Bytes + let text = pdf_extract::extract_text_from_mem(&self.bytes).unwrap(); + + // It's Ok! + text + } +}