use std::ops::{Add, Sub};
use candid::CandidType;
use ex3_serde::bincode;
use ic_stable_structures::{storable::Bound, Storable};
use serde::{Deserialize, Serialize};
use crate::{AssetAmount, CandidAssetAmount};
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)]
pub enum BalanceChanged {
Increase(AssetAmount),
Decrease(AssetAmount),
}
impl Storable for BalanceChanged {
fn to_bytes(&self) -> std::borrow::Cow<[u8]> {
bincode::serialize(self).unwrap().into()
}
fn from_bytes(bytes: std::borrow::Cow<[u8]>) -> Self {
bincode::deserialize(bytes.as_ref()).unwrap()
}
const BOUND: Bound = Bound::Bounded {
max_size: 48,
is_fixed_size: false,
};
}
#[derive(Debug, Clone, Deserialize, CandidType)]
pub enum CandidBalanceChanged {
Increase(CandidAssetAmount),
Decrease(CandidAssetAmount),
}
impl BalanceChanged {
pub fn merge(self, other: Self) -> Self {
match (self, other) {
(BalanceChanged::Increase(a), BalanceChanged::Increase(b)) => {
BalanceChanged::Increase(a.add(b))
}
(BalanceChanged::Decrease(a), BalanceChanged::Decrease(b)) => {
BalanceChanged::Decrease(a.add(b))
}
(BalanceChanged::Increase(a), BalanceChanged::Decrease(b)) => {
if a >= b {
BalanceChanged::Increase(a.sub(b))
} else {
BalanceChanged::Decrease(b.sub(a))
}
}
(BalanceChanged::Decrease(a), BalanceChanged::Increase(b)) => {
if a >= b {
BalanceChanged::Decrease(a.sub(b))
} else {
BalanceChanged::Increase(b.sub(a))
}
}
}
}
}
impl From<CandidBalanceChanged> for BalanceChanged {
fn from(candid_balance_changed: CandidBalanceChanged) -> Self {
match candid_balance_changed {
CandidBalanceChanged::Increase(candid_asset_amount) => {
BalanceChanged::Increase(candid_asset_amount.into())
}
CandidBalanceChanged::Decrease(candid_asset_amount) => {
BalanceChanged::Decrease(candid_asset_amount.into())
}
}
}
}
impl From<BalanceChanged> for CandidBalanceChanged {
fn from(balance_changed: BalanceChanged) -> Self {
match balance_changed {
BalanceChanged::Increase(asset_amount) => {
CandidBalanceChanged::Increase(asset_amount.into())
}
BalanceChanged::Decrease(asset_amount) => {
CandidBalanceChanged::Decrease(asset_amount.into())
}
}
}
}
#[cfg(test)]
mod tests {
use super::BalanceChanged;
use ic_stable_structures::storable::Storable;
#[test]
fn test_storable_for_balance_changed() {
let balance_changed = BalanceChanged::Increase(u128::MAX.into());
let bytes = balance_changed.to_bytes();
assert!(bytes.len() <= 48);
let balance_changed2 = BalanceChanged::from_bytes(bytes);
assert_eq!(balance_changed, balance_changed2);
}
}