almost done

This commit is contained in:
JasterV 2021-07-29 00:00:53 +02:00
parent c047130d2e
commit d08286beb6
10 changed files with 161 additions and 23 deletions

22
Cargo.lock generated
View file

@ -417,6 +417,26 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "thiserror"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tokio"
version = "1.9.0"
@ -466,7 +486,9 @@ dependencies = [
"anyhow",
"csv-async",
"serde",
"thiserror",
"tokio",
"tokio-stream",
]
[[package]]

View file

@ -7,6 +7,8 @@ edition = "2018"
[dependencies]
tokio = { version = "1", features = ["full"] }
tokio-stream = "0.1.7"
serde = { version = "1.0", features = ["derive"] }
csv-async = { version = "1.2.1", features = ["with_serde", "tokio"]}
thiserror = "1.0.26"
anyhow = "1.0.40"

13
src/errors.rs Normal file
View file

@ -0,0 +1,13 @@
use thiserror::Error;
#[derive(Error, Debug)]
pub enum TransactionError {
#[error("Not enough funds to withdraw")]
WithdrawError,
#[error("Not enough available funds to held")]
HeldError,
#[error("Not enough held funds to free")]
UnheldError,
#[error("Account `{0}` is locked")]
AccountLocked(u16),
}

View file

@ -1,12 +1,25 @@
mod errors;
mod models;
mod services;
use std::env;
use anyhow::Result;
use models::{account::Account, transaction::Transaction};
use std::{collections::HashMap, env};
use tokio::fs::File;
use tokio_stream::StreamExt;
type TransactionsMap = HashMap<u32, Transaction>;
type AccountsMap = HashMap<u16, Account>;
#[tokio::main]
async fn main() -> Result<()> {
let file_path = env::args().nth(1).expect("CSV path required");
println!("Hello, World");
let mut rdr = csv_async::AsyncDeserializer::from_reader(File::open(file_path).await?);
let mut records = rdr.deserialize::<Transaction>();
while let Some(record) = records.next().await {
let transaction = record?;
println!("{:#?}", transaction);
}
Ok(())
}

81
src/models/account.rs Normal file
View file

@ -0,0 +1,81 @@
use anyhow::Result;
use serde::Serialize;
use crate::errors::TransactionError;
#[derive(Serialize, Debug)]
pub struct Account {
client: u16,
available: f32,
held: f32,
total: f32,
locked: bool,
}
impl Account {
pub fn new(client: u16) -> Self {
Self {
client,
available: 0.0,
held: 0.0,
total: 0.0,
locked: false,
}
}
pub fn deposit(&mut self, amount: f32) -> Result<()> {
self.assert_lock()?;
self.available += amount;
self.total += amount;
Ok(())
}
pub fn withdraw(&mut self, amount: f32) -> Result<()> {
self.assert_lock()?;
if amount > self.available {
Err(TransactionError::WithdrawError)?;
}
self.available -= amount;
self.total -= amount;
Ok(())
}
pub fn held(&mut self, amount: f32) -> Result<()> {
self.assert_lock()?;
if amount > self.available {
Err(TransactionError::HeldError)?;
}
self.available -= amount;
self.held += amount;
Ok(())
}
pub fn free(&mut self, amount: f32) -> Result<()> {
self.assert_lock()?;
if amount > self.held {
Err(TransactionError::UnheldError)?;
}
self.held -= amount;
self.available += amount;
Ok(())
}
pub fn chargeback(&mut self, amount: f32) -> Result<()> {
self.assert_lock()?;
if amount > self.held {
Err(TransactionError::UnheldError)?;
}
self.held -= amount;
self.total -= amount;
self.locked = true;
Ok(())
}
fn assert_lock(&self) -> Result<()> {
if self.locked {
Err(TransactionError::AccountLocked(self.client))?
} else {
Ok(())
}
}
}

View file

@ -1,18 +1,2 @@
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Debug)]
pub struct Transaction {
pub ty: String,
pub client: u16,
pub tx: u32,
pub amount: f32,
}
#[derive(Serialize, Debug)]
pub struct TransactionResult {
pub client: u16,
pub available: f32,
pub held: f32,
pub total: f32,
pub locked: bool,
}
pub mod account;
pub mod transaction;

25
src/models/transaction.rs Normal file
View file

@ -0,0 +1,25 @@
use serde::Deserialize;
#[derive(Deserialize, Debug)]
pub enum TransactionType {
#[serde(alias = "deposit")]
Deposit,
#[serde(alias = "withdrawal")]
Withdrawal,
#[serde(alias = "dispute")]
Dispute,
#[serde(alias = "resolve")]
Resolve,
#[serde(alias = "chargeback")]
Chargeback,
}
#[derive(Deserialize, Debug)]
pub struct Transaction {
#[serde(alias = "type")]
pub ty: TransactionType,
pub client: u16,
pub tx: u32,
#[serde(default)]
pub amount: f32,
}

View file

@ -1 +0,0 @@

View file

@ -1 +0,0 @@