use rustledger_core::Directive;
use rustledger_core::intern::{InternedStr, StringInterner};
use rustledger_core::{IncompleteAmount, PriceAnnotation};
use rustledger_parser::Spanned;
pub fn reintern_directives(directives: &mut [Spanned<Directive>]) -> usize {
let mut interner = StringInterner::with_capacity(1024);
let mut dedup_count = 0;
for spanned in directives.iter_mut() {
dedup_count += reintern_directive(&mut spanned.value, &mut interner);
}
dedup_count
}
pub fn reintern_plain_directives(directives: &mut [Directive]) -> usize {
let mut interner = StringInterner::with_capacity(1024);
let mut dedup_count = 0;
for directive in directives.iter_mut() {
dedup_count += reintern_directive(directive, &mut interner);
}
dedup_count
}
fn do_intern(s: &mut InternedStr, interner: &mut StringInterner) -> bool {
let (new, was_new) = interner.intern_with_status(s.as_str());
*s = new;
!was_new
}
fn intern_vec(v: &mut [InternedStr], interner: &mut StringInterner, dedup_count: &mut usize) {
for s in v.iter_mut() {
if do_intern(s, interner) {
*dedup_count += 1;
}
}
}
fn reintern_directive(directive: &mut Directive, interner: &mut StringInterner) -> usize {
let mut dedup_count = 0;
match directive {
Directive::Transaction(txn) => {
if let Some(ref mut payee) = txn.payee
&& do_intern(payee, interner)
{
dedup_count += 1;
}
if do_intern(&mut txn.narration, interner) {
dedup_count += 1;
}
intern_vec(&mut txn.tags, interner, &mut dedup_count);
intern_vec(&mut txn.links, interner, &mut dedup_count);
for posting in &mut txn.postings {
if do_intern(&mut posting.account, interner) {
dedup_count += 1;
}
if let Some(ref mut units) = posting.units {
match units {
IncompleteAmount::Complete(amt) => {
if do_intern(&mut amt.currency, interner) {
dedup_count += 1;
}
}
IncompleteAmount::CurrencyOnly(cur) => {
if do_intern(cur, interner) {
dedup_count += 1;
}
}
IncompleteAmount::NumberOnly(_) => {}
}
}
if let Some(ref mut cost) = posting.cost
&& let Some(ref mut cur) = cost.currency
&& do_intern(cur, interner)
{
dedup_count += 1;
}
if let Some(ref mut price) = posting.price {
match price {
PriceAnnotation::Unit(amt) | PriceAnnotation::Total(amt) => {
if do_intern(&mut amt.currency, interner) {
dedup_count += 1;
}
}
PriceAnnotation::UnitIncomplete(inc)
| PriceAnnotation::TotalIncomplete(inc) => match inc {
IncompleteAmount::Complete(amt) => {
if do_intern(&mut amt.currency, interner) {
dedup_count += 1;
}
}
IncompleteAmount::CurrencyOnly(cur) => {
if do_intern(cur, interner) {
dedup_count += 1;
}
}
IncompleteAmount::NumberOnly(_) => {}
},
PriceAnnotation::UnitEmpty | PriceAnnotation::TotalEmpty => {}
}
}
}
}
Directive::Balance(bal) => {
if do_intern(&mut bal.account, interner) {
dedup_count += 1;
}
if do_intern(&mut bal.amount.currency, interner) {
dedup_count += 1;
}
}
Directive::Open(open) => {
if do_intern(&mut open.account, interner) {
dedup_count += 1;
}
intern_vec(&mut open.currencies, interner, &mut dedup_count);
}
Directive::Close(close) => {
if do_intern(&mut close.account, interner) {
dedup_count += 1;
}
}
Directive::Commodity(comm) => {
if do_intern(&mut comm.currency, interner) {
dedup_count += 1;
}
}
Directive::Pad(pad) => {
if do_intern(&mut pad.account, interner) {
dedup_count += 1;
}
if do_intern(&mut pad.source_account, interner) {
dedup_count += 1;
}
}
Directive::Note(note) => {
if do_intern(&mut note.account, interner) {
dedup_count += 1;
}
}
Directive::Document(doc) => {
if do_intern(&mut doc.account, interner) {
dedup_count += 1;
}
intern_vec(&mut doc.tags, interner, &mut dedup_count);
intern_vec(&mut doc.links, interner, &mut dedup_count);
}
Directive::Price(price) => {
if do_intern(&mut price.currency, interner) {
dedup_count += 1;
}
if do_intern(&mut price.amount.currency, interner) {
dedup_count += 1;
}
}
Directive::Event(_) | Directive::Query(_) | Directive::Custom(_) => {
}
}
dedup_count
}