1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
use std::io; use crate::model::*; pub trait Serializer { fn write<W>(&self, writer: &mut W, settings: &SerializerSettings) -> Result<(), io::Error> where W: io::Write; fn to_string_pretty(&self, settings: &SerializerSettings) -> String { let mut res = Vec::new(); self.write(&mut res, settings).unwrap(); return std::str::from_utf8(&res).unwrap().to_string(); } } pub struct SerializerSettings { indent: String, } impl SerializerSettings { pub fn new() -> Self { SerializerSettings::with_indent(" ") } pub fn with_indent(indent: &str) -> Self { SerializerSettings { indent: indent.to_string() } } } impl Serializer for Ledger { fn write<W>(&self, writer: &mut W, settings: &SerializerSettings) -> Result<(), io::Error> where W: io::Write { let mut first = true; for commodity_price in &self.commodity_prices { first = false; commodity_price.write(writer, settings)?; writeln!(writer)?; } for transaction in &self.transactions { if !first { writeln!(writer)?; } first = false; transaction.write(writer, settings)?; writeln!(writer)?; } Ok(()) } } impl Serializer for Transaction { fn write<W>(&self, writer: &mut W, settings: &SerializerSettings) -> Result<(), io::Error> where W: io::Write { write!(writer, "{}", self.date)?; if let Some(effective_date) = self.effective_date { write!(writer, "={}", effective_date)?; } if let Some(ref status) = self.status { write!(writer, " ")?; status.write(writer, settings)?; } if let Some(ref code) = self.code { write!(writer, " ({})", code)?; } if !self.description.is_empty() { write!(writer, " {}", self.description)?; } if let Some(ref comment) = self.comment { for comment in comment.split("\n") { write!(writer, "\n{}; {}", settings.indent, comment)?; } } for posting in &self.postings { write!(writer, "\n{}", settings.indent)?; posting.write(writer, settings)?; } Ok(()) } } impl Serializer for TransactionStatus { fn write<W>(&self, writer: &mut W, _settings: &SerializerSettings) -> Result<(), io::Error> where W: io::Write { match self { TransactionStatus::Pending => write!(writer, "!"), TransactionStatus::Cleared => write!(writer, "*"), } } } impl Serializer for Posting { fn write<W>(&self, writer: &mut W, settings: &SerializerSettings) -> Result<(), io::Error> where W: io::Write { if let Some(ref status) = self.status { status.write(writer, settings)?; write!(writer, " ")?; } write!(writer, "{}", self.account)?; if let Some(ref amount) = self.amount { write!(writer, "{}", settings.indent)?; amount.write(writer, settings)?; } if let Some(ref balance) = self.balance { write!(writer, " = ")?; balance.write(writer, settings)?; } if let Some(ref comment) = self.comment { for comment in comment.split("\n") { write!(writer, "\n{}; {}", settings.indent, comment)?; } } Ok(()) } } impl Serializer for Amount { fn write<W>(&self, writer: &mut W, _settings: &SerializerSettings) -> Result<(), io::Error> where W: io::Write { match self.commodity.position { CommodityPosition::Left => write!(writer, "{}{}", self.commodity.name, self.quantity), CommodityPosition::Right => write!(writer, "{} {}", self.quantity, self.commodity.name), } } } impl Serializer for Balance { fn write<W>(&self, writer: &mut W, settings: &SerializerSettings) -> Result<(), io::Error> where W: io::Write { match self { Balance::Zero => write!(writer, "0"), Balance::Amount(ref balance) => balance.write(writer, settings), } } } impl Serializer for CommodityPrice { fn write<W>(&self, writer: &mut W, settings: &SerializerSettings) -> Result<(), io::Error> where W: io::Write { write!( writer, "P {} {} ", self.datetime, self.commodity_name )?; self.amount.write(writer, settings)?; Ok(()) } }