1use crate::filters::{FilterDefZoned, FilterDefinition};
10use crate::metadata::Checksum;
11use crate::txn_ts;
12use jiff::Zoned;
13use jiff::tz::TimeZone;
14
15#[doc(hidden)]
16pub type MetadataItems = Vec<MetadataItem>;
17
18#[doc(hidden)]
19pub trait Text: std::fmt::Debug {
20 #[must_use]
22 fn text(&self, tz: TimeZone) -> Vec<String>;
23}
24
25#[doc(hidden)]
26#[derive(Debug, Clone)]
27pub enum MetadataItem {
28 #[doc(hidden)]
29 TxnSetChecksum(TxnSetChecksum),
30 #[doc(hidden)]
31 AccountSelectorChecksum(AccountSelectorChecksum),
32 #[doc(hidden)]
33 GitInputReference(GitInputReference),
34 #[doc(hidden)]
35 TxnFilterDescription(TxnFilterDescription),
36}
37
38impl MetadataItem {
39 pub const ITEM_PAD: usize = 15;
40}
41
42impl Text for MetadataItem {
43 fn text(&self, tz: TimeZone) -> Vec<String> {
44 match self {
45 Self::GitInputReference(gif) => gif.text(tz),
46 Self::TxnSetChecksum(tscs) => tscs.text(tz),
47 Self::AccountSelectorChecksum(asc) => asc.text(tz),
48 Self::TxnFilterDescription(tfd) => tfd.text(tz),
49 }
50 }
51}
52
53#[derive(Debug, Clone)]
55pub struct TxnSetChecksum {
56 pub size: usize,
58 pub hash: Checksum,
60}
61impl Text for TxnSetChecksum {
62 fn text(&self, _tz: TimeZone) -> Vec<String> {
63 let pad = MetadataItem::ITEM_PAD;
65 vec![
66 format!("Txn Set Checksum"),
67 format!("{:>pad$} : {}", self.hash.algorithm, &self.hash.value),
68 format!("{:>pad$} : {}", "Set size", self.size),
69 ]
70 }
71}
72
73#[derive(Debug, Clone)]
75pub struct AccountSelectorChecksum {
76 pub hash: Checksum,
78}
79impl Text for AccountSelectorChecksum {
80 fn text(&self, _tz: TimeZone) -> Vec<String> {
81 let pad = MetadataItem::ITEM_PAD;
83 vec![
84 format!("Account Selector Checksum"),
85 format!("{:>pad$} : {}", self.hash.algorithm, &self.hash.value),
86 ]
87 }
88}
89
90#[derive(Debug, Clone)]
92pub struct ReportTimezone {
93 pub timezone: String,
95}
96impl Text for ReportTimezone {
97 fn text(&self, _tz: TimeZone) -> Vec<String> {
98 let pad = MetadataItem::ITEM_PAD;
99 vec![
100 "Report Time Zone".to_string(),
101 format!("{:>pad$} : {}", "TZ name", &self.timezone),
102 ]
103 }
104}
105#[derive(Debug, Clone)]
108pub struct TxnFilterDescription {
109 #[doc(hidden)]
110 txn_filter_def: FilterDefinition,
111}
112
113impl TxnFilterDescription {
114 #[must_use]
117 pub fn from(tf: FilterDefinition) -> TxnFilterDescription {
118 TxnFilterDescription { txn_filter_def: tf }
119 }
120}
121impl Text for TxnFilterDescription {
122 fn text(&self, tz: TimeZone) -> Vec<String> {
123 format!(
126 "{}",
127 FilterDefZoned {
128 filt_def: &self.txn_filter_def,
129 tz
130 }
131 )
132 .trim_end()
133 .split("\n")
134 .map(String::from)
135 .collect::<Vec<String>>()
136 }
137}
138
139#[derive(Debug, Clone)]
142pub struct GitInputReference {
143 pub commit: String,
145 pub reference: Option<String>,
147 pub dir: String,
149 pub suffix: String,
151 pub message: String,
153}
154
155impl Text for GitInputReference {
156 fn text(&self, _tz: TimeZone) -> Vec<String> {
157 let pad = MetadataItem::ITEM_PAD;
158 vec![
159 format!("Git Storage"),
160 format!("{:>pad$} : {}", "commit", self.commit),
161 format!(
162 "{:>pad$} : {}",
163 "reference",
164 self.reference
165 .as_ref()
166 .unwrap_or(&"FIXED by commit".to_string())
167 ),
168 format!("{:>pad$} : {}", "directory", self.dir),
169 format!("{:>pad$} : .{}", "suffix", self.suffix),
170 format!("{:>pad$} : {}", "message", self.message.trim()),
171 ]
172 }
173}
174
175#[derive(Debug, Clone)]
177pub struct PriceRecord {
178 pub ts: Option<Zoned>,
180 pub source: String,
182 pub rate: Option<String>,
184 pub target: String,
186}
187impl Text for PriceRecord {
188 fn text(&self, tz: TimeZone) -> Vec<String> {
189 let pad = MetadataItem::ITEM_PAD;
190 vec![
191 format!(
192 "{:>pad$} : {}",
193 "Time",
194 self.ts.as_ref().map_or("At txn time".to_string(), |ts| {
195 txn_ts::as_tz_full(ts, tz)
196 })
197 ),
198 format!("{:>pad$} : {}", "Commodity", self.source),
199 format!(
200 "{:>pad$} : {} {}",
201 "Value",
202 self.rate.clone().map_or("-".to_string(), |v| v),
203 self.target
204 ),
205 ]
206 }
207}
208#[derive(Debug, Clone)]
210pub struct PriceRecords {
211 pub rates: Vec<PriceRecord>,
213}
214impl Text for PriceRecords {
215 fn text(&self, tz: TimeZone) -> Vec<String> {
216 let pad = MetadataItem::ITEM_PAD;
217
218 let mut txt = Vec::new();
219
220 if let Some(pr) = self.rates.first() {
221 txt.push("Commodity Prices".to_string());
222 txt.extend(pr.text(tz.clone()));
223
224 if self.rates.len() > 1 {
225 for pr in &self.rates[1..] {
226 txt.push(format!("{:>pad$} -", ""));
227 txt.extend(pr.text(tz.clone()));
228 }
229 }
230 }
231 txt
232 }
233}