okane_core/report/
context.rs1use bumpalo::Bump;
2
3use super::{
4 commodity::CommodityStore,
5 intern::{FromInterned, InternStore, InternedStr, StoredValue},
6};
7
8#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
10pub struct Account<'arena>(InternedStr<'arena>);
11
12impl<'arena> FromInterned<'arena> for Account<'arena> {
13 fn from_interned(v: InternedStr<'arena>) -> Self {
14 Self(v)
15 }
16
17 fn as_interned(&self) -> InternedStr<'arena> {
18 self.0
19 }
20}
21
22impl<'arena> Account<'arena> {
23 pub fn as_str(&self) -> &'arena str {
25 self.0.as_str()
26 }
27}
28
29pub(super) type AccountStore<'arena> = InternStore<'arena, Account<'arena>>;
31pub struct ReportContext<'ctx> {
33 pub(super) arena: &'ctx Bump,
34 pub(super) accounts: AccountStore<'ctx>,
35 pub(super) commodities: CommodityStore<'ctx>,
36}
37
38impl<'ctx> ReportContext<'ctx> {
39 pub fn new(arena: &'ctx Bump) -> Self {
41 let accounts = AccountStore::new(arena);
42 let commodities = CommodityStore::new(arena);
43 Self {
44 arena,
45 accounts,
46 commodities,
47 }
48 }
49
50 pub fn all_accounts(&self) -> Vec<Account<'ctx>> {
52 let mut r: Vec<Account<'ctx>> = self
53 .accounts
54 .iter()
55 .filter_map(|x| match x {
56 StoredValue::Canonical(x) => Some(x),
57 StoredValue::Alias { .. } => None,
58 })
59 .collect();
60 r.sort_unstable_by_key(|x| x.as_str());
61 r
62 }
63
64 pub fn account(&self, value: &str) -> Option<Account<'ctx>> {
66 self.accounts.resolve(value)
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use pretty_assertions::assert_eq;
73
74 use super::*;
75
76 #[test]
77 fn context_all_accounts() {
78 let arena = Bump::new();
79 let mut ctx = ReportContext::new(&arena);
80 let want = vec![
81 ctx.accounts.ensure("Account 1"),
82 ctx.accounts.ensure("Account 2"),
83 ctx.accounts.ensure("Account 2:Sub account"),
84 ctx.accounts.ensure("Account 3"),
85 ctx.accounts.ensure("資産:りんご"),
88 ctx.accounts.ensure("資産:バナナ"),
89 ctx.accounts.ensure("資産:吉祥寺"),
90 ];
91
92 let got = ctx.all_accounts();
93
94 assert_eq!(want, got);
95 }
96
97 #[test]
98 fn context_sccount() {
99 let arena = Bump::new();
100 let mut ctx = ReportContext::new(&arena);
101 let a1 = ctx.accounts.ensure("Account 1");
102 let a3 = ctx.accounts.ensure("Account 3");
103
104 assert_eq!(Some(a1), ctx.account("Account 1"));
105 assert_eq!(None, ctx.account("Account 2"));
106 assert_eq!(Some(a3), ctx.account("Account 3"));
107 }
108}