1mod filter_definition;
12pub mod logic;
13pub mod posting;
14pub mod txn;
15
16pub use crate::filters::filter_definition::FilterDefZoned;
17pub use crate::filters::filter_definition::FilterDefinition;
18use jiff::tz::TimeZone;
19use rust_decimal::Decimal;
20use serde::{Deserialize, Serialize};
21use std::fmt::{Error, Formatter};
22
23use logic::TxnFilterAND;
24use logic::TxnFilterNOT;
25use logic::TxnFilterOR;
26
27use txn::TxnFilterBBoxLatLon;
28use txn::TxnFilterBBoxLatLonAlt;
29use txn::TxnFilterTxnCode;
30use txn::TxnFilterTxnComments;
31use txn::TxnFilterTxnDescription;
32use txn::TxnFilterTxnTSBegin;
33use txn::TxnFilterTxnTSEnd;
34use txn::TxnFilterTxnTags;
35use txn::TxnFilterTxnUUID;
36
37use posting::TxnFilterPostingAccount;
38use posting::TxnFilterPostingAmountEqual;
39use posting::TxnFilterPostingAmountGreater;
40use posting::TxnFilterPostingAmountLess;
41use posting::TxnFilterPostingComment;
42use posting::TxnFilterPostingCommodity;
43
44pub trait IndentDisplay {
47 fn i_fmt(&self, indent: &str, _tz: TimeZone, f: &mut Formatter<'_>) -> std::fmt::Result;
49}
50
51#[derive(Serialize, Deserialize, Clone, Debug)]
56pub enum TxnFilter {
57 #[doc(hidden)]
59 NullaryTRUE(NullaryTRUE),
60 #[doc(hidden)]
61 NullaryFALSE(NullaryFALSE),
62
63 #[doc(hidden)]
65 TxnFilterAND(TxnFilterAND),
66 #[doc(hidden)]
67 TxnFilterOR(TxnFilterOR),
68 #[doc(hidden)]
69 TxnFilterNOT(TxnFilterNOT),
70
71 #[doc(hidden)]
73 TxnFilterTxnTSBegin(TxnFilterTxnTSBegin),
74 #[doc(hidden)]
75 TxnFilterTxnTSEnd(TxnFilterTxnTSEnd),
76 #[doc(hidden)]
77 TxnFilterTxnCode(TxnFilterTxnCode),
78 #[doc(hidden)]
79 TxnFilterTxnDescription(TxnFilterTxnDescription),
80 #[doc(hidden)]
81 TxnFilterTxnUUID(TxnFilterTxnUUID),
82 #[doc(hidden)]
83 TxnFilterBBoxLatLon(TxnFilterBBoxLatLon),
84 #[doc(hidden)]
85 TxnFilterBBoxLatLonAlt(TxnFilterBBoxLatLonAlt),
86 #[doc(hidden)]
87 TxnFilterTxnTags(TxnFilterTxnTags),
88 #[doc(hidden)]
89 TxnFilterTxnComments(TxnFilterTxnComments),
90
91 #[doc(hidden)]
93 TxnFilterPostingAccount(TxnFilterPostingAccount),
94 #[doc(hidden)]
95 TxnFilterPostingComment(TxnFilterPostingComment),
96 #[doc(hidden)]
97 TxnFilterPostingAmountEqual(TxnFilterPostingAmountEqual),
98 #[doc(hidden)]
99 TxnFilterPostingAmountLess(TxnFilterPostingAmountLess),
100 #[doc(hidden)]
101 TxnFilterPostingAmountGreater(TxnFilterPostingAmountGreater),
102 #[doc(hidden)]
103 TxnFilterPostingCommodity(TxnFilterPostingCommodity),
104}
105
106impl IndentDisplay for TxnFilter {
114 fn i_fmt(&self, indent: &str, tz: TimeZone, f: &mut Formatter<'_>) -> std::fmt::Result {
115 match self {
116 TxnFilter::NullaryTRUE(tf) => tf.i_fmt(indent, tz, f),
118 TxnFilter::NullaryFALSE(tf) => tf.i_fmt(indent, tz, f),
119
120 TxnFilter::TxnFilterAND(tf) => tf.i_fmt(indent, tz, f),
122 TxnFilter::TxnFilterOR(tf) => tf.i_fmt(indent, tz, f),
123 TxnFilter::TxnFilterNOT(tf) => tf.i_fmt(indent, tz, f),
124
125 TxnFilter::TxnFilterTxnTSBegin(tf) => tf.i_fmt(indent, tz, f),
127 TxnFilter::TxnFilterTxnTSEnd(tf) => tf.i_fmt(indent, tz, f),
128 TxnFilter::TxnFilterTxnCode(tf) => tf.i_fmt(indent, tz, f),
129 TxnFilter::TxnFilterTxnDescription(tf) => tf.i_fmt(indent, tz, f),
130 TxnFilter::TxnFilterTxnUUID(tf) => tf.i_fmt(indent, tz, f),
131 TxnFilter::TxnFilterBBoxLatLon(tf) => tf.i_fmt(indent, tz, f),
132 TxnFilter::TxnFilterBBoxLatLonAlt(tf) => tf.i_fmt(indent, tz, f),
133 TxnFilter::TxnFilterTxnTags(tf) => tf.i_fmt(indent, tz, f),
134 TxnFilter::TxnFilterTxnComments(tf) => tf.i_fmt(indent, tz, f),
135
136 TxnFilter::TxnFilterPostingAccount(tf) => tf.i_fmt(indent, tz, f),
138 TxnFilter::TxnFilterPostingComment(tf) => tf.i_fmt(indent, tz, f),
139 TxnFilter::TxnFilterPostingAmountEqual(tf) => tf.i_fmt(indent, tz, f),
140 TxnFilter::TxnFilterPostingAmountLess(tf) => tf.i_fmt(indent, tz, f),
141 TxnFilter::TxnFilterPostingAmountGreater(tf) => tf.i_fmt(indent, tz, f),
142 TxnFilter::TxnFilterPostingCommodity(tf) => tf.i_fmt(indent, tz, f),
143 }
144 }
145}
146
147#[derive(Serialize, Deserialize, Clone, Debug)]
149pub struct NullaryTRUE {}
150
151impl IndentDisplay for NullaryTRUE {
152 fn i_fmt(&self, indent: &str, _tz: TimeZone, f: &mut Formatter<'_>) -> std::fmt::Result {
153 writeln!(f, "{indent}All pass")
154 }
155}
156
157#[derive(Serialize, Deserialize, Clone, Debug)]
159pub struct NullaryFALSE {}
160
161impl IndentDisplay for NullaryFALSE {
162 fn i_fmt(&self, indent: &str, _tz: TimeZone, f: &mut Formatter<'_>) -> std::fmt::Result {
163 writeln!(f, "{indent}None pass")
164 }
165}
166
167fn logic_filter_indent_fmt(
168 op: &str,
169 indent: &str,
170 tz: TimeZone,
171 filters: &[TxnFilter],
172 f: &mut Formatter<'_>,
173) -> std::fmt::Result {
174 let new_ident = format!("{indent} ");
175
176 writeln!(f, "{indent}{op}")?;
177 let result: Result<Vec<()>, Error> = filters
178 .iter()
179 .map(|tf| tf.i_fmt(&new_ident, tz.clone(), f))
180 .collect();
181
182 match result {
183 Ok(_) => Ok(()),
184 Err(err) => Err(err),
185 }
186}
187
188fn posting_filter_indent_fmt(
189 indent: &str,
190 target: &str,
191 regex: &str,
192 op: &str,
193 amount: &Decimal,
194 f: &mut Formatter<'_>,
195) -> std::fmt::Result {
196 let my_indent = format!("{indent} ");
197 writeln!(f, "{indent}{target}")?;
198 writeln!(f, "{my_indent}account: \"{regex}\"")?;
199 writeln!(f, "{my_indent}amount {op} {amount}")
200}