1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
mod utils;
pub(crate) mod core;
mod accounts;
mod engine;
mod ledger;
use crate::core::{Accounts, Ledger, PaymentEngine, Tx};
use clap::{self, Arg, ArgMatches};
use csv::{Reader, ReaderBuilder, Trim};
use std::error::Error;
use std::fs::File;
fn main() -> Result<(), Box<dyn Error>> {
let csv_path = input();
let mut engine = PaymentEngine::default();
let mut ledger = Ledger::default();
let mut accounts = Accounts::default();
let mut transactions = get_transactions(csv_path.value_of("csv-path"))?;
for tx in transactions.deserialize() {
let tx: Tx<ledger::transaction::Default> = tx?;
engine
.process_transaction(tx, &mut ledger, &mut accounts)
.map_err(|e| eprintln!("{} (tx = {})", e.to_string(), &tx))
.ok();
}
let csv_report = accounts.report_accounts_balances()?;
output(&csv_report);
Ok(())
}
fn input() -> ArgMatches {
clap::Command::new("interviewpuzzle")
.arg_required_else_help(true)
.arg(
Arg::new("csv-path")
.help("Path to csv file.")
.takes_value(true),
)
.get_matches()
}
fn get_transactions(csv_path: Option<&str>) -> csv::Result<Reader<File>> {
let transactions = ReaderBuilder::new()
.trim(Trim::All)
.from_path(csv_path.unwrap())?;
Ok(transactions)
}
fn output(csv: &str) {
print!("{}", csv);
}