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;
53}
54
55#[derive(Serialize, Deserialize, Clone, Debug)]
60pub enum TxnFilter {
61 #[doc(hidden)]
63 NullaryTRUE(NullaryTRUE),
64 #[doc(hidden)]
65 NullaryFALSE(NullaryFALSE),
66
67 #[doc(hidden)]
69 TxnFilterAND(TxnFilterAND),
70 #[doc(hidden)]
71 TxnFilterOR(TxnFilterOR),
72 #[doc(hidden)]
73 TxnFilterNOT(TxnFilterNOT),
74
75 #[doc(hidden)]
77 TxnFilterTxnTSBegin(TxnFilterTxnTSBegin),
78 #[doc(hidden)]
79 TxnFilterTxnTSEnd(TxnFilterTxnTSEnd),
80 #[doc(hidden)]
81 TxnFilterTxnCode(TxnFilterTxnCode),
82 #[doc(hidden)]
83 TxnFilterTxnDescription(TxnFilterTxnDescription),
84 #[doc(hidden)]
85 TxnFilterTxnUUID(TxnFilterTxnUUID),
86 #[doc(hidden)]
87 TxnFilterBBoxLatLon(TxnFilterBBoxLatLon),
88 #[doc(hidden)]
89 TxnFilterBBoxLatLonAlt(TxnFilterBBoxLatLonAlt),
90 #[doc(hidden)]
91 TxnFilterTxnTags(TxnFilterTxnTags),
92 #[doc(hidden)]
93 TxnFilterTxnComments(TxnFilterTxnComments),
94
95 #[doc(hidden)]
97 TxnFilterPostingAccount(TxnFilterPostingAccount),
98 #[doc(hidden)]
99 TxnFilterPostingComment(TxnFilterPostingComment),
100 #[doc(hidden)]
101 TxnFilterPostingAmountEqual(TxnFilterPostingAmountEqual),
102 #[doc(hidden)]
103 TxnFilterPostingAmountLess(TxnFilterPostingAmountLess),
104 #[doc(hidden)]
105 TxnFilterPostingAmountGreater(TxnFilterPostingAmountGreater),
106 #[doc(hidden)]
107 TxnFilterPostingCommodity(TxnFilterPostingCommodity),
108}
109
110impl IndentDisplay for TxnFilter {
118 fn i_fmt(&self, indent: &str, tz: TimeZone, f: &mut Formatter<'_>) -> std::fmt::Result {
119 match self {
120 TxnFilter::NullaryTRUE(tf) => tf.i_fmt(indent, tz, f),
122 TxnFilter::NullaryFALSE(tf) => tf.i_fmt(indent, tz, f),
123
124 TxnFilter::TxnFilterAND(tf) => tf.i_fmt(indent, tz, f),
126 TxnFilter::TxnFilterOR(tf) => tf.i_fmt(indent, tz, f),
127 TxnFilter::TxnFilterNOT(tf) => tf.i_fmt(indent, tz, f),
128
129 TxnFilter::TxnFilterTxnTSBegin(tf) => tf.i_fmt(indent, tz, f),
131 TxnFilter::TxnFilterTxnTSEnd(tf) => tf.i_fmt(indent, tz, f),
132 TxnFilter::TxnFilterTxnCode(tf) => tf.i_fmt(indent, tz, f),
133 TxnFilter::TxnFilterTxnDescription(tf) => tf.i_fmt(indent, tz, f),
134 TxnFilter::TxnFilterTxnUUID(tf) => tf.i_fmt(indent, tz, f),
135 TxnFilter::TxnFilterBBoxLatLon(tf) => tf.i_fmt(indent, tz, f),
136 TxnFilter::TxnFilterBBoxLatLonAlt(tf) => tf.i_fmt(indent, tz, f),
137 TxnFilter::TxnFilterTxnTags(tf) => tf.i_fmt(indent, tz, f),
138 TxnFilter::TxnFilterTxnComments(tf) => tf.i_fmt(indent, tz, f),
139
140 TxnFilter::TxnFilterPostingAccount(tf) => tf.i_fmt(indent, tz, f),
142 TxnFilter::TxnFilterPostingComment(tf) => tf.i_fmt(indent, tz, f),
143 TxnFilter::TxnFilterPostingAmountEqual(tf) => tf.i_fmt(indent, tz, f),
144 TxnFilter::TxnFilterPostingAmountLess(tf) => tf.i_fmt(indent, tz, f),
145 TxnFilter::TxnFilterPostingAmountGreater(tf) => tf.i_fmt(indent, tz, f),
146 TxnFilter::TxnFilterPostingCommodity(tf) => tf.i_fmt(indent, tz, f),
147 }
148 }
149}
150
151#[derive(Serialize, Deserialize, Clone, Debug)]
153pub struct NullaryTRUE {}
154
155impl IndentDisplay for NullaryTRUE {
156 fn i_fmt(&self, indent: &str, _tz: TimeZone, f: &mut Formatter<'_>) -> std::fmt::Result {
157 writeln!(f, "{indent}All pass")
158 }
159}
160
161#[derive(Serialize, Deserialize, Clone, Debug)]
163pub struct NullaryFALSE {}
164
165impl IndentDisplay for NullaryFALSE {
166 fn i_fmt(&self, indent: &str, _tz: TimeZone, f: &mut Formatter<'_>) -> std::fmt::Result {
167 writeln!(f, "{indent}None pass")
168 }
169}
170
171#[allow(clippy::needless_pass_by_value)]
172fn logic_filter_indent_fmt(
173 op: &str,
174 indent: &str,
175 tz: TimeZone,
176 filters: &[TxnFilter],
177 f: &mut Formatter<'_>,
178) -> std::fmt::Result {
179 let new_ident = format!("{indent} ");
180
181 writeln!(f, "{indent}{op}")?;
182 let result: Result<Vec<()>, Error> = filters
183 .iter()
184 .map(|tf| tf.i_fmt(&new_ident, tz.clone(), f))
185 .collect();
186
187 match result {
188 Ok(_) => Ok(()),
189 Err(err) => Err(err),
190 }
191}
192
193fn posting_filter_indent_fmt(
194 indent: &str,
195 target: &str,
196 regex: &str,
197 op: &str,
198 amount: &Decimal,
199 f: &mut Formatter<'_>,
200) -> std::fmt::Result {
201 let my_indent = format!("{indent} ");
202 writeln!(f, "{indent}{target}")?;
203 writeln!(f, "{my_indent}account: \"{regex}\"")?;
204 writeln!(f, "{my_indent}amount {op} {amount}")
205}