use std::collections::{HashMap, HashSet}; use std::sync::{RwLock, RwLockReadGuard}; use crate::account::{Account, AccountError}; #[derive(Default)] pub struct Bank { pub accounts: HashMap>, } impl Bank { pub fn new() -> Self { Default::default() } pub fn account_action Result, R>( bank: RwLockReadGuard<'_, Bank>, nr: &str, action: F, ) -> Result { match bank.accounts.get(nr) { None => Err(AccountError::NotFound), Some(account) => { let mut account = account.write().unwrap(); action(&mut account) } } } pub fn account_numbers(&self) -> HashSet { self.accounts .iter() .filter(|(_, acc)| acc.read().unwrap().is_active) .map(|(_, acc)| acc.read().unwrap().number.clone()) .collect() } pub fn create_account(&mut self, owner: String) -> String { let acc = Account { owner, ..Default::default() }; let nr = acc.number.clone(); self.accounts.insert(acc.number.clone(), RwLock::new(acc)); nr } pub fn transfer( &self, from: &mut Account, to: &mut Account, amount: f64, ) -> Result<(), AccountError> { from.withdraw(amount)?; to.deposit(amount)?; Ok(()) } } #[cfg(test)] mod tests { use super::*; #[test] fn creation() { let mut bank = Bank::new(); let nr = bank.create_account("Rohaja".into()); assert!(bank.accounts.get(&nr).is_some()); assert!(bank.accounts.get("thisisnotauuid").is_none()); } #[test] fn transfer() { let mut bank = Bank::new(); let nr1 = bank.create_account("Rohaja".into()); let nr2 = bank.create_account("Hal".into()); { let mut acc1 = bank.accounts.get(&nr1).unwrap().write().unwrap(); let mut acc2 = bank.accounts.get(&nr2).unwrap().write().unwrap(); let result = bank.transfer(&mut acc1, &mut acc2, 100_f64); assert!(result.is_err()); acc1.deposit(100_f64).unwrap(); let result = bank.transfer(&mut acc1, &mut acc2, 50_f64); assert!(result.is_ok()); assert_eq!(acc2.balance, 50_f64); let result = bank.transfer(&mut acc1, &mut acc2, -50_f64); assert!(result.is_err()); acc2.withdraw(50_f64).unwrap(); assert!(acc2.passivate()); let result = bank.transfer(&mut acc1, &mut acc2, 50_f64); assert!(result.is_err()); } assert_eq!(1, bank.account_numbers().len()); } }