1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use std::{collections::BTreeMap, fmt};
#[derive(Clone, PartialEq, Default)]
pub struct Sum<Unit, Number>(pub(crate) BTreeMap<Unit, Number>)
where
Unit: Ord;
impl<Unit, Number> Sum<Unit, Number>
where
Unit: Ord,
{
pub fn set_amount_for_unit(&mut self, amount: Number, unit_: Unit) {
self.0.insert(unit_, amount);
}
pub fn amounts(&self) -> impl Iterator<Item = (&Unit, &Number)> {
self.0.iter()
}
pub fn unit_amount(&self, unit: &Unit) -> Option<&Number> {
self.0.get(unit)
}
}
impl<Unit, Number> fmt::Debug for Sum<Unit, Number>
where
Unit: Ord + fmt::Debug,
Number: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Sum(")?;
f.debug_map().entries(self.0.iter()).finish()?;
f.write_str(")")
}
}
#[cfg(test)]
mod test {
use super::Sum;
use maplit::btreemap;
#[test]
fn default() {
let actual = Sum::<&str, usize>::default();
let expected = Sum(btreemap! {});
assert_eq!(actual, expected);
}
#[test]
fn from_entries() {
let thb = "THB";
let usd = "USD";
let actual = sum!(100, thb; 200, usd);
let expected = Sum(btreemap! {
thb => 100,
usd => 200,
});
assert_eq!(actual, expected);
}
#[test]
fn set_amount_for_unit() {
let unit = "USD";
let mut actual = Sum::default();
actual.set_amount_for_unit(3, unit);
let expected = Sum(btreemap! { unit => 3 });
assert_eq!(actual, expected);
}
#[test]
fn unit_amount() {
let unit = "USD";
let amount = 123;
let mut sum = Sum::default();
sum.set_amount_for_unit(amount, unit);
let actual = sum.unit_amount(&unit).unwrap();
assert_eq!(actual, &amount);
}
#[test]
fn amounts() {
let thb = "THB";
let usd = "USD";
let sum = sum!(3, thb; 10, usd);
let actual = sum.amounts().collect::<Vec<_>>();
let expected = vec![(&thb, &3), (&usd, &10)];
assert_eq!(actual, expected);
}
#[test]
fn fmt_debug() {
let usd = "USD";
let amount_usd = 76;
let thb = "THB";
let amount_thb = 45;
let sum = sum!(amount_usd, usd; amount_thb, thb);
let actual = format!("{:?}", sum);
let expected = format!(
"Sum({{{:?}: {:?}, {:?}: {:?}}})",
thb, amount_thb, usd, amount_usd
);
assert_eq!(actual, expected);
}
}