rustledger_plugin/native/plugins/
leaf_only.rs1use crate::types::{DirectiveData, PluginError, PluginInput, PluginOutput};
4
5use super::super::NativePlugin;
6
7pub struct LeafOnlyPlugin;
9
10impl NativePlugin for LeafOnlyPlugin {
11 fn name(&self) -> &'static str {
12 "leafonly"
13 }
14
15 fn description(&self) -> &'static str {
16 "Error on postings to non-leaf accounts"
17 }
18
19 fn process(&self, input: PluginInput) -> PluginOutput {
20 use std::collections::HashSet;
21
22 let mut all_accounts: HashSet<String> = HashSet::new();
24 for wrapper in &input.directives {
25 if let DirectiveData::Transaction(txn) = &wrapper.data {
26 for posting in &txn.postings {
27 all_accounts.insert(posting.account.clone());
28 }
29 }
30 }
31
32 let parent_accounts: HashSet<&String> = all_accounts
34 .iter()
35 .filter(|acc| {
36 all_accounts
37 .iter()
38 .any(|other| other != *acc && other.starts_with(&format!("{acc}:")))
39 })
40 .collect();
41
42 let mut errors = Vec::new();
44 for wrapper in &input.directives {
45 if let DirectiveData::Transaction(txn) = &wrapper.data {
46 for posting in &txn.postings {
47 if parent_accounts.contains(&posting.account) {
48 errors.push(PluginError::error(format!(
49 "Posting to non-leaf account '{}' - has child accounts",
50 posting.account
51 )));
52 }
53 }
54 }
55 }
56
57 PluginOutput {
58 directives: input.directives,
59 errors,
60 }
61 }
62}