whisky_common/data/
value.rs1use serde::{Deserialize, Serialize};
2
3use crate::models::Asset;
4use std::collections::HashMap;
5
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
7pub struct Value(pub HashMap<String, u64>);
8
9impl Value {
10 pub fn new() -> Self {
11 Value(HashMap::new())
12 }
13
14 pub fn from_asset(asset: &Asset) -> Self {
15 let mut asset_map = HashMap::new();
16 asset_map.insert(
17 Value::sanitize_unit(&asset.unit()),
18 asset.quantity().parse::<u64>().unwrap(),
19 );
20 Value(asset_map)
21 }
22
23 pub fn from_asset_vec(assets: &[Asset]) -> Self {
24 let mut asset_map = HashMap::new();
25 for asset in assets {
26 let current_value = asset_map
27 .entry(Value::sanitize_unit(&asset.unit()))
28 .or_insert(0);
29 *current_value += asset.quantity().parse::<u64>().unwrap();
30 }
31 Value(asset_map)
32 }
33
34 pub fn add_asset(&mut self, unit: &str, quantity: u64) -> &mut Self {
35 let current_value = self.0.entry(Value::sanitize_unit(unit)).or_insert(0);
36 *current_value += quantity;
37 self
38 }
39
40 pub fn add_assets(&mut self, assets: &[Asset]) -> &mut Self {
41 for asset in assets {
42 self.add_asset(&asset.unit(), asset.quantity().parse::<u64>().unwrap());
43 }
44 self
45 }
46
47 pub fn merge(&mut self, other: &Value) -> &mut Self {
48 for (key, value) in other.0.clone() {
49 let current_value = self.0.entry(Value::sanitize_unit(&key)).or_insert(0);
50 *current_value += value;
51 }
52 self
53 }
54
55 pub fn negate_asset(&mut self, unit: &str, quantity: u64) -> &mut Self {
56 let current_value = self.0.entry(Value::sanitize_unit(unit)).or_insert(0);
57 if *current_value <= quantity {
58 self.0.remove(unit);
59 } else {
60 *current_value -= quantity;
61 };
62 self
63 }
64
65 pub fn negate_assets(&mut self, other: &[Asset]) -> &mut Self {
66 for asset in other {
67 self.negate_asset(&asset.unit(), asset.quantity().parse::<u64>().unwrap());
68 }
69 self
70 }
71
72 pub fn negate_value(&mut self, other: &Value) -> &mut Self {
73 for (key, value) in other.0.clone() {
74 let unit = Value::sanitize_unit(&key);
75 let current_value = self.0.entry(unit.clone()).or_insert(0);
76 if *current_value <= value {
77 self.0.remove(&unit);
78 } else {
79 *current_value -= value;
80 }
81 }
82 self
83 }
84
85 pub fn to_asset_vec(&self) -> Vec<Asset> {
86 let mut assets = vec![];
87 for (unit, quantity) in &self.0 {
88 assets.push(Asset::new(Value::sanitize_unit(unit), quantity.to_string()));
89 }
90 assets
91 }
92
93 pub fn get(&self, key: &str) -> u64 {
95 let key = if key.is_empty() { "lovelace" } else { key };
96 match self.0.get(key) {
97 Some(value) => *value,
98 None => 0,
99 }
100 }
101
102 pub fn keys(&self) -> Vec<String> {
103 self.0.keys().cloned().collect()
104 }
105
106 pub fn len(&self) -> usize {
107 self.0.len()
108 }
109
110 pub fn geq(&self, other: &Value) -> bool {
112 for (key, value) in &other.0 {
113 if self
114 .0
115 .get(&Value::sanitize_unit(key))
116 .is_some_and(|v| v < value)
117 {
118 return false;
119 }
120 }
121 true
122 }
123
124 pub fn leq(&self, other: &Value) -> bool {
125 for (key, value) in &other.0 {
126 if self
127 .0
128 .get(&Value::sanitize_unit(key))
129 .is_some_and(|v| v > value)
130 {
131 return false;
132 }
133 }
134 true
135 }
136
137 pub fn is_empty(&self) -> bool {
138 self.0.is_empty()
139 }
140
141 pub fn sanitize_unit(unit: &str) -> String {
142 if unit.is_empty() {
143 "lovelace".to_string()
144 } else {
145 unit.to_string()
146 }
147 }
148}
149
150impl Default for Value {
151 fn default() -> Self {
152 Value::new()
153 }
154}