oxygengine_overworld/resources/
bank.rs1use crate::resources::market::Currency;
2use oxygengine_core::id::ID;
3use std::collections::HashMap;
4
5pub type BankAccountId = ID<BankAccount<()>>;
6
7#[derive(Debug, Clone)]
8pub enum BankError<T>
9where
10 T: Currency,
11{
12 AccountDoesNotExists(BankAccountId),
13 CouldNotDeposit(BankAccountId, T),
14 CouldNotWithdraw(BankAccountId, T),
15 CouldNotTransfer(BankAccountId, BankAccountId, T),
16}
17
18#[derive(Debug, Default, Clone)]
19pub struct BankAccount<T>
20where
21 T: Currency + std::fmt::Debug + Default + Clone + Send + Sync,
22{
23 pub value: T,
24}
25
26#[derive(Debug, Clone)]
27pub struct Bank<T>
28where
29 T: Currency + std::fmt::Debug + Default + Clone + Send + Sync,
30{
31 accounts: HashMap<BankAccountId, BankAccount<T>>,
32}
33
34impl<T> Default for Bank<T>
35where
36 T: Currency + std::fmt::Debug + Default + Clone + Send + Sync,
37{
38 fn default() -> Self {
39 Self {
40 accounts: Default::default(),
41 }
42 }
43}
44
45impl<T> Bank<T>
46where
47 T: Currency + std::fmt::Debug + Default + Clone + Send + Sync,
48{
49 pub fn create_account(&mut self) -> BankAccountId {
50 let id = BankAccountId::new();
51 self.accounts.insert(id, Default::default());
52 id
53 }
54
55 pub fn remove_account(&mut self, id: BankAccountId) -> Result<T, BankError<T>> {
56 match self.accounts.remove(&id) {
57 Some(account) => Ok(account.value),
58 None => Err(BankError::AccountDoesNotExists(id)),
59 }
60 }
61
62 pub fn accounts(&self) -> impl Iterator<Item = (BankAccountId, &BankAccount<T>)> {
63 self.accounts.iter().map(|(id, account)| (*id, account))
64 }
65
66 pub fn deposit(&mut self, id: BankAccountId, value: T) -> Result<(), BankError<T>> {
67 match self.accounts.get_mut(&id) {
68 Some(account) => match account.value.accumulate(value) {
69 Ok(value) => {
70 account.value = value;
71 Ok(())
72 }
73 Err(_) => Err(BankError::CouldNotDeposit(id, value)),
74 },
75 None => Err(BankError::AccountDoesNotExists(id)),
76 }
77 }
78
79 pub fn withdraw(&mut self, id: BankAccountId, value: T) -> Result<T, BankError<T>> {
80 match self.accounts.get_mut(&id) {
81 Some(account) => match account.value.take(value) {
82 Ok((left, taken)) => {
83 account.value = left;
84 Ok(taken)
85 }
86 Err(_) => Err(BankError::CouldNotDeposit(id, value)),
87 },
88 None => Err(BankError::AccountDoesNotExists(id)),
89 }
90 }
91
92 pub fn transfer(
93 &mut self,
94 from: BankAccountId,
95 to: BankAccountId,
96 value: T,
97 ) -> Result<(), BankError<T>> {
98 if from == to {
99 return Ok(());
100 }
101 let from_value = match self.accounts.get(&from) {
102 Some(from) => from.value,
103 None => return Err(BankError::AccountDoesNotExists(from)),
104 };
105 let to_value = match self.accounts.get(&to) {
106 Some(to) => to.value,
107 None => return Err(BankError::AccountDoesNotExists(to)),
108 };
109 let (from_value, to_value) = match from_value.exchange(to_value, value) {
110 Ok(result) => result,
111 Err(_) => return Err(BankError::CouldNotTransfer(from, to, value)),
112 };
113 self.accounts.get_mut(&from).unwrap().value = from_value;
114 self.accounts.get_mut(&to).unwrap().value = to_value;
115 Ok(())
116 }
117
118 pub fn batched_transfers<'a>(
119 &'a mut self,
120 iter: impl Iterator<Item = (BankAccountId, BankAccountId, T)> + 'a,
121 ) -> impl Iterator<Item = BankError<T>> + 'a {
122 iter.filter_map(|(from, to, value)| match self.transfer(from, to, value) {
123 Ok(_) => None,
124 Err(error) => Some(error),
125 })
126 }
127}