123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- use itertools::Itertools;
- use super::{AccountName, Datestamp, Decimal, Spanned, UnitName};
- mod parse;
- pub use parse::parse_ledger;
- mod print;
- pub use print::print_ledger;
- #[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
- pub struct Change {
- pub account: Spanned<AccountName>,
- pub amount: Spanned<Decimal>,
- pub balance: Option<Spanned<Decimal>>,
- pub unit: Spanned<UnitName>,
- }
- #[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
- pub struct Transaction {
- pub datestamp: Datestamp,
- pub title: Option<String>,
- pub annotations: Vec<String>,
- pub changes: Vec<Spanned<Change>>,
- }
- impl Transaction {
- pub fn modifies(&self, account: AccountName) -> bool {
- self.changes.iter().any(|b| b.account.as_ref() == &account)
- }
- pub fn change_for(&self, account: AccountName) -> Option<&Spanned<Change>> {
- self.changes.iter().find(|b| b.account.as_ref() == &account)
- }
- pub fn split_changes(
- &self,
- account: AccountName,
- ) -> Option<(&Spanned<Change>, impl Iterator<Item = &Spanned<Change>>)> {
- let index = self
- .changes
- .iter()
- .position(|b| b.account.as_ref() == &account)?;
- Some((
- &self.changes[index],
- self.changes[0..index]
- .iter()
- .chain(self.changes[index + 1..].iter()),
- ))
- }
- pub fn is_mono_unit(&self) -> bool {
- self.changes.iter().unique_by(|b| *b.unit).count() == 1
- }
- pub fn mono_unit(&self) -> Option<UnitName> {
- let mut it = self.changes.iter().unique_by(|b| *b.unit);
- let uniq = it.next()?;
- it.next().is_none().then_some(*uniq.unit)
- }
- pub fn get_annotation(&self, label: &str) -> Option<&str> {
- for anno in self.annotations.iter() {
- if let Some(body) = anno.strip_prefix(label) {
- return Some(body)
- }
- }
- None
- }
- }
- #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
- pub enum LedgerEntry {
- Transaction(Spanned<Transaction>),
- Comment(Spanned<String>),
- }
- impl LedgerEntry {
- pub fn as_transaction(&self) -> Option<&Spanned<Transaction>> {
- match self {
- Self::Transaction(tx) => Some(tx),
- _ => None,
- }
- }
- pub fn as_transaction_mut(&mut self) -> Option<&mut Spanned<Transaction>> {
- match self {
- Self::Transaction(tx) => Some(tx),
- _ => None,
- }
- }
- pub fn span(&self) -> super::Span {
- match self {
- Self::Transaction(ts) => ts.span(),
- Self::Comment(c) => c.span(),
- }
- }
- }
|